Browse Source

Editor: Improve capsule gizmos

HolonProduction 8 months ago
parent
commit
02eab5e2c4

+ 11 - 44
editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp

@@ -115,7 +115,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g
 	}
 	}
 
 
 	if (Object::cast_to<CapsuleShape3D>(*s)) {
 	if (Object::cast_to<CapsuleShape3D>(*s)) {
-		return p_id == 0 ? "Radius" : "Height";
+		return helper->capsule_get_handle_name(p_id);
 	}
 	}
 
 
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 	if (Object::cast_to<CylinderShape3D>(*s)) {
@@ -154,7 +154,7 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p
 
 
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 		Ref<CylinderShape3D> cs2 = s;
 		Ref<CylinderShape3D> cs2 = s;
-		return p_id == 0 ? cs2->get_radius() : cs2->get_height();
+		return Vector2(cs2->get_radius(), cs2->get_height());
 	}
 	}
 
 
 	if (Object::cast_to<SeparationRayShape3D>(*s)) {
 	if (Object::cast_to<SeparationRayShape3D>(*s)) {
@@ -222,26 +222,15 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i
 	}
 	}
 
 
 	if (Object::cast_to<CapsuleShape3D>(*s)) {
 	if (Object::cast_to<CapsuleShape3D>(*s)) {
-		Vector3 axis;
-		axis[p_id == 0 ? 0 : 1] = 1.0;
 		Ref<CapsuleShape3D> cs2 = s;
 		Ref<CapsuleShape3D> cs2 = s;
-		Vector3 ra, rb;
-		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
-		float d = axis.dot(ra);
-
-		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
-			d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
-		}
-
-		if (d < 0.001) {
-			d = 0.001;
-		}
 
 
-		if (p_id == 0) {
-			cs2->set_radius(d);
-		} else if (p_id == 1) {
-			cs2->set_height(d * 2.0);
-		}
+		real_t height = cs2->get_height();
+		real_t radius = cs2->get_radius();
+		Vector3 position;
+		helper->capsule_set_handle(sg, p_id, height, radius, position);
+		cs2->set_height(height);
+		cs2->set_radius(radius);
+		cs->set_global_position(position);
 	}
 	}
 
 
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 	if (Object::cast_to<CylinderShape3D>(*s)) {
@@ -285,26 +274,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
 
 
 	if (Object::cast_to<CapsuleShape3D>(*s)) {
 	if (Object::cast_to<CapsuleShape3D>(*s)) {
 		Ref<CapsuleShape3D> ss = s;
 		Ref<CapsuleShape3D> ss = s;
-		Vector2 values = p_restore;
-
-		if (p_cancel) {
-			ss->set_radius(values[0]);
-			ss->set_height(values[1]);
-			return;
-		}
-
-		EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
-		if (p_id == 0) {
-			ur->create_action(TTR("Change Capsule Shape Radius"));
-			ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
-		} else {
-			ur->create_action(TTR("Change Capsule Shape Height"));
-			ur->add_do_method(ss.ptr(), "set_height", ss->get_height());
-		}
-		ur->add_undo_method(ss.ptr(), "set_radius", values[0]);
-		ur->add_undo_method(ss.ptr(), "set_height", values[1]);
-
-		ur->commit_action();
+		helper->cylinder_commit_handle(p_id, TTR("Change Capsule Shape Radius"), TTR("Change Capsule Shape Height"), p_cancel, cs, *ss, *ss);
 	}
 	}
 
 
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 	if (Object::cast_to<CylinderShape3D>(*s)) {
@@ -547,10 +517,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 		p_gizmo->add_lines(points, material, false, collision_color);
 		p_gizmo->add_lines(points, material, false, collision_color);
 		p_gizmo->add_collision_segments(points);
 		p_gizmo->add_collision_segments(points);
 
 
-		Vector<Vector3> handles = {
-			Vector3(cs2->get_radius(), 0, 0),
-			Vector3(0, cs2->get_height() * 0.5, 0)
-		};
+		Vector<Vector3> handles = helper->capsule_get_handles(cs2->get_height(), cs2->get_radius());
 		p_gizmo->add_handles(handles, handles_material);
 		p_gizmo->add_handles(handles, handles_material);
 	}
 	}
 
 

+ 24 - 17
editor/plugins/gizmos/gizmo_3d_helper.cpp

@@ -156,7 +156,10 @@ String Gizmo3DHelper::cylinder_get_handle_name(int p_id) const {
 	}
 	}
 }
 }
 
 
-void Gizmo3DHelper::cylinder_set_handle(const Vector3 p_segment[2], int p_id, real_t &r_height, real_t &r_radius, Vector3 &r_cylinder_position) {
+void Gizmo3DHelper::_cylinder_or_capsule_set_handle(const Vector3 p_segment[2], int p_id, real_t &r_height, real_t &r_radius, Vector3 &r_cylinder_position, bool p_is_capsule) {
+	real_t initial_radius = initial_value.operator Vector2().x;
+	real_t initial_height = initial_value.operator Vector2().y;
+
 	int sign = p_id == 2 ? -1 : 1;
 	int sign = p_id == 2 ? -1 : 1;
 	int axis = p_id == 0 ? 0 : 1;
 	int axis = p_id == 0 ? 0 : 1;
 
 
@@ -178,9 +181,13 @@ void Gizmo3DHelper::cylinder_set_handle(const Vector3 p_segment[2], int p_id, re
 		}
 		}
 		r_radius = d;
 		r_radius = d;
 		r_cylinder_position = initial_transform.get_origin();
 		r_cylinder_position = initial_transform.get_origin();
-	} else if (p_id == 1 || p_id == 2) {
-		real_t initial_height = initial_value;
 
 
+		if (p_is_capsule) {
+			r_height = MAX(initial_height, r_radius * 2.0);
+		} else {
+			r_height = initial_height;
+		}
+	} else if (p_id == 1 || p_id == 2) {
 		// Adjust height.
 		// Adjust height.
 		if (Input::get_singleton()->is_key_pressed(Key::ALT)) {
 		if (Input::get_singleton()->is_key_pressed(Key::ALT)) {
 			r_height = d * 2.0;
 			r_height = d * 2.0;
@@ -200,6 +207,12 @@ void Gizmo3DHelper::cylinder_set_handle(const Vector3 p_segment[2], int p_id, re
 			offset[axis] = (r_height - initial_height) * 0.5 * sign;
 			offset[axis] = (r_height - initial_height) * 0.5 * sign;
 			r_cylinder_position = initial_transform.xform(offset);
 			r_cylinder_position = initial_transform.xform(offset);
 		}
 		}
+
+		if (p_is_capsule) {
+			r_radius = MIN(initial_radius, r_height / 2.0);
+		} else {
+			r_radius = initial_radius;
+		}
 	}
 	}
 }
 }
 
 
@@ -212,25 +225,19 @@ void Gizmo3DHelper::cylinder_commit_handle(int p_id, const String &p_radius_acti
 	}
 	}
 
 
 	if (p_cancel) {
 	if (p_cancel) {
-		if (p_id == 0) {
-			p_radius_object->set(p_radius_property, initial_value);
-		} else {
-			p_height_object->set(p_height_property, initial_value);
-		}
+		p_radius_object->set(p_radius_property, initial_value.operator Vector2().x);
+		p_height_object->set(p_height_property, initial_value.operator Vector2().y);
 		p_position_object->set(p_position_property, initial_transform.get_origin());
 		p_position_object->set(p_position_property, initial_transform.get_origin());
 		return;
 		return;
 	}
 	}
 
 
 	EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
 	EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
 	ur->create_action(p_id == 0 ? p_radius_action_name : p_height_action_name);
 	ur->create_action(p_id == 0 ? p_radius_action_name : p_height_action_name);
-	if (p_id == 0) {
-		ur->add_do_property(p_radius_object, p_radius_property, p_radius_object->get(p_radius_property));
-		ur->add_undo_property(p_radius_object, p_radius_property, initial_value);
-	} else {
-		ur->add_do_property(p_height_object, p_height_property, p_height_object->get(p_height_property));
-		ur->add_do_property(p_position_object, p_position_property, p_position_object->get(p_position_property));
-		ur->add_undo_property(p_height_object, p_height_property, initial_value);
-		ur->add_undo_property(p_position_object, p_position_property, initial_transform.get_origin());
-	}
+	ur->add_do_property(p_radius_object, p_radius_property, p_radius_object->get(p_radius_property));
+	ur->add_undo_property(p_radius_object, p_radius_property, initial_value.operator Vector2().x);
+	ur->add_do_property(p_height_object, p_height_property, p_height_object->get(p_height_property));
+	ur->add_undo_property(p_height_object, p_height_property, initial_value.operator Vector2().y);
+	ur->add_do_property(p_position_object, p_position_property, p_position_object->get(p_position_property));
+	ur->add_undo_property(p_position_object, p_position_property, initial_transform.get_origin());
 	ur->commit_action();
 	ur->commit_action();
 }
 }

+ 28 - 1
editor/plugins/gizmos/gizmo_3d_helper.h

@@ -41,17 +41,44 @@ class Gizmo3DHelper : public RefCounted {
 	Variant initial_value;
 	Variant initial_value;
 	Transform3D initial_transform;
 	Transform3D initial_transform;
 
 
+private:
+	void _cylinder_or_capsule_set_handle(const Vector3 p_segment[2], int p_id, real_t &r_height, real_t &r_radius, Vector3 &r_cylinder_position, bool p_is_capsule);
+
 public:
 public:
+	/**
+	 * Initializes a new action involving a handle.
+	 *
+	 * Depending on the type of gizmo that will be used, different formats for the `p_initial_value` are required:
+	 * Box: The size of the box as `Vector3`
+	 * Cylinder or Capsule: A `Vector2` of the form `Vector2(radius, height)`
+	 */
 	void initialize_handle_action(const Variant &p_initial_value, const Transform3D &p_initial_transform);
 	void initialize_handle_action(const Variant &p_initial_value, const Transform3D &p_initial_transform);
 	void get_segment(Camera3D *p_camera, const Point2 &p_point, Vector3 *r_segment);
 	void get_segment(Camera3D *p_camera, const Point2 &p_point, Vector3 *r_segment);
 
 
+	// Box
+
 	Vector<Vector3> box_get_handles(const Vector3 &p_box_size);
 	Vector<Vector3> box_get_handles(const Vector3 &p_box_size);
 	String box_get_handle_name(int p_id) const;
 	String box_get_handle_name(int p_id) const;
 	void box_set_handle(const Vector3 p_segment[2], int p_id, Vector3 &r_box_size, Vector3 &r_box_position);
 	void box_set_handle(const Vector3 p_segment[2], int p_id, Vector3 &r_box_size, Vector3 &r_box_position);
 	void box_commit_handle(const String &p_action_name, bool p_cancel, Object *p_position_object, Object *p_size_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_size_property = "size");
 	void box_commit_handle(const String &p_action_name, bool p_cancel, Object *p_position_object, Object *p_size_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_size_property = "size");
 
 
+	// Cylinder
+
 	Vector<Vector3> cylinder_get_handles(real_t p_height, real_t p_radius);
 	Vector<Vector3> cylinder_get_handles(real_t p_height, real_t p_radius);
 	String cylinder_get_handle_name(int p_id) const;
 	String cylinder_get_handle_name(int p_id) const;
-	void cylinder_set_handle(const Vector3 p_segment[2], int p_id, real_t &r_height, real_t &r_radius, Vector3 &r_cylinder_position);
+	_FORCE_INLINE_ void cylinder_set_handle(const Vector3 p_segment[2], int p_id, real_t &r_height, real_t &r_radius, Vector3 &r_cylinder_position) {
+		_cylinder_or_capsule_set_handle(p_segment, p_id, r_height, r_radius, r_cylinder_position, false);
+	}
 	void cylinder_commit_handle(int p_id, const String &p_radius_action_name, const String &p_height_action_name, bool p_cancel, Object *p_position_object, Object *p_height_object = nullptr, Object *p_radius_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_height_property = "height", const StringName &p_radius_property = "radius");
 	void cylinder_commit_handle(int p_id, const String &p_radius_action_name, const String &p_height_action_name, bool p_cancel, Object *p_position_object, Object *p_height_object = nullptr, Object *p_radius_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_height_property = "height", const StringName &p_radius_property = "radius");
+
+	// Capsule
+
+	_FORCE_INLINE_ Vector<Vector3> capsule_get_handles(real_t p_height, real_t p_radius) { return cylinder_get_handles(p_height, p_radius); }
+	_FORCE_INLINE_ String capsule_get_handle_name(int p_id) { return cylinder_get_handle_name(p_id); }
+	_FORCE_INLINE_ void capsule_set_handle(const Vector3 p_segment[2], int p_id, real_t &r_height, real_t &r_radius, Vector3 &r_capsule_position) {
+		_cylinder_or_capsule_set_handle(p_segment, p_id, r_height, r_radius, r_capsule_position, true);
+	}
+	_FORCE_INLINE_ void capsule_commit_handle(int p_id, const String &p_radius_action_name, const String &p_height_action_name, bool p_cancel, Object *p_position_object, Object *p_height_object = nullptr, Object *p_radius_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_height_property = "height", const StringName &p_radius_property = "radius") {
+		cylinder_commit_handle(p_id, p_radius_action_name, p_height_action_name, p_cancel, p_position_object, p_height_object, p_radius_object, p_position_property, p_height_property, p_radius_property);
+	}
 };
 };

+ 1 - 1
modules/csg/editor/csg_gizmos.cpp

@@ -222,7 +222,7 @@ Variant CSGShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo
 
 
 	if (Object::cast_to<CSGCylinder3D>(cs)) {
 	if (Object::cast_to<CSGCylinder3D>(cs)) {
 		CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
 		CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
-		return p_id == 0 ? s->get_radius() : s->get_height();
+		return Vector2(s->get_radius(), s->get_height());
 	}
 	}
 
 
 	if (Object::cast_to<CSGTorus3D>(cs)) {
 	if (Object::cast_to<CSGTorus3D>(cs)) {