4747#include " scene/3d/physics/physics_body_3d.h"
4848#include " scene/gui/separator.h"
4949#include " scene/gui/texture_rect.h"
50+ #include " scene/property_utils.h"
5051#include " scene/resources/3d/capsule_shape_3d.h"
5152#include " scene/resources/skeleton_profile.h"
5253#include " scene/resources/surface_tool.h"
@@ -65,7 +66,7 @@ void BoneTransformEditor::create_editors() {
6566
6667 // Position property.
6768 position_property = memnew (EditorPropertyVector3 ());
68- position_property->setup (-10000 , 10000 , 0 .001f , true );
69+ position_property->setup (-10000 , 10000 , 0.001 , true );
6970 position_property->set_label (" Position" );
7071 position_property->set_selectable (false );
7172 position_property->connect (" property_changed" , callable_mp (this , &BoneTransformEditor::_value_changed));
@@ -74,7 +75,7 @@ void BoneTransformEditor::create_editors() {
7475
7576 // Rotation property.
7677 rotation_property = memnew (EditorPropertyQuaternion ());
77- rotation_property->setup (-10000 , 10000 , 0 .001f , true );
78+ rotation_property->setup (-10000 , 10000 , 0.001 , true );
7879 rotation_property->set_label (" Rotation" );
7980 rotation_property->set_selectable (false );
8081 rotation_property->connect (" property_changed" , callable_mp (this , &BoneTransformEditor::_value_changed));
@@ -83,7 +84,7 @@ void BoneTransformEditor::create_editors() {
8384
8485 // Scale property.
8586 scale_property = memnew (EditorPropertyVector3 ());
86- scale_property->setup (-10000 , 10000 , 0 .001f , true );
87+ scale_property->setup (-10000 , 10000 , 0.001 , true , true );
8788 scale_property->set_label (" Scale" );
8889 scale_property->set_selectable (false );
8990 scale_property->connect (" property_changed" , callable_mp (this , &BoneTransformEditor::_value_changed));
@@ -97,7 +98,7 @@ void BoneTransformEditor::create_editors() {
9798
9899 // Transform/Matrix property.
99100 rest_matrix = memnew (EditorPropertyTransform3D ());
100- rest_matrix->setup (-10000 , 10000 , 0 .001f , true );
101+ rest_matrix->setup (-10000 , 10000 , 0.001 , true );
101102 rest_matrix->set_label (" Transform" );
102103 rest_matrix->set_selectable (false );
103104 rest_section->get_vbox ()->add_child (rest_matrix);
@@ -122,6 +123,13 @@ void BoneTransformEditor::_value_changed(const String &p_property, const Variant
122123 undo_redo->create_action (TTR (" Set Bone Transform" ), UndoRedo::MERGE_ENDS);
123124 undo_redo->add_undo_property (skeleton, p_property, skeleton->get (p_property));
124125 undo_redo->add_do_property (skeleton, p_property, p_value);
126+
127+ Skeleton3DEditor *se = Skeleton3DEditor::get_singleton ();
128+ if (se) {
129+ undo_redo->add_do_method (se, " update_joint_tree" );
130+ undo_redo->add_undo_method (se, " update_joint_tree" );
131+ }
132+
125133 undo_redo->commit_action ();
126134 }
127135}
@@ -189,26 +197,31 @@ void BoneTransformEditor::_update_properties() {
189197 if (split[2 ] == " enabled" ) {
190198 enabled_checkbox->set_read_only (E.usage & PROPERTY_USAGE_READ_ONLY);
191199 enabled_checkbox->update_property ();
200+ enabled_checkbox->update_editor_property_status ();
192201 enabled_checkbox->queue_redraw ();
193202 }
194203 if (split[2 ] == " position" ) {
195204 position_property->set_read_only (E.usage & PROPERTY_USAGE_READ_ONLY);
196205 position_property->update_property ();
206+ position_property->update_editor_property_status ();
197207 position_property->queue_redraw ();
198208 }
199209 if (split[2 ] == " rotation" ) {
200210 rotation_property->set_read_only (E.usage & PROPERTY_USAGE_READ_ONLY);
201211 rotation_property->update_property ();
212+ rotation_property->update_editor_property_status ();
202213 rotation_property->queue_redraw ();
203214 }
204215 if (split[2 ] == " scale" ) {
205216 scale_property->set_read_only (E.usage & PROPERTY_USAGE_READ_ONLY);
206217 scale_property->update_property ();
218+ scale_property->update_editor_property_status ();
207219 scale_property->queue_redraw ();
208220 }
209221 if (split[2 ] == " rest" ) {
210222 rest_matrix->set_read_only (E.usage & PROPERTY_USAGE_READ_ONLY);
211223 rest_matrix->update_property ();
224+ rest_matrix->update_editor_property_status ();
212225 rest_matrix->queue_redraw ();
213226 }
214227 }
@@ -232,6 +245,11 @@ void Skeleton3DEditor::set_bone_options_enabled(const bool p_bone_options_enable
232245 skeleton_options->get_popup ()->set_item_disabled (SKELETON_OPTION_SELECTED_POSES_TO_RESTS, !p_bone_options_enabled);
233246};
234247
248+ void Skeleton3DEditor::_bind_methods () {
249+ ClassDB::bind_method (D_METHOD (" update_all" ), &Skeleton3DEditor::update_all);
250+ ClassDB::bind_method (D_METHOD (" update_joint_tree" ), &Skeleton3DEditor::update_joint_tree);
251+ }
252+
235253void Skeleton3DEditor::_on_click_skeleton_option (int p_skeleton_option) {
236254 if (!skeleton) {
237255 return ;
@@ -294,6 +312,10 @@ void Skeleton3DEditor::reset_pose(const bool p_all_bones) {
294312 ur->add_undo_method (skeleton, " set_bone_pose_scale" , selected_bone, skeleton->get_bone_pose_scale (selected_bone));
295313 ur->add_do_method (skeleton, " reset_bone_pose" , selected_bone);
296314 }
315+
316+ ur->add_undo_method (this , " update_joint_tree" );
317+ ur->add_do_method (this , " update_joint_tree" );
318+
297319 ur->commit_action ();
298320}
299321
@@ -357,6 +379,10 @@ void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) {
357379 ur->add_do_method (skeleton, " set_bone_rest" , selected_bone, skeleton->get_bone_pose (selected_bone));
358380 ur->add_undo_method (skeleton, " set_bone_rest" , selected_bone, skeleton->get_bone_rest (selected_bone));
359381 }
382+
383+ ur->add_undo_method (this , " update_joint_tree" );
384+ ur->add_do_method (this , " update_joint_tree" );
385+
360386 ur->commit_action ();
361387}
362388
@@ -620,9 +646,12 @@ void Skeleton3DEditor::move_skeleton_bone(NodePath p_skeleton_path, int32_t p_se
620646 }
621647 ur->add_undo_method (skeleton_node, " set_bone_parent" , p_selected_boneidx, skeleton_node->get_bone_parent (p_selected_boneidx));
622648 ur->add_do_method (skeleton_node, " set_bone_parent" , p_selected_boneidx, p_target_boneidx);
649+
650+ ur->add_undo_method (this , " update_joint_tree" );
651+ ur->add_do_method (this , " update_joint_tree" );
652+
623653 skeleton_node->set_bone_parent (p_selected_boneidx, p_target_boneidx);
624654
625- update_joint_tree ();
626655 ur->commit_action ();
627656}
628657
@@ -655,6 +684,107 @@ void Skeleton3DEditor::_joint_tree_selection_changed() {
655684void Skeleton3DEditor::_joint_tree_rmb_select (const Vector2 &p_pos, MouseButton p_button) {
656685}
657686
687+ void Skeleton3DEditor::_joint_tree_button_clicked (Object *p_item, int p_column, int p_id, MouseButton p_button) {
688+ if (!skeleton) {
689+ return ;
690+ }
691+
692+ TreeItem *tree_item = Object::cast_to<TreeItem>(p_item);
693+ if (tree_item) {
694+ String tree_item_metadata = tree_item->get_metadata (0 );
695+
696+ String bone_enabled_property = tree_item_metadata + " /enabled" ;
697+ String bone_parent_property = tree_item_metadata + " /parent" ;
698+ String bone_name_property = tree_item_metadata + " /name" ;
699+ String bone_position_property = tree_item_metadata + " /position" ;
700+ String bone_rotation_property = tree_item_metadata + " /rotation" ;
701+ String bone_scale_property = tree_item_metadata + " /scale" ;
702+ String bone_rest_property = tree_item_metadata + " /rest" ;
703+
704+ Variant current_enabled = skeleton->get (bone_enabled_property);
705+ Variant current_parent = skeleton->get (bone_parent_property);
706+ Variant current_name = skeleton->get (bone_name_property);
707+ Variant current_position = skeleton->get (bone_position_property);
708+ Variant current_rotation = skeleton->get (bone_rotation_property);
709+ Variant current_scale = skeleton->get (bone_scale_property);
710+ Variant current_rest = skeleton->get (bone_rest_property);
711+
712+ EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton ();
713+ ur->create_action (TTR (" Revert Bone" ));
714+
715+ bool can_revert_enabled = EditorPropertyRevert::can_property_revert (skeleton, bone_enabled_property, ¤t_enabled);
716+ if (can_revert_enabled) {
717+ bool is_valid = false ;
718+ Variant new_enabled = EditorPropertyRevert::get_property_revert_value (skeleton, bone_enabled_property, &is_valid);
719+ if (is_valid) {
720+ ur->add_undo_method (skeleton, " set" , bone_enabled_property, current_enabled);
721+ ur->add_do_method (skeleton, " set" , bone_enabled_property, new_enabled);
722+ }
723+ }
724+
725+ bool can_revert_parent = EditorPropertyRevert::can_property_revert (skeleton, bone_parent_property, ¤t_parent);
726+ if (can_revert_parent) {
727+ bool is_valid = false ;
728+ Variant new_parent = EditorPropertyRevert::get_property_revert_value (skeleton, bone_parent_property, &is_valid);
729+ if (is_valid) {
730+ ur->add_undo_method (skeleton, " set" , bone_parent_property, current_parent);
731+ ur->add_do_method (skeleton, " set" , bone_parent_property, new_parent);
732+ }
733+ }
734+ bool can_revert_name = EditorPropertyRevert::can_property_revert (skeleton, bone_name_property, ¤t_name);
735+ if (can_revert_name) {
736+ bool is_valid = false ;
737+ Variant new_name = EditorPropertyRevert::get_property_revert_value (skeleton, bone_name_property, &is_valid);
738+ if (is_valid) {
739+ ur->add_undo_method (skeleton, " set" , bone_name_property, current_name);
740+ ur->add_do_method (skeleton, " set" , bone_name_property, new_name);
741+ }
742+ }
743+ bool can_revert_position = EditorPropertyRevert::can_property_revert (skeleton, bone_position_property, ¤t_position);
744+ if (can_revert_position) {
745+ bool is_valid = false ;
746+ Variant new_position = EditorPropertyRevert::get_property_revert_value (skeleton, bone_position_property, &is_valid);
747+ if (is_valid) {
748+ ur->add_undo_method (skeleton, " set" , bone_position_property, current_position);
749+ ur->add_do_method (skeleton, " set" , bone_position_property, new_position);
750+ }
751+ }
752+ bool can_revert_rotation = EditorPropertyRevert::can_property_revert (skeleton, bone_rotation_property, ¤t_rotation);
753+ if (can_revert_rotation) {
754+ bool is_valid = false ;
755+ Variant new_rotation = EditorPropertyRevert::get_property_revert_value (skeleton, bone_rotation_property, &is_valid);
756+ if (is_valid) {
757+ ur->add_undo_method (skeleton, " set" , bone_rotation_property, current_rotation);
758+ ur->add_do_method (skeleton, " set" , bone_rotation_property, new_rotation);
759+ }
760+ }
761+ bool can_revert_scale = EditorPropertyRevert::can_property_revert (skeleton, bone_scale_property, ¤t_scale);
762+ if (can_revert_scale) {
763+ bool is_valid = false ;
764+ Variant new_scale = EditorPropertyRevert::get_property_revert_value (skeleton, bone_scale_property, &is_valid);
765+ if (is_valid) {
766+ ur->add_undo_method (skeleton, " set" , bone_scale_property, current_scale);
767+ ur->add_do_method (skeleton, " set" , bone_scale_property, new_scale);
768+ }
769+ }
770+ bool can_revert_rest = EditorPropertyRevert::can_property_revert (skeleton, bone_rest_property, ¤t_rest);
771+ if (can_revert_rest) {
772+ bool is_valid = false ;
773+ Variant new_rest = EditorPropertyRevert::get_property_revert_value (skeleton, bone_rest_property, &is_valid);
774+ if (is_valid) {
775+ ur->add_undo_method (skeleton, " set" , bone_rest_property, current_rest);
776+ ur->add_do_method (skeleton, " set" , bone_rest_property, new_rest);
777+ }
778+ }
779+
780+ ur->add_undo_method (this , " update_all" );
781+ ur->add_do_method (this , " update_all" );
782+
783+ ur->commit_action ();
784+ }
785+ return ;
786+ }
787+
658788void Skeleton3DEditor::_update_properties () {
659789 if (pose_editor) {
660790 pose_editor->_update_properties ();
@@ -693,15 +823,52 @@ void Skeleton3DEditor::update_joint_tree() {
693823 joint_item->set_selectable (0 , true );
694824 joint_item->set_metadata (0 , " bones/" + itos (current_bone_idx));
695825
826+ String bone_enabled_property = " bones/" + itos (current_bone_idx) + " /enabled" ;
827+ String bone_parent_property = " bones/" + itos (current_bone_idx) + " /parent" ;
828+ String bone_name_property = " bones/" + itos (current_bone_idx) + " /name" ;
829+ String bone_position_property = " bones/" + itos (current_bone_idx) + " /position" ;
830+ String bone_rotation_property = " bones/" + itos (current_bone_idx) + " /rotation" ;
831+ String bone_scale_property = " bones/" + itos (current_bone_idx) + " /scale" ;
832+ String bone_rest_property = " bones/" + itos (current_bone_idx) + " /rest" ;
833+
834+ Variant current_enabled = skeleton->get (bone_enabled_property);
835+ Variant current_parent = skeleton->get (bone_parent_property);
836+ Variant current_name = skeleton->get (bone_name_property);
837+ Variant current_position = skeleton->get (bone_position_property);
838+ Variant current_rotation = skeleton->get (bone_rotation_property);
839+ Variant current_scale = skeleton->get (bone_scale_property);
840+ Variant current_rest = skeleton->get (bone_rest_property);
841+
842+ bool can_revert_enabled = EditorPropertyRevert::can_property_revert (skeleton, bone_enabled_property, ¤t_enabled);
843+ bool can_revert_parent = EditorPropertyRevert::can_property_revert (skeleton, bone_parent_property, ¤t_parent);
844+ bool can_revert_name = EditorPropertyRevert::can_property_revert (skeleton, bone_name_property, ¤t_name);
845+ bool can_revert_position = EditorPropertyRevert::can_property_revert (skeleton, bone_position_property, ¤t_position);
846+ bool can_revert_rotation = EditorPropertyRevert::can_property_revert (skeleton, bone_rotation_property, ¤t_rotation);
847+ bool can_revert_scale = EditorPropertyRevert::can_property_revert (skeleton, bone_scale_property, ¤t_scale);
848+ bool can_revert_rest = EditorPropertyRevert::can_property_revert (skeleton, bone_rest_property, ¤t_rest);
849+
850+ if (can_revert_enabled || can_revert_parent || can_revert_name || can_revert_position || can_revert_rotation || can_revert_scale || can_revert_rest) {
851+ joint_item->add_button (0 , get_editor_theme_icon (SNAME (" ReloadSmall" )), JOINT_BUTTON_REVERT, false , TTR (" Revert" ));
852+ }
853+
696854 // Add the bone's children to the list of bones to be processed.
697855 Vector<int > current_bone_child_bones = skeleton->get_bone_children (current_bone_idx);
698856 int child_bone_size = current_bone_child_bones.size ();
699857 for (int i = 0 ; i < child_bone_size; i++) {
700858 bones_to_process.push_back (current_bone_child_bones[i]);
701859 }
860+
861+ if (current_bone_idx == selected_bone) {
862+ joint_item->select (0 );
863+ }
702864 }
703865}
704866
867+ void Skeleton3DEditor::update_all () {
868+ _update_properties ();
869+ update_joint_tree ();
870+ }
871+
705872void Skeleton3DEditor::create_editors () {
706873 set_h_size_flags (SIZE_EXPAND_FILL);
707874 set_focus_mode (FOCUS_ALL);
@@ -840,6 +1007,7 @@ void Skeleton3DEditor::_notification(int p_what) {
8401007
8411008 joint_tree->connect (SceneStringName (item_selected), callable_mp (this , &Skeleton3DEditor::_joint_tree_selection_changed));
8421009 joint_tree->connect (" item_mouse_selected" , callable_mp (this , &Skeleton3DEditor::_joint_tree_rmb_select));
1010+ joint_tree->connect (" button_clicked" , callable_mp (this , &Skeleton3DEditor::_joint_tree_button_clicked));
8431011#ifdef TOOLS_ENABLED
8441012 skeleton->connect (SceneStringName (pose_updated), callable_mp (this , &Skeleton3DEditor::_draw_gizmo));
8451013 skeleton->connect (SceneStringName (pose_updated), callable_mp (this , &Skeleton3DEditor::_update_properties));
@@ -1337,6 +1505,10 @@ void Skeleton3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, c
13371505 ur->add_undo_method (skeleton, " set_bone_pose_scale" , p_ids[i], se->get_bone_original_scale ());
13381506 }
13391507 }
1508+
1509+ ur->add_do_method (se, " update_joint_tree" );
1510+ ur->add_undo_method (se, " update_joint_tree" );
1511+
13401512 ur->commit_action ();
13411513}
13421514
0 commit comments