diff options
Diffstat (limited to 'editor/plugins/skeleton_3d_editor_plugin.cpp')
-rw-r--r-- | editor/plugins/skeleton_3d_editor_plugin.cpp | 173 |
1 files changed, 143 insertions, 30 deletions
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 99cb03cdcd..64b9522864 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -52,7 +52,7 @@ #include "scene/resources/skeleton_profile.h" #include "scene/resources/surface_tool.h" -void BoneTransformEditor::create_editors() { +void BonePropertiesEditor::create_editors() { section = memnew(EditorInspectorSection); section->setup("trf_properties", label, this, Color(0.0f, 0.0f, 0.0f), true); section->unfold(); @@ -61,7 +61,7 @@ void BoneTransformEditor::create_editors() { enabled_checkbox = memnew(EditorPropertyCheck()); enabled_checkbox->set_label("Pose Enabled"); enabled_checkbox->set_selectable(false); - enabled_checkbox->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed)); + enabled_checkbox->connect("property_changed", callable_mp(this, &BonePropertiesEditor::_value_changed)); section->get_vbox()->add_child(enabled_checkbox); // Position property. @@ -69,8 +69,8 @@ void BoneTransformEditor::create_editors() { position_property->setup(-10000, 10000, 0.001, true); position_property->set_label("Position"); position_property->set_selectable(false); - position_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed)); - position_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed)); + position_property->connect("property_changed", callable_mp(this, &BonePropertiesEditor::_value_changed)); + position_property->connect("property_keyed", callable_mp(this, &BonePropertiesEditor::_property_keyed)); section->get_vbox()->add_child(position_property); // Rotation property. @@ -78,8 +78,8 @@ void BoneTransformEditor::create_editors() { rotation_property->setup(-10000, 10000, 0.001, true); rotation_property->set_label("Rotation"); rotation_property->set_selectable(false); - rotation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed)); - rotation_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed)); + rotation_property->connect("property_changed", callable_mp(this, &BonePropertiesEditor::_value_changed)); + rotation_property->connect("property_keyed", callable_mp(this, &BonePropertiesEditor::_property_keyed)); section->get_vbox()->add_child(rotation_property); // Scale property. @@ -87,8 +87,8 @@ void BoneTransformEditor::create_editors() { scale_property->setup(-10000, 10000, 0.001, true, true); scale_property->set_label("Scale"); scale_property->set_selectable(false); - scale_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed)); - scale_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed)); + scale_property->connect("property_changed", callable_mp(this, &BonePropertiesEditor::_value_changed)); + scale_property->connect("property_keyed", callable_mp(this, &BonePropertiesEditor::_property_keyed)); section->get_vbox()->add_child(scale_property); // Transform/Matrix section. @@ -102,50 +102,136 @@ void BoneTransformEditor::create_editors() { rest_matrix->set_label("Transform"); rest_matrix->set_selectable(false); rest_section->get_vbox()->add_child(rest_matrix); + + // Bone Metadata property + meta_section = memnew(EditorInspectorSection); + meta_section->setup("bone_meta", TTR("Bone Metadata"), this, Color(.0f, .0f, .0f), true); + section->get_vbox()->add_child(meta_section); + + add_metadata_button = EditorInspector::create_inspector_action_button(TTR("Add Bone Metadata")); + add_metadata_button->connect(SceneStringName(pressed), callable_mp(this, &BonePropertiesEditor::_show_add_meta_dialog)); + section->get_vbox()->add_child(add_metadata_button); + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->connect("version_changed", callable_mp(this, &BonePropertiesEditor::_update_properties)); + undo_redo->connect("history_changed", callable_mp(this, &BonePropertiesEditor::_update_properties)); } -void BoneTransformEditor::_notification(int p_what) { +void BonePropertiesEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { const Color section_color = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)); section->set_bg_color(section_color); rest_section->set_bg_color(section_color); + add_metadata_button->set_icon(get_editor_theme_icon(SNAME("Add"))); } break; } } -void BoneTransformEditor::_value_changed(const String &p_property, const Variant &p_value, const String &p_name, bool p_changing) { - if (updating) { +void BonePropertiesEditor::_value_changed(const String &p_property, const Variant &p_value, const String &p_name, bool p_changing) { + if (updating || !skeleton) { + return; + } + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS); + undo_redo->add_undo_property(skeleton, p_property, skeleton->get(p_property)); + undo_redo->add_do_property(skeleton, p_property, p_value); + + Skeleton3DEditor *se = Skeleton3DEditor::get_singleton(); + if (se) { + undo_redo->add_do_method(se, "update_joint_tree"); + undo_redo->add_undo_method(se, "update_joint_tree"); + } + + undo_redo->commit_action(); +} + +void BonePropertiesEditor::_meta_changed(const String &p_property, const Variant &p_value, const String &p_name, bool p_changing) { + if (!skeleton || p_property.get_slicec('/', 2) != "bone_meta") { return; } - if (skeleton) { - EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS); - undo_redo->add_undo_property(skeleton, p_property, skeleton->get(p_property)); - undo_redo->add_do_property(skeleton, p_property, p_value); - - Skeleton3DEditor *se = Skeleton3DEditor::get_singleton(); - if (se) { - undo_redo->add_do_method(se, "update_joint_tree"); - undo_redo->add_undo_method(se, "update_joint_tree"); - } - undo_redo->commit_action(); + int bone = p_property.get_slicec('/', 1).to_int(); + if (bone >= skeleton->get_bone_count()) { + return; } + + String key = p_property.get_slicec('/', 3); + if (!skeleton->has_bone_meta(1, key)) { + return; + } + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(vformat(TTR("Modify metadata '%s' for bone '%s'"), key, skeleton->get_bone_name(bone))); + undo_redo->add_do_property(skeleton, p_property, p_value); + undo_redo->add_do_method(meta_editors[p_property], "update_property"); + undo_redo->add_undo_property(skeleton, p_property, skeleton->get_bone_meta(bone, key)); + undo_redo->add_undo_method(meta_editors[p_property], "update_property"); + undo_redo->commit_action(); } -BoneTransformEditor::BoneTransformEditor(Skeleton3D *p_skeleton) : +void BonePropertiesEditor::_meta_deleted(const String &p_property) { + if (!skeleton || p_property.get_slicec('/', 2) != "bone_meta") { + return; + } + + int bone = p_property.get_slicec('/', 1).to_int(); + if (bone >= skeleton->get_bone_count()) { + return; + } + + String key = p_property.get_slicec('/', 3); + if (!skeleton->has_bone_meta(1, key)) { + return; + } + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(vformat(TTR("Remove metadata '%s' from bone '%s'"), key, skeleton->get_bone_name(bone))); + undo_redo->add_do_property(skeleton, p_property, Variant()); + undo_redo->add_undo_property(skeleton, p_property, skeleton->get_bone_meta(bone, key)); + undo_redo->commit_action(); + + emit_signal(SNAME("property_deleted"), p_property); +} + +void BonePropertiesEditor::_show_add_meta_dialog() { + if (!add_meta_dialog) { + add_meta_dialog = memnew(AddMetadataDialog()); + add_meta_dialog->connect(SceneStringName(confirmed), callable_mp(this, &BonePropertiesEditor::_add_meta_confirm)); + add_child(add_meta_dialog); + } + + int bone = Skeleton3DEditor::get_singleton()->get_selected_bone(); + StringName dialog_title = skeleton->get_bone_name(bone); + + List<StringName> existing_meta_keys; + skeleton->get_bone_meta_list(bone, &existing_meta_keys); + add_meta_dialog->open(dialog_title, existing_meta_keys); +} + +void BonePropertiesEditor::_add_meta_confirm() { + int bone = Skeleton3DEditor::get_singleton()->get_selected_bone(); + String name = add_meta_dialog->get_meta_name(); + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(vformat(TTR("Add metadata '%s' to bone '%s'"), name, skeleton->get_bone_name(bone))); + undo_redo->add_do_method(skeleton, "set_bone_meta", bone, name, add_meta_dialog->get_meta_defval()); + undo_redo->add_undo_method(skeleton, "set_bone_meta", bone, name, Variant()); + undo_redo->commit_action(); +} + +BonePropertiesEditor::BonePropertiesEditor(Skeleton3D *p_skeleton) : skeleton(p_skeleton) { create_editors(); } -void BoneTransformEditor::set_keyable(const bool p_keyable) { +void BonePropertiesEditor::set_keyable(const bool p_keyable) { position_property->set_keying(p_keyable); rotation_property->set_keying(p_keyable); scale_property->set_keying(p_keyable); } -void BoneTransformEditor::set_target(const String &p_prop) { +void BonePropertiesEditor::set_target(const String &p_prop) { enabled_checkbox->set_object_and_property(skeleton, p_prop + "enabled"); enabled_checkbox->update_property(); @@ -162,7 +248,7 @@ void BoneTransformEditor::set_target(const String &p_prop) { rest_matrix->update_property(); } -void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance) { +void BonePropertiesEditor::_property_keyed(const String &p_path, bool p_advance) { AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor(); if (!te || !te->has_keying()) { return; @@ -183,16 +269,17 @@ void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance) } } -void BoneTransformEditor::_update_properties() { +void BonePropertiesEditor::_update_properties() { if (!skeleton) { return; } int selected = Skeleton3DEditor::get_singleton()->get_selected_bone(); List<PropertyInfo> props; + HashSet<StringName> meta_seen; skeleton->get_property_list(&props); for (const PropertyInfo &E : props) { PackedStringArray split = E.name.split("/"); - if (split.size() == 3 && split[0] == "bones") { + if (split.size() >= 3 && split[0] == "bones") { if (split[1].to_int() == selected) { if (split[2] == "enabled") { enabled_checkbox->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY); @@ -224,9 +311,35 @@ void BoneTransformEditor::_update_properties() { rest_matrix->update_editor_property_status(); rest_matrix->queue_redraw(); } + if (split[2] == "bone_meta") { + meta_seen.insert(E.name); + if (!meta_editors.find(E.name)) { + EditorProperty *editor = EditorInspectorDefaultPlugin::get_editor_for_property(skeleton, E.type, E.name, PROPERTY_HINT_NONE, "", E.usage); + editor->set_label(split[3]); + editor->set_object_and_property(skeleton, E.name); + editor->set_deletable(true); + editor->set_selectable(false); + editor->connect("property_changed", callable_mp(this, &BonePropertiesEditor::_meta_changed)); + editor->connect("property_deleted", callable_mp(this, &BonePropertiesEditor::_meta_deleted)); + + meta_section->get_vbox()->add_child(editor); + editor->update_property(); + editor->update_editor_property_status(); + editor->queue_redraw(); + + meta_editors[E.name] = editor; + } + } } } } + // UI for any bone metadata prop not seen during the iteration has to be deleted + for (KeyValue<StringName, EditorProperty *> iter : meta_editors) { + if (!meta_seen.has(iter.key)) { + callable_mp((Node *)meta_section->get_vbox(), &Node::remove_child).call_deferred(iter.value); + meta_editors.remove(meta_editors.find(iter.key)); + } + } } Skeleton3DEditor *Skeleton3DEditor::singleton = nullptr; @@ -992,7 +1105,7 @@ void Skeleton3DEditor::create_editors() { SET_DRAG_FORWARDING_GCD(joint_tree, Skeleton3DEditor); s_con->add_child(joint_tree); - pose_editor = memnew(BoneTransformEditor(skeleton)); + pose_editor = memnew(BonePropertiesEditor(skeleton)); pose_editor->set_label(TTR("Bone Transform")); pose_editor->set_visible(false); add_child(pose_editor); |