summaryrefslogtreecommitdiffstats
path: root/editor/plugins/skeleton_3d_editor_plugin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins/skeleton_3d_editor_plugin.cpp')
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp173
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);