Browse Source

Improve editing of box collision shapes

kobewi 2 years ago
parent
commit
0a9a8c75fa

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

@@ -134,6 +134,11 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p
 	return Variant();
 	return Variant();
 }
 }
 
 
+void CollisionShape3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) {
+	initial_transform = p_gizmo->get_node_3d()->get_global_transform();
+	initial_value = get_handle_value(p_gizmo, p_id, p_secondary);
+}
+
 void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
 void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
 	CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_node_3d());
 	CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_node_3d());
 
 
@@ -142,7 +147,7 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i
 		return;
 		return;
 	}
 	}
 
 
-	Transform3D gt = cs->get_global_transform();
+	Transform3D gt = initial_transform;
 	Transform3D gi = gt.affine_inverse();
 	Transform3D gi = gt.affine_inverse();
 
 
 	Vector3 ray_from = p_camera->project_ray_origin(p_point);
 	Vector3 ray_from = p_camera->project_ray_origin(p_point);
@@ -184,22 +189,37 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i
 
 
 	if (Object::cast_to<BoxShape3D>(*s)) {
 	if (Object::cast_to<BoxShape3D>(*s)) {
 		Vector3 axis;
 		Vector3 axis;
-		axis[p_id] = 1.0;
+		axis[p_id / 2] = 1.0;
 		Ref<BoxShape3D> bs = s;
 		Ref<BoxShape3D> bs = s;
 		Vector3 ra, rb;
 		Vector3 ra, rb;
-		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
-		float d = ra[p_id] * 2;
-		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
-			d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
-		}
+		int sign = p_id % 2 * -2 + 1;
+		Vector3 initial_size = initial_value;
 
 
-		if (d < 0.001) {
-			d = 0.001;
+		Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * sign, sg[0], sg[1], ra, rb);
+		if (ra[p_id / 2] == 0) {
+			// Point before half of the shape. Needs to be calculated in opposite direction.
+			Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * -sign, sg[0], sg[1], ra, rb);
 		}
 		}
 
 
+		float d = ra[p_id / 2] * sign;
+
 		Vector3 he = bs->get_size();
 		Vector3 he = bs->get_size();
-		he[p_id] = d;
-		bs->set_size(he);
+		he[p_id / 2] = d * 2;
+		if (Node3DEditor::get_singleton()->is_snap_enabled()) {
+			he[p_id / 2] = Math::snapped(he[p_id / 2], Node3DEditor::get_singleton()->get_translate_snap());
+		}
+
+		if (Input::get_singleton()->is_key_pressed(Key::ALT)) {
+			he[p_id / 2] = MAX(he[p_id / 2], 0.001);
+			bs->set_size(he);
+			cs->set_global_position(initial_transform.get_origin());
+		} else {
+			he[p_id / 2] = MAX(he[p_id / 2], -initial_size[p_id / 2] + 0.002);
+			bs->set_size((initial_size + (he - initial_size) * 0.5).abs());
+			Vector3 pos = initial_transform.affine_inverse().xform(initial_transform.get_origin());
+			pos += (bs->get_size() - initial_size) * 0.5 * sign;
+			cs->set_global_position(initial_transform.xform(pos));
+		}
 	}
 	}
 
 
 	if (Object::cast_to<CapsuleShape3D>(*s)) {
 	if (Object::cast_to<CapsuleShape3D>(*s)) {
@@ -273,6 +293,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
 	if (Object::cast_to<BoxShape3D>(*s)) {
 	if (Object::cast_to<BoxShape3D>(*s)) {
 		Ref<BoxShape3D> ss = s;
 		Ref<BoxShape3D> ss = s;
 		if (p_cancel) {
 		if (p_cancel) {
+			cs->set_global_position(initial_transform.get_origin());
 			ss->set_size(p_restore);
 			ss->set_size(p_restore);
 			return;
 			return;
 		}
 		}
@@ -280,7 +301,9 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
 		EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
 		EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
 		ur->create_action(TTR("Change Box Shape Size"));
 		ur->create_action(TTR("Change Box Shape Size"));
 		ur->add_do_method(ss.ptr(), "set_size", ss->get_size());
 		ur->add_do_method(ss.ptr(), "set_size", ss->get_size());
+		ur->add_do_method(cs, "set_position", cs->get_global_position());
 		ur->add_undo_method(ss.ptr(), "set_size", p_restore);
 		ur->add_undo_method(ss.ptr(), "set_size", p_restore);
+		ur->add_undo_method(cs, "set_global_position", initial_transform.get_origin());
 		ur->commit_action();
 		ur->commit_action();
 	}
 	}
 
 
@@ -429,6 +452,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			Vector3 ax;
 			Vector3 ax;
 			ax[i] = bs->get_size()[i] / 2;
 			ax[i] = bs->get_size()[i] / 2;
 			handles.push_back(ax);
 			handles.push_back(ax);
+			handles.push_back(-ax);
 		}
 		}
 
 
 		p_gizmo->add_lines(lines, material);
 		p_gizmo->add_lines(lines, material);

+ 4 - 0
editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h

@@ -36,6 +36,9 @@
 class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
 class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
 	GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
 	GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
 
 
+	Transform3D initial_transform;
+	Variant initial_value;
+
 public:
 public:
 	bool has_gizmo(Node3D *p_spatial) override;
 	bool has_gizmo(Node3D *p_spatial) override;
 	String get_gizmo_name() const override;
 	String get_gizmo_name() const override;
@@ -44,6 +47,7 @@ public:
 
 
 	String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
 	String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
 	Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
 	Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
+	void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override;
 	void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override;
 	void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override;
 	void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override;
 	void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override;
 
 

+ 13 - 0
editor/plugins/node_3d_editor_gizmos.cpp

@@ -115,6 +115,15 @@ Variant EditorNode3DGizmo::get_handle_value(int p_id, bool p_secondary) const {
 	return gizmo_plugin->get_handle_value(this, p_id, p_secondary);
 	return gizmo_plugin->get_handle_value(this, p_id, p_secondary);
 }
 }
 
 
+void EditorNode3DGizmo::begin_handle_action(int p_id, bool p_secondary) {
+	if (GDVIRTUAL_CALL(_begin_handle_action, p_id, p_secondary)) {
+		return;
+	}
+
+	ERR_FAIL_COND(!gizmo_plugin);
+	gizmo_plugin->begin_handle_action(this, p_id, p_secondary);
+}
+
 void EditorNode3DGizmo::set_handle(int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
 void EditorNode3DGizmo::set_handle(int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
 	if (GDVIRTUAL_CALL(_set_handle, p_id, p_secondary, p_camera, p_point)) {
 	if (GDVIRTUAL_CALL(_set_handle, p_id, p_secondary, p_camera, p_point)) {
 		return;
 		return;
@@ -1095,6 +1104,10 @@ Variant EditorNode3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_giz
 	return ret;
 	return ret;
 }
 }
 
 
+void EditorNode3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) {
+	GDVIRTUAL_CALL(_begin_handle_action, Ref<EditorNode3DGizmo>(p_gizmo), p_id, p_secondary);
+}
+
 void EditorNode3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
 void EditorNode3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
 	GDVIRTUAL_CALL(_set_handle, Ref<EditorNode3DGizmo>(p_gizmo), p_id, p_secondary, p_camera, p_point);
 	GDVIRTUAL_CALL(_set_handle, Ref<EditorNode3DGizmo>(p_gizmo), p_id, p_secondary, p_camera, p_point);
 }
 }

+ 4 - 0
editor/plugins/node_3d_editor_gizmos.h

@@ -83,6 +83,7 @@ protected:
 	GDVIRTUAL2RC(String, _get_handle_name, int, bool)
 	GDVIRTUAL2RC(String, _get_handle_name, int, bool)
 	GDVIRTUAL2RC(bool, _is_handle_highlighted, int, bool)
 	GDVIRTUAL2RC(bool, _is_handle_highlighted, int, bool)
 	GDVIRTUAL2RC(Variant, _get_handle_value, int, bool)
 	GDVIRTUAL2RC(Variant, _get_handle_value, int, bool)
+	GDVIRTUAL2(_begin_handle_action, int, bool)
 	GDVIRTUAL4(_set_handle, int, bool, const Camera3D *, Vector2)
 	GDVIRTUAL4(_set_handle, int, bool, const Camera3D *, Vector2)
 	GDVIRTUAL4(_commit_handle, int, bool, Variant, bool)
 	GDVIRTUAL4(_commit_handle, int, bool, Variant, bool)
 
 
@@ -104,6 +105,7 @@ public:
 	virtual bool is_handle_highlighted(int p_id, bool p_secondary) const;
 	virtual bool is_handle_highlighted(int p_id, bool p_secondary) const;
 	virtual String get_handle_name(int p_id, bool p_secondary) const;
 	virtual String get_handle_name(int p_id, bool p_secondary) const;
 	virtual Variant get_handle_value(int p_id, bool p_secondary) const;
 	virtual Variant get_handle_value(int p_id, bool p_secondary) const;
+	virtual void begin_handle_action(int p_id, bool p_secondary);
 	virtual void set_handle(int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point);
 	virtual void set_handle(int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point);
 	virtual void commit_handle(int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false);
 	virtual void commit_handle(int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false);
 
 
@@ -170,6 +172,7 @@ protected:
 	GDVIRTUAL3RC(bool, _is_handle_highlighted, Ref<EditorNode3DGizmo>, int, bool)
 	GDVIRTUAL3RC(bool, _is_handle_highlighted, Ref<EditorNode3DGizmo>, int, bool)
 	GDVIRTUAL3RC(Variant, _get_handle_value, Ref<EditorNode3DGizmo>, int, bool)
 	GDVIRTUAL3RC(Variant, _get_handle_value, Ref<EditorNode3DGizmo>, int, bool)
 
 
+	GDVIRTUAL3(_begin_handle_action, Ref<EditorNode3DGizmo>, int, bool)
 	GDVIRTUAL5(_set_handle, Ref<EditorNode3DGizmo>, int, bool, const Camera3D *, Vector2)
 	GDVIRTUAL5(_set_handle, Ref<EditorNode3DGizmo>, int, bool, const Camera3D *, Vector2)
 	GDVIRTUAL5(_commit_handle, Ref<EditorNode3DGizmo>, int, bool, Variant, bool)
 	GDVIRTUAL5(_commit_handle, Ref<EditorNode3DGizmo>, int, bool, Variant, bool)
 
 
@@ -196,6 +199,7 @@ public:
 	virtual bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const;
 	virtual bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const;
 	virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const;
 	virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const;
 	virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const;
 	virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const;
+	virtual void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary);
 	virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point);
 	virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point);
 	virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false);
 	virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false);
 
 

+ 2 - 1
editor/plugins/node_3d_editor_plugin.cpp

@@ -1775,6 +1775,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 							seg->handles_intersect_ray(camera, _edit.mouse_pos, b->is_shift_pressed(), gizmo_handle, gizmo_secondary);
 							seg->handles_intersect_ray(camera, _edit.mouse_pos, b->is_shift_pressed(), gizmo_handle, gizmo_secondary);
 							if (gizmo_handle != -1) {
 							if (gizmo_handle != -1) {
 								_edit.gizmo = seg;
 								_edit.gizmo = seg;
+								seg->begin_handle_action(gizmo_handle, gizmo_secondary);
 								_edit.gizmo_handle = gizmo_handle;
 								_edit.gizmo_handle = gizmo_handle;
 								_edit.gizmo_handle_secondary = gizmo_secondary;
 								_edit.gizmo_handle_secondary = gizmo_secondary;
 								_edit.gizmo_initial_value = seg->get_handle_value(gizmo_handle, gizmo_secondary);
 								_edit.gizmo_initial_value = seg->get_handle_value(gizmo_handle, gizmo_secondary);
@@ -2152,7 +2153,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 		}
 		}
 
 
 		if (_edit.mode == TRANSFORM_NONE) {
 		if (_edit.mode == TRANSFORM_NONE) {
-			if (_edit.gizmo.is_valid()) {
+			if (_edit.gizmo.is_valid() && (k->get_keycode() == Key::ESCAPE || k->get_keycode() == Key::BACKSPACE)) {
 				// Restore.
 				// Restore.
 				_edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, true);
 				_edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, true);
 				_edit.gizmo = Ref<EditorNode3DGizmo>();
 				_edit.gizmo = Ref<EditorNode3DGizmo>();