summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPouleyKetchoupp <pouleyketchoup@gmail.com>2021-08-12 11:26:47 -0700
committerPouleyKetchoupp <pouleyketchoup@gmail.com>2021-08-19 10:31:19 -0700
commit645bc94bfcb0d494e9d53e29aee1419800adcd4e (patch)
tree1ff9fd17f54d9490effc9bb09f0610bad3577b3c
parent93dac1c7db0837eba82831e6391a022d454b67f9 (diff)
Fix capsule height/radius setters with linked properties
Capsule height and radius setters can modify each other, rather than using clamping, to avoid cases where values are not set correctly when loading a scene (depending on the order of properties). Inspector undo/redo: Added the possibility to link properties together in the editor, so they can be undone together, for cases where a property can modify another one. Gizmo undo/redo: Capsule handles pass both radius and height values so they can be undone together.
-rw-r--r--core/object/class_db.cpp14
-rw-r--r--core/object/class_db.h1
-rw-r--r--core/object/object.h5
-rw-r--r--editor/editor_inspector.cpp7
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp19
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp15
-rw-r--r--scene/resources/capsule_shape_2d.cpp12
-rw-r--r--scene/resources/capsule_shape_3d.cpp6
8 files changed, 55 insertions, 24 deletions
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index c58fe7bc24..75145e1b65 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -1068,6 +1068,20 @@ void ClassDB::set_property_default_value(const StringName &p_class, const String
default_values[p_class][p_name] = p_default;
}
+void ClassDB::add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property) {
+#ifdef TOOLS_ENABLED
+ OBJTYPE_WLOCK;
+ ClassInfo *type = classes.getptr(p_class);
+ ERR_FAIL_COND(!type);
+
+ ERR_FAIL_COND(!type->property_map.has(p_property));
+ ERR_FAIL_COND(!type->property_map.has(p_linked_property));
+
+ PropertyInfo &pinfo = type->property_map[p_property];
+ pinfo.linked_properties.push_back(p_linked_property);
+#endif
+}
+
void ClassDB::get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
OBJTYPE_RLOCK;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 6a7b39c230..8add0285f7 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -354,6 +354,7 @@ public:
static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix = "");
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
static void set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default);
+ static void add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property);
static void get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr);
static bool get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance = false, const Object *p_validator = nullptr);
static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = nullptr);
diff --git a/core/object/object.h b/core/object/object.h
index 63d38120f6..94531f1cd0 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -143,6 +143,7 @@ enum PropertyUsageFlags {
#define ADD_PROPERTY_DEFAULT(m_property, m_default) ::ClassDB::set_property_default_value(get_class_static(), m_property, m_default)
#define ADD_GROUP(m_name, m_prefix) ::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
#define ADD_SUBGROUP(m_name, m_prefix) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
+#define ADD_LINKED_PROPERTY(m_property, m_linked_property) ::ClassDB::add_linked_property(get_class_static(), m_property, m_linked_property)
struct PropertyInfo {
Variant::Type type = Variant::NIL;
@@ -152,6 +153,10 @@ struct PropertyInfo {
String hint_string;
uint32_t usage = PROPERTY_USAGE_DEFAULT;
+#ifdef TOOLS_ENABLED
+ Vector<String> linked_properties;
+#endif
+
_FORCE_INLINE_ PropertyInfo added_usage(uint32_t p_fl) const {
PropertyInfo pi = *this;
pi.usage |= p_fl;
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 9de8b0451a..b3ce11028b 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -2243,6 +2243,13 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
undo_redo->add_do_property(object, p_name, p_value);
undo_redo->add_undo_property(object, p_name, object->get(p_name));
+ PropertyInfo prop_info;
+ if (ClassDB::get_property_info(object->get_class_name(), p_name, &prop_info)) {
+ for (const String &linked_prop : prop_info.linked_properties) {
+ undo_redo->add_undo_property(object, linked_prop, object->get(linked_prop));
+ }
+ }
+
Variant v_undo_redo = (Object *)undo_redo;
Variant v_object = object;
Variant v_name = p_name;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index 486f947e43..c2684305ef 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -50,12 +50,7 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const {
switch (shape_type) {
case CAPSULE_SHAPE: {
Ref<CapsuleShape2D> capsule = node->get_shape();
-
- if (idx == 0) {
- return capsule->get_radius();
- } else if (idx == 1) {
- return capsule->get_height();
- }
+ return Vector2(capsule->get_radius(), capsule->get_height());
} break;
@@ -209,17 +204,17 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
case CAPSULE_SHAPE: {
Ref<CapsuleShape2D> capsule = node->get_shape();
+ Vector2 values = p_org;
+
if (idx == 0) {
undo_redo->add_do_method(capsule.ptr(), "set_radius", capsule->get_radius());
- undo_redo->add_do_method(canvas_item_editor, "update_viewport");
- undo_redo->add_undo_method(capsule.ptr(), "set_radius", p_org);
- undo_redo->add_do_method(canvas_item_editor, "update_viewport");
} else if (idx == 1) {
undo_redo->add_do_method(capsule.ptr(), "set_height", capsule->get_height());
- undo_redo->add_do_method(canvas_item_editor, "update_viewport");
- undo_redo->add_undo_method(capsule.ptr(), "set_height", p_org);
- undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
}
+ undo_redo->add_do_method(canvas_item_editor, "update_viewport");
+ undo_redo->add_undo_method(capsule.ptr(), "set_radius", values[0]);
+ undo_redo->add_undo_method(capsule.ptr(), "set_height", values[1]);
+ undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} break;
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 38510ff81e..a42f94ed3d 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -4114,7 +4114,7 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p
if (Object::cast_to<CapsuleShape3D>(*s)) {
Ref<CapsuleShape3D> cs2 = s;
- return p_id == 0 ? cs2->get_radius() : cs2->get_height();
+ return Vector2(cs2->get_radius(), cs2->get_height());
}
if (Object::cast_to<CylinderShape3D>(*s)) {
@@ -4261,12 +4261,11 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
if (Object::cast_to<CapsuleShape3D>(*s)) {
Ref<CapsuleShape3D> ss = s;
+ Vector2 values = p_restore;
+
if (p_cancel) {
- if (p_id == 0) {
- ss->set_radius(p_restore);
- } else {
- ss->set_height(p_restore);
- }
+ ss->set_radius(values[0]);
+ ss->set_height(values[1]);
return;
}
@@ -4274,12 +4273,12 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
if (p_id == 0) {
ur->create_action(TTR("Change Capsule 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 Capsule Shape Height"));
ur->add_do_method(ss.ptr(), "set_height", ss->get_height());
- ur->add_undo_method(ss.ptr(), "set_height", p_restore);
}
+ ur->add_undo_method(ss.ptr(), "set_radius", values[0]);
+ ur->add_undo_method(ss.ptr(), "set_height", values[1]);
ur->commit_action();
}
diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp
index 596fa70f15..0818e4fd99 100644
--- a/scene/resources/capsule_shape_2d.cpp
+++ b/scene/resources/capsule_shape_2d.cpp
@@ -59,7 +59,10 @@ void CapsuleShape2D::_update_shape() {
}
void CapsuleShape2D::set_radius(real_t p_radius) {
- radius = MIN(p_radius, height * 0.5);
+ radius = p_radius;
+ if (radius > height * 0.5) {
+ height = radius * 2.0;
+ }
_update_shape();
}
@@ -68,7 +71,10 @@ real_t CapsuleShape2D::get_radius() const {
}
void CapsuleShape2D::set_height(real_t p_height) {
- height = MAX(p_height, radius * 2);
+ height = p_height;
+ if (radius > height * 0.5) {
+ radius = height * 0.5;
+ }
_update_shape();
}
@@ -105,6 +111,8 @@ void CapsuleShape2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius"), "set_radius", "get_radius");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height"), "set_height", "get_height");
+ ADD_LINKED_PROPERTY("radius", "height");
+ ADD_LINKED_PROPERTY("height", "radius");
}
CapsuleShape2D::CapsuleShape2D() :
diff --git a/scene/resources/capsule_shape_3d.cpp b/scene/resources/capsule_shape_3d.cpp
index e267941d6a..afec7b1877 100644
--- a/scene/resources/capsule_shape_3d.cpp
+++ b/scene/resources/capsule_shape_3d.cpp
@@ -81,7 +81,7 @@ void CapsuleShape3D::_update_shape() {
void CapsuleShape3D::set_radius(float p_radius) {
radius = p_radius;
if (radius > height * 0.5) {
- radius = height * 0.5;
+ height = radius * 2.0;
}
_update_shape();
notify_change_to_owners();
@@ -94,7 +94,7 @@ float CapsuleShape3D::get_radius() const {
void CapsuleShape3D::set_height(float p_height) {
height = p_height;
if (radius > height * 0.5) {
- height = radius * 2;
+ radius = height * 0.5;
}
_update_shape();
notify_change_to_owners();
@@ -112,6 +112,8 @@ void CapsuleShape3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,4096,0.001"), "set_radius", "get_radius");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,4096,0.001"), "set_height", "get_height");
+ ADD_LINKED_PROPERTY("radius", "height");
+ ADD_LINKED_PROPERTY("height", "radius");
}
CapsuleShape3D::CapsuleShape3D() :