Преглед изворни кода

Merge pull request #97535 from HolonProduction/gizmo-cylinder

Editor: Improve cylinder gizmos
Thaddeus Crews пре 10 месеци
родитељ
комит
61accf0605

+ 10 - 47
editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp

@@ -93,7 +93,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g
 	}
 	}
 
 
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 	if (Object::cast_to<CylinderShape3D>(*s)) {
-		return p_id == 0 ? "Radius" : "Height";
+		return helper->cylinder_get_handle_name(p_id);
 	}
 	}
 
 
 	if (Object::cast_to<SeparationRayShape3D>(*s)) {
 	if (Object::cast_to<SeparationRayShape3D>(*s)) {
@@ -219,25 +219,15 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i
 	}
 	}
 
 
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 	if (Object::cast_to<CylinderShape3D>(*s)) {
-		Vector3 axis;
-		axis[p_id == 0 ? 0 : 1] = 1.0;
 		Ref<CylinderShape3D> cs2 = s;
 		Ref<CylinderShape3D> 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->cylinder_set_handle(sg, p_id, height, radius, position);
+		cs2->set_height(height);
+		cs2->set_radius(radius);
+		cs->set_global_position(position);
 	}
 	}
 }
 }
 
 
@@ -293,31 +283,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
 
 
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 	if (Object::cast_to<CylinderShape3D>(*s)) {
 		Ref<CylinderShape3D> ss = s;
 		Ref<CylinderShape3D> ss = s;
-		if (p_cancel) {
-			if (p_id == 0) {
-				ss->set_radius(p_restore);
-			} else {
-				ss->set_height(p_restore);
-			}
-			return;
-		}
-
-		EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
-		if (p_id == 0) {
-			ur->create_action(TTR("Change Cylinder Shape Radius"));
-			ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
-			ur->add_undo_method(ss.ptr(), "set_radius", p_restore);
-		} else {
-			ur->create_action(
-					///
-
-					////////
-					TTR("Change Cylinder Shape Height"));
-			ur->add_do_method(ss.ptr(), "set_height", ss->get_height());
-			ur->add_undo_method(ss.ptr(), "set_height", p_restore);
-		}
-
-		ur->commit_action();
+		helper->cylinder_commit_handle(p_id, TTR("Change Cylinder Shape Radius"), TTR("Change Cylinder Shape Height"), p_cancel, cs, *ss, *ss);
 	}
 	}
 
 
 	if (Object::cast_to<SeparationRayShape3D>(*s)) {
 	if (Object::cast_to<SeparationRayShape3D>(*s)) {
@@ -534,10 +500,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 
 
 		p_gizmo->add_collision_segments(collision_segments);
 		p_gizmo->add_collision_segments(collision_segments);
 
 
-		Vector<Vector3> handles = {
-			Vector3(cs2->get_radius(), 0, 0),
-			Vector3(0, cs2->get_height() * 0.5, 0)
-		};
+		Vector<Vector3> handles = helper->cylinder_get_handles(cs2->get_height(), cs2->get_radius());
 		p_gizmo->add_handles(handles, handles_material);
 		p_gizmo->add_handles(handles, handles_material);
 	}
 	}
 
 

+ 95 - 0
editor/plugins/gizmos/gizmo_3d_helper.cpp

@@ -139,3 +139,98 @@ void Gizmo3DHelper::box_commit_handle(const String &p_action_name, bool p_cancel
 	ur->add_undo_property(p_position_object, p_position_property, initial_transform.get_origin());
 	ur->add_undo_property(p_position_object, p_position_property, initial_transform.get_origin());
 	ur->commit_action();
 	ur->commit_action();
 }
 }
+
+Vector<Vector3> Gizmo3DHelper::cylinder_get_handles(real_t p_height, real_t p_radius) {
+	Vector<Vector3> handles;
+	handles.push_back(Vector3(p_radius, 0, 0));
+	handles.push_back(Vector3(0, p_height * 0.5, 0));
+	handles.push_back(Vector3(0, p_height * -0.5, 0));
+	return handles;
+}
+
+String Gizmo3DHelper::cylinder_get_handle_name(int p_id) const {
+	if (p_id == 0) {
+		return "Radius";
+	} else {
+		return "Height";
+	}
+}
+
+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) {
+	int sign = p_id == 2 ? -1 : 1;
+	int axis = p_id == 0 ? 0 : 1;
+
+	Vector3 axis_vector;
+	axis_vector[axis] = sign;
+	Vector3 ra, rb;
+	Geometry3D::get_closest_points_between_segments(axis_vector * -4096, axis_vector * 4096, p_segment[0], p_segment[1], ra, rb);
+	float d = axis_vector.dot(ra);
+
+	// Snap to grid.
+	if (Node3DEditor::get_singleton()->is_snap_enabled()) {
+		d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
+	}
+
+	if (p_id == 0) {
+		// Adjust radius.
+		if (d < 0.001) {
+			d = 0.001;
+		}
+		r_radius = d;
+		r_cylinder_position = initial_transform.get_origin();
+	} else if (p_id == 1 || p_id == 2) {
+		real_t initial_height = initial_value;
+
+		// Adjust height.
+		if (Input::get_singleton()->is_key_pressed(Key::ALT)) {
+			r_height = d * 2.0;
+		} else {
+			r_height = (initial_height * 0.5) + d;
+		}
+
+		if (r_height < 0.001) {
+			r_height = 0.001;
+		}
+
+		// Adjust position.
+		if (Input::get_singleton()->is_key_pressed(Key::ALT)) {
+			r_cylinder_position = initial_transform.get_origin();
+		} else {
+			Vector3 offset;
+			offset[axis] = (r_height - initial_height) * 0.5 * sign;
+			r_cylinder_position = initial_transform.xform(offset);
+		}
+	}
+}
+
+void Gizmo3DHelper::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, Object *p_radius_object, const StringName &p_position_property, const StringName &p_height_property, const StringName &p_radius_property) {
+	if (!p_height_object) {
+		p_height_object = p_position_object;
+	}
+	if (!p_radius_object) {
+		p_radius_object = p_position_object;
+	}
+
+	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_position_object->set(p_position_property, initial_transform.get_origin());
+		return;
+	}
+
+	EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
+	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->commit_action();
+}

+ 5 - 0
editor/plugins/gizmos/gizmo_3d_helper.h

@@ -50,6 +50,11 @@ public:
 	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");
+
+	Vector<Vector3> cylinder_get_handles(real_t p_height, real_t p_radius);
+	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);
+	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");
 };
 };
 
 
 #endif // GIZMO_3D_HELPER_H
 #endif // GIZMO_3D_HELPER_H

+ 10 - 44
modules/csg/editor/csg_gizmos.cpp

@@ -278,24 +278,13 @@ void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_i
 	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);
 
 
-		Vector3 axis;
-		axis[p_id == 0 ? 0 : 1] = 1.0;
-		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) {
-			s->set_radius(d);
-		} else if (p_id == 1) {
-			s->set_height(d * 2.0);
-		}
+		real_t height = s->get_height();
+		real_t radius = s->get_radius();
+		Vector3 position;
+		helper->cylinder_set_handle(sg, p_id, height, radius, position);
+		s->set_height(height);
+		s->set_radius(radius);
+		s->set_global_position(position);
 	}
 	}
 
 
 	if (Object::cast_to<CSGTorus3D>(cs)) {
 	if (Object::cast_to<CSGTorus3D>(cs)) {
@@ -340,32 +329,11 @@ void CSGShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int
 	}
 	}
 
 
 	if (Object::cast_to<CSGBox3D>(cs)) {
 	if (Object::cast_to<CSGBox3D>(cs)) {
-		helper->box_commit_handle(TTR("Change Box Shape Size"), p_cancel, cs);
+		helper->box_commit_handle(TTR("Change CSG Box Size"), p_cancel, cs);
 	}
 	}
 
 
 	if (Object::cast_to<CSGCylinder3D>(cs)) {
 	if (Object::cast_to<CSGCylinder3D>(cs)) {
-		CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
-		if (p_cancel) {
-			if (p_id == 0) {
-				s->set_radius(p_restore);
-			} else {
-				s->set_height(p_restore);
-			}
-			return;
-		}
-
-		EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
-		if (p_id == 0) {
-			ur->create_action(TTR("Change Cylinder Radius"));
-			ur->add_do_method(s, "set_radius", s->get_radius());
-			ur->add_undo_method(s, "set_radius", p_restore);
-		} else {
-			ur->create_action(TTR("Change Cylinder Height"));
-			ur->add_do_method(s, "set_height", s->get_height());
-			ur->add_undo_method(s, "set_height", p_restore);
-		}
-
-		ur->commit_action();
+		helper->cylinder_commit_handle(p_id, TTR("Change CSG Cylinder Radius"), TTR("Change CSG Cylinder Height"), p_cancel, cs);
 	}
 	}
 
 
 	if (Object::cast_to<CSGTorus3D>(cs)) {
 	if (Object::cast_to<CSGTorus3D>(cs)) {
@@ -506,9 +474,7 @@ void CSGShape3DGizmoPlugin::redraw(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);
 
 
-		Vector<Vector3> handles;
-		handles.push_back(Vector3(s->get_radius(), 0, 0));
-		handles.push_back(Vector3(0, s->get_height() * 0.5, 0));
+		Vector<Vector3> handles = helper->cylinder_get_handles(s->get_height(), s->get_radius());
 		p_gizmo->add_handles(handles, handles_material);
 		p_gizmo->add_handles(handles, handles_material);
 	}
 	}