mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
shape editing prototype for colliders
- does not handle vec3 params of shapes yet - does not create respective commands when releasing mouse button - added more supported shape types
This commit is contained in:
+487
-53
@@ -7,6 +7,7 @@ use crate::{
|
||||
core::{
|
||||
algebra::{Vector2, Vector3},
|
||||
color::Color,
|
||||
math::plane::Plane,
|
||||
pool::Handle,
|
||||
type_traits::prelude::*,
|
||||
Uuid,
|
||||
@@ -29,6 +30,7 @@ use crate::{
|
||||
};
|
||||
|
||||
enum ShapeGizmo {
|
||||
NonEditable,
|
||||
Cuboid {
|
||||
pos_x_handle: Handle<Node>,
|
||||
pos_y_handle: Handle<Node>,
|
||||
@@ -53,9 +55,23 @@ enum ShapeGizmo {
|
||||
radius_handle: Handle<Node>,
|
||||
half_height_handle: Handle<Node>,
|
||||
},
|
||||
Segment {
|
||||
begin_handle: Handle<Node>,
|
||||
end_handle: Handle<Node>,
|
||||
},
|
||||
Triangle {
|
||||
a_handle: Handle<Node>,
|
||||
b_handle: Handle<Node>,
|
||||
c_handle: Handle<Node>,
|
||||
},
|
||||
}
|
||||
|
||||
fn make_handle(scene: &mut Scene, position: Vector3<f32>, root: Handle<Node>) -> Handle<Node> {
|
||||
fn make_handle(
|
||||
scene: &mut Scene,
|
||||
position: Vector3<f32>,
|
||||
root: Handle<Node>,
|
||||
visible: bool,
|
||||
) -> Handle<Node> {
|
||||
let mut material = Material::standard_sprite();
|
||||
|
||||
material
|
||||
@@ -72,7 +88,7 @@ fn make_handle(scene: &mut Scene, position: Vector3<f32>, root: Handle<Node>) ->
|
||||
.with_local_position(position)
|
||||
.build(),
|
||||
)
|
||||
.with_visibility(false),
|
||||
.with_visibility(visible),
|
||||
)
|
||||
.with_material(MaterialResource::new_ok(ResourceKind::Embedded, material))
|
||||
.with_size(0.05)
|
||||
@@ -85,7 +101,7 @@ fn make_handle(scene: &mut Scene, position: Vector3<f32>, root: Handle<Node>) ->
|
||||
}
|
||||
|
||||
impl ShapeGizmo {
|
||||
fn try_create(
|
||||
fn create(
|
||||
shape: ColliderShape,
|
||||
center: Vector3<f32>,
|
||||
side: Vector3<f32>,
|
||||
@@ -93,71 +109,102 @@ impl ShapeGizmo {
|
||||
look: Vector3<f32>,
|
||||
scene: &mut Scene,
|
||||
root: Handle<Node>,
|
||||
) -> Option<Self> {
|
||||
visible: bool,
|
||||
) -> Self {
|
||||
match shape {
|
||||
ColliderShape::Ball(ball_shape) => Some(Self::Ball {
|
||||
radius_handle: make_handle(scene, center + side.scale(ball_shape.radius), root),
|
||||
}),
|
||||
ColliderShape::Cylinder(cylinder_shape) => Some(Self::Cylinder {
|
||||
radius_handle: make_handle(scene, center + side.scale(cylinder_shape.radius), root),
|
||||
ColliderShape::Ball(ball) => Self::Ball {
|
||||
radius_handle: make_handle(scene, center + side.scale(ball.radius), root, visible),
|
||||
},
|
||||
ColliderShape::Cylinder(cylinder) => Self::Cylinder {
|
||||
radius_handle: make_handle(
|
||||
scene,
|
||||
center + side.scale(cylinder.radius),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
half_height_handle: make_handle(
|
||||
scene,
|
||||
center + up.scale(cylinder_shape.half_height),
|
||||
center + up.scale(cylinder.half_height),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
}),
|
||||
ColliderShape::Cone(cone_shape) => Some(Self::Cone {
|
||||
radius_handle: make_handle(scene, center + side.scale(cone_shape.radius), root),
|
||||
},
|
||||
ColliderShape::Cone(cone) => Self::Cone {
|
||||
radius_handle: make_handle(scene, center + side.scale(cone.radius), root, visible),
|
||||
half_height_handle: make_handle(
|
||||
scene,
|
||||
center + up.scale(cone_shape.half_height),
|
||||
center + up.scale(cone.half_height),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
}),
|
||||
ColliderShape::Cuboid(cuboid_shape) => Some(Self::Cuboid {
|
||||
},
|
||||
ColliderShape::Cuboid(cuboid) => Self::Cuboid {
|
||||
pos_x_handle: make_handle(
|
||||
scene,
|
||||
center + side.scale(cuboid_shape.half_extents.x),
|
||||
center + side.scale(cuboid.half_extents.x),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
pos_y_handle: make_handle(
|
||||
scene,
|
||||
center + up.scale(cuboid_shape.half_extents.y),
|
||||
center + up.scale(cuboid.half_extents.y),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
pos_z_handle: make_handle(
|
||||
scene,
|
||||
center + look.scale(cuboid_shape.half_extents.z),
|
||||
center + look.scale(cuboid.half_extents.z),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
neg_x_handle: make_handle(
|
||||
scene,
|
||||
center - side.scale(cuboid_shape.half_extents.x),
|
||||
center - side.scale(cuboid.half_extents.x),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
neg_y_handle: make_handle(
|
||||
scene,
|
||||
center - up.scale(cuboid_shape.half_extents.y),
|
||||
center - up.scale(cuboid.half_extents.y),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
neg_z_handle: make_handle(
|
||||
scene,
|
||||
center - look.scale(cuboid_shape.half_extents.z),
|
||||
center - look.scale(cuboid.half_extents.z),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
}),
|
||||
ColliderShape::Capsule(capsule_shape) => Some(Self::Capsule {
|
||||
radius_handle: make_handle(scene, center + side.scale(capsule_shape.radius), root),
|
||||
begin_handle: make_handle(scene, center + capsule_shape.begin, root),
|
||||
end_handle: make_handle(scene, center + capsule_shape.end, root),
|
||||
}),
|
||||
_ => None,
|
||||
},
|
||||
ColliderShape::Capsule(capsule) => Self::Capsule {
|
||||
radius_handle: make_handle(
|
||||
scene,
|
||||
center + side.scale(capsule.radius),
|
||||
root,
|
||||
visible,
|
||||
),
|
||||
begin_handle: make_handle(scene, center + capsule.begin, root, visible),
|
||||
end_handle: make_handle(scene, center + capsule.end, root, visible),
|
||||
},
|
||||
ColliderShape::Segment(segment) => Self::Segment {
|
||||
begin_handle: make_handle(scene, center + segment.begin, root, visible),
|
||||
end_handle: make_handle(scene, center + segment.end, root, visible),
|
||||
},
|
||||
ColliderShape::Triangle(triangle) => Self::Triangle {
|
||||
a_handle: make_handle(scene, center + triangle.a, root, visible),
|
||||
b_handle: make_handle(scene, center + triangle.b, root, visible),
|
||||
c_handle: make_handle(scene, center + triangle.c, root, visible),
|
||||
},
|
||||
ColliderShape::Polyhedron(_)
|
||||
| ColliderShape::Heightfield(_)
|
||||
| ColliderShape::Trimesh(_) => Self::NonEditable,
|
||||
}
|
||||
}
|
||||
|
||||
fn for_each_handle<F: FnMut(Handle<Node>)>(&self, mut func: F) {
|
||||
match self {
|
||||
ShapeGizmo::Cuboid {
|
||||
Self::NonEditable => {}
|
||||
Self::Cuboid {
|
||||
pos_x_handle,
|
||||
pos_y_handle,
|
||||
pos_z_handle,
|
||||
@@ -176,8 +223,8 @@ impl ShapeGizmo {
|
||||
func(*handle)
|
||||
}
|
||||
}
|
||||
ShapeGizmo::Ball { radius_handle } => func(*radius_handle),
|
||||
ShapeGizmo::Capsule {
|
||||
Self::Ball { radius_handle } => func(*radius_handle),
|
||||
Self::Capsule {
|
||||
radius_handle,
|
||||
begin_handle,
|
||||
end_handle,
|
||||
@@ -186,11 +233,11 @@ impl ShapeGizmo {
|
||||
func(*handle)
|
||||
}
|
||||
}
|
||||
ShapeGizmo::Cylinder {
|
||||
Self::Cylinder {
|
||||
radius_handle,
|
||||
half_height_handle,
|
||||
}
|
||||
| ShapeGizmo::Cone {
|
||||
| Self::Cone {
|
||||
radius_handle,
|
||||
half_height_handle,
|
||||
} => {
|
||||
@@ -198,10 +245,27 @@ impl ShapeGizmo {
|
||||
func(*handle)
|
||||
}
|
||||
}
|
||||
Self::Segment {
|
||||
begin_handle,
|
||||
end_handle,
|
||||
} => {
|
||||
for handle in [begin_handle, end_handle] {
|
||||
func(*handle)
|
||||
}
|
||||
}
|
||||
Self::Triangle {
|
||||
a_handle,
|
||||
b_handle,
|
||||
c_handle,
|
||||
} => {
|
||||
for handle in [a_handle, b_handle, c_handle] {
|
||||
func(*handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sync_to_shape(
|
||||
fn try_sync_to_shape(
|
||||
&self,
|
||||
shape: ColliderShape,
|
||||
center: Vector3<f32>,
|
||||
@@ -209,7 +273,7 @@ impl ShapeGizmo {
|
||||
up: Vector3<f32>,
|
||||
look: Vector3<f32>,
|
||||
scene: &mut Scene,
|
||||
) {
|
||||
) -> bool {
|
||||
let mut set_position = |handle: Handle<Node>, position: Vector3<f32>| {
|
||||
scene.graph[handle]
|
||||
.local_transform_mut()
|
||||
@@ -219,6 +283,7 @@ impl ShapeGizmo {
|
||||
match (self, shape) {
|
||||
(Self::Ball { radius_handle }, ColliderShape::Ball(ball_shape)) => {
|
||||
set_position(*radius_handle, center + side.scale(ball_shape.radius));
|
||||
true
|
||||
}
|
||||
(
|
||||
Self::Cylinder {
|
||||
@@ -229,6 +294,7 @@ impl ShapeGizmo {
|
||||
) => {
|
||||
set_position(*radius_handle, center + side.scale(cylinder.radius));
|
||||
set_position(*half_height_handle, center + up.scale(cylinder.half_height));
|
||||
true
|
||||
}
|
||||
(
|
||||
Self::Cone {
|
||||
@@ -239,6 +305,7 @@ impl ShapeGizmo {
|
||||
) => {
|
||||
set_position(*radius_handle, center + side.scale(cone.radius));
|
||||
set_position(*half_height_handle, center + up.scale(cone.half_height));
|
||||
true
|
||||
}
|
||||
(
|
||||
Self::Cuboid {
|
||||
@@ -257,6 +324,7 @@ impl ShapeGizmo {
|
||||
set_position(*neg_x_handle, center - side.scale(cuboid.half_extents.x));
|
||||
set_position(*neg_y_handle, center - up.scale(cuboid.half_extents.y));
|
||||
set_position(*neg_z_handle, center - look.scale(cuboid.half_extents.z));
|
||||
true
|
||||
}
|
||||
(
|
||||
Self::Capsule {
|
||||
@@ -269,9 +337,279 @@ impl ShapeGizmo {
|
||||
set_position(*radius_handle, center + side.scale(capsule_shape.radius));
|
||||
set_position(*begin_handle, center + capsule_shape.begin);
|
||||
set_position(*end_handle, center + capsule_shape.end);
|
||||
true
|
||||
}
|
||||
(
|
||||
Self::Segment {
|
||||
begin_handle,
|
||||
end_handle,
|
||||
},
|
||||
ColliderShape::Segment(segment),
|
||||
) => {
|
||||
set_position(*begin_handle, center + segment.begin);
|
||||
set_position(*end_handle, center + segment.end);
|
||||
true
|
||||
}
|
||||
(
|
||||
Self::Triangle {
|
||||
a_handle,
|
||||
b_handle,
|
||||
c_handle,
|
||||
},
|
||||
ColliderShape::Triangle(triangle),
|
||||
) => {
|
||||
set_position(*a_handle, center + triangle.a);
|
||||
set_position(*b_handle, center + triangle.b);
|
||||
set_position(*c_handle, center + triangle.c);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn value_by_handle(
|
||||
&self,
|
||||
handle: Handle<Node>,
|
||||
collider: &Collider,
|
||||
) -> Option<ShapeHandleValue> {
|
||||
match (self, collider.shape()) {
|
||||
(Self::Ball { radius_handle }, ColliderShape::Ball(ball_shape)) => {
|
||||
if handle == *radius_handle {
|
||||
return Some(ShapeHandleValue::Scalar(ball_shape.radius));
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Cylinder {
|
||||
radius_handle,
|
||||
half_height_handle,
|
||||
},
|
||||
ColliderShape::Cylinder(cylinder),
|
||||
) => {
|
||||
if handle == *radius_handle {
|
||||
return Some(ShapeHandleValue::Scalar(cylinder.radius));
|
||||
} else if handle == *half_height_handle {
|
||||
return Some(ShapeHandleValue::Scalar(cylinder.half_height));
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Cone {
|
||||
radius_handle,
|
||||
half_height_handle,
|
||||
},
|
||||
ColliderShape::Cone(cone),
|
||||
) => {
|
||||
if handle == *radius_handle {
|
||||
return Some(ShapeHandleValue::Scalar(cone.radius));
|
||||
} else if handle == *half_height_handle {
|
||||
return Some(ShapeHandleValue::Scalar(cone.half_height));
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Cuboid {
|
||||
pos_x_handle,
|
||||
pos_y_handle,
|
||||
pos_z_handle,
|
||||
neg_x_handle,
|
||||
neg_y_handle,
|
||||
neg_z_handle,
|
||||
},
|
||||
ColliderShape::Cuboid(cuboid),
|
||||
) => {
|
||||
if handle == *pos_x_handle {
|
||||
return Some(ShapeHandleValue::Scalar(cuboid.half_extents.x));
|
||||
} else if handle == *pos_y_handle {
|
||||
return Some(ShapeHandleValue::Scalar(cuboid.half_extents.y));
|
||||
} else if handle == *pos_z_handle {
|
||||
return Some(ShapeHandleValue::Scalar(cuboid.half_extents.z));
|
||||
} else if handle == *neg_x_handle {
|
||||
return Some(ShapeHandleValue::Scalar(-cuboid.half_extents.x));
|
||||
} else if handle == *neg_y_handle {
|
||||
return Some(ShapeHandleValue::Scalar(-cuboid.half_extents.y));
|
||||
} else if handle == *neg_z_handle {
|
||||
return Some(ShapeHandleValue::Scalar(-cuboid.half_extents.z));
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Capsule {
|
||||
radius_handle,
|
||||
begin_handle,
|
||||
end_handle,
|
||||
},
|
||||
ColliderShape::Capsule(capsule_shape),
|
||||
) => {
|
||||
if handle == *radius_handle {
|
||||
return Some(ShapeHandleValue::Scalar(capsule_shape.radius));
|
||||
} else if handle == *begin_handle {
|
||||
return Some(ShapeHandleValue::Vector(capsule_shape.begin));
|
||||
} else if handle == *end_handle {
|
||||
return Some(ShapeHandleValue::Vector(capsule_shape.end));
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Segment {
|
||||
begin_handle,
|
||||
end_handle,
|
||||
},
|
||||
ColliderShape::Segment(segment),
|
||||
) => {
|
||||
if handle == *begin_handle {
|
||||
return Some(ShapeHandleValue::Vector(segment.begin));
|
||||
} else if handle == *end_handle {
|
||||
return Some(ShapeHandleValue::Vector(segment.end));
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Triangle {
|
||||
a_handle,
|
||||
b_handle,
|
||||
c_handle,
|
||||
},
|
||||
ColliderShape::Triangle(triangle),
|
||||
) => {
|
||||
if handle == *a_handle {
|
||||
return Some(ShapeHandleValue::Vector(triangle.a));
|
||||
} else if handle == *b_handle {
|
||||
return Some(ShapeHandleValue::Vector(triangle.b));
|
||||
} else if handle == *c_handle {
|
||||
return Some(ShapeHandleValue::Vector(triangle.c));
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn set_value_by_handle(
|
||||
&self,
|
||||
handle: Handle<Node>,
|
||||
value: ShapeHandleValue,
|
||||
collider: &mut Collider,
|
||||
) -> Option<ShapeHandleValue> {
|
||||
match (self, collider.shape_mut()) {
|
||||
(Self::Ball { radius_handle }, ColliderShape::Ball(ball_shape)) => {
|
||||
if handle == *radius_handle {
|
||||
ball_shape.radius = value.into_scalar();
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Cylinder {
|
||||
radius_handle,
|
||||
half_height_handle,
|
||||
},
|
||||
ColliderShape::Cylinder(cylinder),
|
||||
) => {
|
||||
if handle == *radius_handle {
|
||||
cylinder.radius = value.into_scalar();
|
||||
} else if handle == *half_height_handle {
|
||||
cylinder.half_height = value.into_scalar();
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Cone {
|
||||
radius_handle,
|
||||
half_height_handle,
|
||||
},
|
||||
ColliderShape::Cone(cone),
|
||||
) => {
|
||||
if handle == *radius_handle {
|
||||
cone.radius = value.into_scalar();
|
||||
} else if handle == *half_height_handle {
|
||||
cone.half_height = value.into_scalar();
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Cuboid {
|
||||
pos_x_handle,
|
||||
pos_y_handle,
|
||||
pos_z_handle,
|
||||
neg_x_handle,
|
||||
neg_y_handle,
|
||||
neg_z_handle,
|
||||
},
|
||||
ColliderShape::Cuboid(cuboid),
|
||||
) => {
|
||||
if handle == *pos_x_handle {
|
||||
cuboid.half_extents.x = value.into_scalar();
|
||||
} else if handle == *pos_y_handle {
|
||||
cuboid.half_extents.y = value.into_scalar();
|
||||
} else if handle == *pos_z_handle {
|
||||
cuboid.half_extents.z = value.into_scalar();
|
||||
} else if handle == *neg_x_handle {
|
||||
let transform = collider.local_transform_mut();
|
||||
let position = **transform.position();
|
||||
transform.set_position(Vector3::new(
|
||||
position.x - value.into_scalar(),
|
||||
position.y,
|
||||
position.z,
|
||||
));
|
||||
} else if handle == *neg_y_handle {
|
||||
let transform = collider.local_transform_mut();
|
||||
let position = **transform.position();
|
||||
transform.set_position(Vector3::new(
|
||||
position.x,
|
||||
position.y - value.into_scalar(),
|
||||
position.z,
|
||||
));
|
||||
} else if handle == *neg_z_handle {
|
||||
let transform = collider.local_transform_mut();
|
||||
let position = **transform.position();
|
||||
transform.set_position(Vector3::new(
|
||||
position.x,
|
||||
position.y,
|
||||
position.z - value.into_scalar(),
|
||||
));
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Capsule {
|
||||
radius_handle,
|
||||
begin_handle,
|
||||
end_handle,
|
||||
},
|
||||
ColliderShape::Capsule(capsule),
|
||||
) => {
|
||||
if handle == *radius_handle {
|
||||
capsule.radius = value.into_scalar();
|
||||
} else if handle == *begin_handle {
|
||||
capsule.begin = value.into_vector();
|
||||
} else if handle == *end_handle {
|
||||
capsule.end = value.into_vector();
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Segment {
|
||||
begin_handle,
|
||||
end_handle,
|
||||
},
|
||||
ColliderShape::Segment(segment),
|
||||
) => {
|
||||
if handle == *begin_handle {
|
||||
segment.begin = value.into_vector();
|
||||
} else if handle == *end_handle {
|
||||
segment.end = value.into_vector();
|
||||
}
|
||||
}
|
||||
(
|
||||
Self::Triangle {
|
||||
a_handle,
|
||||
b_handle,
|
||||
c_handle,
|
||||
},
|
||||
ColliderShape::Triangle(triangle),
|
||||
) => {
|
||||
if handle == *a_handle {
|
||||
triangle.a = value.into_vector();
|
||||
} else if handle == *b_handle {
|
||||
triangle.b = value.into_vector();
|
||||
} else if handle == *c_handle {
|
||||
triangle.c = value.into_vector();
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn reset_handles(&self, scene: &mut Scene) {
|
||||
@@ -301,12 +639,42 @@ impl ShapeGizmo {
|
||||
}
|
||||
}
|
||||
|
||||
enum ShapeHandleValue {
|
||||
Scalar(f32),
|
||||
Vector(Vector3<f32>),
|
||||
}
|
||||
|
||||
impl ShapeHandleValue {
|
||||
fn into_scalar(self) -> f32 {
|
||||
match self {
|
||||
ShapeHandleValue::Scalar(scalar) => scalar,
|
||||
ShapeHandleValue::Vector(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn into_vector(self) -> Vector3<f32> {
|
||||
match self {
|
||||
ShapeHandleValue::Scalar(_) => unreachable!(),
|
||||
ShapeHandleValue::Vector(vector) => vector,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DragContext {
|
||||
handle: Handle<Node>,
|
||||
initial_position: Vector3<f32>,
|
||||
plane: Plane,
|
||||
initial_value: ShapeHandleValue,
|
||||
}
|
||||
|
||||
#[derive(TypeUuidProvider)]
|
||||
#[type_uuid(id = "a012dd4c-ce6d-4e7e-8879-fd8eddaa9677")]
|
||||
pub struct ColliderShapeInteractionMode {
|
||||
active_handle: Handle<Node>,
|
||||
collider: Handle<Node>,
|
||||
gizmo: ShapeGizmo,
|
||||
drag_context: Option<DragContext>,
|
||||
}
|
||||
|
||||
impl ColliderShapeInteractionMode {
|
||||
@@ -330,12 +698,45 @@ impl InteractionMode for ColliderShapeInteractionMode {
|
||||
fn on_left_mouse_button_down(
|
||||
&mut self,
|
||||
_editor_selection: &Selection,
|
||||
_controller: &mut dyn SceneController,
|
||||
_engine: &mut Engine,
|
||||
_mouse_pos: Vector2<f32>,
|
||||
controller: &mut dyn SceneController,
|
||||
engine: &mut Engine,
|
||||
mouse_position: Vector2<f32>,
|
||||
_frame_size: Vector2<f32>,
|
||||
_settings: &Settings,
|
||||
) {
|
||||
let Some(game_scene) = controller.downcast_mut::<GameScene>() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let scene = &mut engine.scenes[game_scene.scene];
|
||||
|
||||
if let Some(result) = game_scene.camera_controller.pick(
|
||||
&scene.graph,
|
||||
PickingOptions {
|
||||
cursor_pos: mouse_position,
|
||||
editor_only: true,
|
||||
..Default::default()
|
||||
},
|
||||
) {
|
||||
if let Some(handle_value) = self
|
||||
.gizmo
|
||||
.value_by_handle(result.node, scene.graph[self.collider].as_collider())
|
||||
{
|
||||
let initial_position = scene.graph[result.node].global_position();
|
||||
let camera_view_dir = scene.graph[game_scene.camera_controller.camera]
|
||||
.look_vector()
|
||||
.try_normalize(f32::EPSILON)
|
||||
.unwrap_or_default();
|
||||
|
||||
self.drag_context = Some(DragContext {
|
||||
handle: result.node,
|
||||
initial_position,
|
||||
plane: Plane::from_normal_and_point(&-camera_view_dir, &initial_position)
|
||||
.unwrap_or_default(),
|
||||
initial_value: handle_value,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_left_mouse_button_up(
|
||||
@@ -347,6 +748,7 @@ impl InteractionMode for ColliderShapeInteractionMode {
|
||||
_frame_size: Vector2<f32>,
|
||||
_settings: &Settings,
|
||||
) {
|
||||
if let Some(_drag_context) = self.drag_context.take() {}
|
||||
}
|
||||
|
||||
fn on_mouse_move(
|
||||
@@ -356,7 +758,7 @@ impl InteractionMode for ColliderShapeInteractionMode {
|
||||
_editor_selection: &Selection,
|
||||
controller: &mut dyn SceneController,
|
||||
engine: &mut Engine,
|
||||
_frame_size: Vector2<f32>,
|
||||
frame_size: Vector2<f32>,
|
||||
_settings: &Settings,
|
||||
) {
|
||||
let Some(game_scene) = controller.downcast_mut::<GameScene>() else {
|
||||
@@ -366,7 +768,6 @@ impl InteractionMode for ColliderShapeInteractionMode {
|
||||
let scene = &mut engine.scenes[game_scene.scene];
|
||||
|
||||
self.gizmo.reset_handles(scene);
|
||||
self.active_handle = Handle::NONE;
|
||||
|
||||
if let Some(result) = game_scene.camera_controller.pick(
|
||||
&scene.graph,
|
||||
@@ -380,8 +781,22 @@ impl InteractionMode for ColliderShapeInteractionMode {
|
||||
scene.graph[result.node]
|
||||
.as_sprite_mut()
|
||||
.set_color(Color::RED);
|
||||
}
|
||||
}
|
||||
|
||||
self.active_handle = result.node;
|
||||
if let Some(drag_context) = self.drag_context.as_ref() {
|
||||
let camera = scene.graph[game_scene.camera_controller.camera].as_camera();
|
||||
let ray = camera.make_ray(mouse_position, frame_size);
|
||||
if let Some(intersection) = ray.plane_intersection_point(&drag_context.plane) {
|
||||
let delta = drag_context.initial_position.metric_distance(&intersection);
|
||||
|
||||
if let ShapeHandleValue::Scalar(inital_value) = drag_context.initial_value {
|
||||
self.gizmo.set_value_by_handle(
|
||||
drag_context.handle,
|
||||
ShapeHandleValue::Scalar(inital_value + delta),
|
||||
scene.graph[self.collider].as_collider_mut(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,8 +832,26 @@ impl InteractionMode for ColliderShapeInteractionMode {
|
||||
.try_normalize(f32::EPSILON)
|
||||
.unwrap_or_default();
|
||||
|
||||
self.gizmo
|
||||
.sync_to_shape(collider.shape().clone(), center, side, up, look, scene);
|
||||
let shape = collider.shape().clone();
|
||||
if !self
|
||||
.gizmo
|
||||
.try_sync_to_shape(shape.clone(), center, side, up, look, scene)
|
||||
{
|
||||
let new_gizmo = ShapeGizmo::create(
|
||||
shape,
|
||||
center,
|
||||
side,
|
||||
up,
|
||||
look,
|
||||
scene,
|
||||
game_scene.editor_objects_root,
|
||||
true,
|
||||
);
|
||||
|
||||
let old_gizmo = std::mem::replace(&mut self.gizmo, new_gizmo);
|
||||
|
||||
old_gizmo.destroy(scene);
|
||||
}
|
||||
}
|
||||
|
||||
fn activate(&mut self, controller: &dyn SceneController, engine: &mut Engine) {
|
||||
@@ -486,7 +919,7 @@ impl EditorPlugin for ColliderShapePlugin {
|
||||
.try_normalize(f32::EPSILON)
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(gizmo) = ShapeGizmo::try_create(
|
||||
let gizmo = ShapeGizmo::create(
|
||||
collider.shape().clone(),
|
||||
center,
|
||||
side,
|
||||
@@ -494,13 +927,14 @@ impl EditorPlugin for ColliderShapePlugin {
|
||||
look,
|
||||
scene,
|
||||
game_scene.editor_objects_root,
|
||||
) {
|
||||
entry.interaction_modes.add(ColliderShapeInteractionMode {
|
||||
active_handle: Default::default(),
|
||||
collider: *node_handle,
|
||||
gizmo,
|
||||
})
|
||||
}
|
||||
false,
|
||||
);
|
||||
|
||||
entry.interaction_modes.add(ColliderShapeInteractionMode {
|
||||
collider: *node_handle,
|
||||
gizmo,
|
||||
drag_context: None,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user