Преглед на файлове

Merge pull request #53786 from TokageItLab/fix-skeleton-editor-methods

Rémi Verschelde преди 3 години
родител
ревизия
f90047f158
променени са 4 файла, в които са добавени 173 реда и са изтрити 323 реда
  1. 117 279
      editor/plugins/skeleton_3d_editor_plugin.cpp
  2. 16 44
      editor/plugins/skeleton_3d_editor_plugin.h
  3. 39 0
      scene/3d/skeleton_3d.cpp
  4. 1 0
      scene/3d/skeleton_3d.h

+ 117 - 279
editor/plugins/skeleton_3d_editor_plugin.cpp

@@ -49,276 +49,128 @@ void BoneTransformEditor::create_editors() {
 
 	section = memnew(EditorInspectorSection);
 	section->setup("trf_properties", label, this, section_color, true);
+	section->unfold();
 	add_child(section);
 
-	enabled_checkbox = memnew(CheckBox(TTR("Pose Enabled")));
-	enabled_checkbox->set_flat(true);
-	enabled_checkbox->set_visible(toggle_enabled);
+	enabled_checkbox = memnew(EditorPropertyCheck());
+	enabled_checkbox->set_label("Pose Enabled");
+	enabled_checkbox->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
 	section->get_vbox()->add_child(enabled_checkbox);
 
-	key_button = memnew(Button);
-	key_button->set_text(TTR("Key Transform"));
-	key_button->set_visible(keyable);
-	key_button->set_icon(get_theme_icon(SNAME("Key"), SNAME("EditorIcons")));
-	key_button->set_flat(true);
-	section->get_vbox()->add_child(key_button);
-
-	// Translation property.
-	translation_property = memnew(EditorPropertyVector3());
-	translation_property->setup(-10000, 10000, 0.001f, true);
-	translation_property->set_label("Translation");
-	translation_property->set_use_folding(true);
-	translation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3));
-	section->get_vbox()->add_child(translation_property);
+	// Position property.
+	position_property = memnew(EditorPropertyVector3());
+	position_property->setup(-10000, 10000, 0.001f, true);
+	position_property->set_label("Position");
+	position_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
+	section->get_vbox()->add_child(position_property);
 
 	// Rotation property.
-	rotation_property = memnew(EditorPropertyVector3());
+	rotation_property = memnew(EditorPropertyQuaternion());
 	rotation_property->setup(-10000, 10000, 0.001f, true);
-	rotation_property->set_label("Rotation Degrees");
-	rotation_property->set_use_folding(true);
-	rotation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3));
+	rotation_property->set_label("Rotation");
+	rotation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
 	section->get_vbox()->add_child(rotation_property);
 
 	// Scale property.
 	scale_property = memnew(EditorPropertyVector3());
 	scale_property->setup(-10000, 10000, 0.001f, true);
 	scale_property->set_label("Scale");
-	scale_property->set_use_folding(true);
-	scale_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3));
+	scale_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
 	section->get_vbox()->add_child(scale_property);
 
 	// Transform/Matrix section.
-	transform_section = memnew(EditorInspectorSection);
-	transform_section->setup("trf_properties_transform", "Matrix", this, section_color, true);
-	section->get_vbox()->add_child(transform_section);
+	rest_section = memnew(EditorInspectorSection);
+	rest_section->setup("trf_properties_transform", "Rest", this, section_color, true);
+	section->get_vbox()->add_child(rest_section);
 
 	// Transform/Matrix property.
-	transform_property = memnew(EditorPropertyTransform3D());
-	transform_property->setup(-10000, 10000, 0.001f, true);
-	transform_property->set_label("Transform");
-	transform_property->set_use_folding(true);
-	transform_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_transform));
-	transform_section->get_vbox()->add_child(transform_property);
+	rest_matrix = memnew(EditorPropertyTransform3D());
+	rest_matrix->setup(-10000, 10000, 0.001f, true);
+	rest_matrix->set_label("Transform");
+	rest_section->get_vbox()->add_child(rest_matrix);
 }
 
 void BoneTransformEditor::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 			create_editors();
-			key_button->connect("pressed", callable_mp(this, &BoneTransformEditor::_key_button_pressed));
-			enabled_checkbox->connect("pressed", callable_mp(this, &BoneTransformEditor::_checkbox_pressed));
-			[[fallthrough]];
-		}
-		case NOTIFICATION_SORT_CHILDREN: {
-			const Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree"));
-			int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree"));
-
-			Point2 buffer;
-			buffer.x += get_theme_constant(SNAME("inspector_margin"), SNAME("Editor"));
-			buffer.y += font->get_height(font_size);
-			buffer.y += get_theme_constant(SNAME("vseparation"), SNAME("Tree"));
-
-			const float vector_height = translation_property->get_size().y;
-			const float transform_height = transform_property->get_size().y;
-			const float button_height = key_button->get_size().y;
-
-			const float width = get_size().x - get_theme_constant(SNAME("inspector_margin"), SNAME("Editor"));
-			Vector<Rect2> input_rects;
-			if (keyable && section->get_vbox()->is_visible()) {
-				input_rects.push_back(Rect2(key_button->get_position() + buffer, Size2(width, button_height)));
-			} else {
-				input_rects.push_back(Rect2(0, 0, 0, 0));
-			}
-
-			if (section->get_vbox()->is_visible()) {
-				input_rects.push_back(Rect2(translation_property->get_position() + buffer, Size2(width, vector_height)));
-				input_rects.push_back(Rect2(rotation_property->get_position() + buffer, Size2(width, vector_height)));
-				input_rects.push_back(Rect2(scale_property->get_position() + buffer, Size2(width, vector_height)));
-				input_rects.push_back(Rect2(transform_property->get_position() + buffer, Size2(width, transform_height)));
-			} else {
-				const int32_t start = input_rects.size();
-				const int32_t empty_input_rect_elements = 4;
-				const int32_t end = start + empty_input_rect_elements;
-				for (int i = start; i < end; ++i) {
-					input_rects.push_back(Rect2(0, 0, 0, 0));
-				}
-			}
-
-			for (int32_t i = 0; i < input_rects.size(); i++) {
-				background_rects[i] = input_rects[i];
-			}
-
-			update();
-			break;
-		}
-		case NOTIFICATION_DRAW: {
-			const Color dark_color = get_theme_color(SNAME("dark_color_2"), SNAME("Editor"));
-
-			for (int i = 0; i < 5; ++i) {
-				draw_rect(background_rects[i], dark_color);
-			}
-
 			break;
 		}
 	}
 }
 
-void BoneTransformEditor::_value_changed(const double p_value) {
-	if (updating) {
-		return;
-	}
-
-	Transform3D tform = compute_transform_from_vector3s();
-	_change_transform(tform);
-}
-
-void BoneTransformEditor::_value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean) {
-	if (updating) {
-		return;
-	}
-	Transform3D tform = compute_transform_from_vector3s();
-	_change_transform(tform);
-}
-
-Transform3D BoneTransformEditor::compute_transform_from_vector3s() const {
-	// Convert rotation from degrees to radians.
-	Vector3 prop_rotation = rotation_property->get_vector();
-	prop_rotation.x = Math::deg2rad(prop_rotation.x);
-	prop_rotation.y = Math::deg2rad(prop_rotation.y);
-	prop_rotation.z = Math::deg2rad(prop_rotation.z);
-
-	return Transform3D(
-			Basis(prop_rotation, scale_property->get_vector()),
-			translation_property->get_vector());
-}
-
-void BoneTransformEditor::_value_changed_transform(const String p_property_name, const Transform3D p_transform, const StringName p_edited_property_name, const bool p_boolean) {
+void BoneTransformEditor::_value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
 	if (updating) {
 		return;
 	}
-	_change_transform(p_transform);
-}
-
-void BoneTransformEditor::_change_transform(Transform3D p_new_transform) {
-	if (property.get_slicec('/', 0) == "bones") {
+	if (skeleton) {
 		undo_redo->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS);
-		undo_redo->add_undo_property(skeleton, property, skeleton->get(property));
-		undo_redo->add_do_property(skeleton, property, p_new_transform);
+		undo_redo->add_undo_property(skeleton, p_property, skeleton->get(p_property));
+		undo_redo->add_do_property(skeleton, p_property, p_value);
 		undo_redo->commit_action();
 	}
 }
 
-void BoneTransformEditor::update_enabled_checkbox() {
-	if (enabled_checkbox) {
-		const String path = "bones/" + property.get_slicec('/', 1) + "/enabled";
-		const bool is_enabled = skeleton->get(path);
-		enabled_checkbox->set_pressed(is_enabled);
-	}
-}
-
-void BoneTransformEditor::_update_properties() {
-	if (updating) {
-		return;
-	}
-
-	if (!skeleton) {
-		return;
-	}
-
-	updating = true;
-
-	Transform3D tform = skeleton->get(property);
-	_update_transform_properties(tform);
-}
-
-void BoneTransformEditor::_update_transform_properties(Transform3D tform) {
-	Basis rotation_basis = tform.get_basis();
-	Vector3 rotation_radians = rotation_basis.get_rotation_euler();
-	Vector3 rotation_degrees = Vector3(Math::rad2deg(rotation_radians.x), Math::rad2deg(rotation_radians.y), Math::rad2deg(rotation_radians.z));
-	Vector3 translation = tform.get_origin();
-	Vector3 scale = tform.basis.get_scale();
-
-	translation_property->update_using_vector(translation);
-	rotation_property->update_using_vector(rotation_degrees);
-	scale_property->update_using_vector(scale);
-	transform_property->update_using_transform(tform);
-
-	update_enabled_checkbox();
-	updating = false;
-}
-
 BoneTransformEditor::BoneTransformEditor(Skeleton3D *p_skeleton) :
 		skeleton(p_skeleton) {
 	undo_redo = EditorNode::get_undo_redo();
 }
 
 void BoneTransformEditor::set_target(const String &p_prop) {
-	property = p_prop;
-}
+	enabled_checkbox->set_object_and_property(skeleton, p_prop + "enabled");
+	enabled_checkbox->update_property();
 
-void BoneTransformEditor::set_keyable(const bool p_keyable) {
-	keyable = p_keyable;
-}
+	position_property->set_object_and_property(skeleton, p_prop + "position");
+	position_property->update_property();
 
-void BoneTransformEditor::_update_key_button(const bool p_keyable) {
-	bool is_keyable = keyable && p_keyable;
-	if (key_button) {
-		key_button->set_visible(is_keyable);
-	}
-}
+	rotation_property->set_object_and_property(skeleton, p_prop + "rotation");
+	rotation_property->update_property();
 
-void BoneTransformEditor::set_properties_read_only(const bool p_readonly) {
-	enabled_checkbox->set_disabled(p_readonly);
-	enabled_checkbox->update();
-}
-
-void BoneTransformEditor::set_transform_read_only(const bool p_readonly) {
-	translation_property->set_read_only(p_readonly);
-	rotation_property->set_read_only(p_readonly);
-	scale_property->set_read_only(p_readonly);
-	transform_property->set_read_only(p_readonly);
-	translation_property->update();
-	rotation_property->update();
-	scale_property->update();
-	transform_property->update();
-	_update_key_button(!p_readonly);
-}
-
-void BoneTransformEditor::set_toggle_enabled(const bool p_enabled) {
-	toggle_enabled = p_enabled;
-	if (enabled_checkbox) {
-		enabled_checkbox->set_visible(p_enabled);
-	}
-}
-
-void BoneTransformEditor::_key_button_pressed() {
-	if (!skeleton) {
-		return;
-	}
-
-	const BoneId bone_id = property.get_slicec('/', 1).to_int();
-	const String name = skeleton->get_bone_name(bone_id);
-
-	if (name.is_empty()) {
-		return;
-	}
+	scale_property->set_object_and_property(skeleton, p_prop + "scale");
+	scale_property->update_property();
 
-	Transform3D tform = compute_transform_from_vector3s();
-	AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(skeleton, name, tform);
+	rest_matrix->set_object_and_property(skeleton, p_prop + "rest");
+	rest_matrix->update_property();
 }
 
-void BoneTransformEditor::_checkbox_pressed() {
+void BoneTransformEditor::_update_properties() {
 	if (!skeleton) {
 		return;
 	}
-
-	const BoneId bone_id = property.get_slicec('/', 1).to_int();
-	if (enabled_checkbox) {
-		undo_redo->create_action(TTR("Set Pose Enabled"));
-		bool enabled = skeleton->is_bone_enabled(bone_id);
-		undo_redo->add_do_method(skeleton, "set_bone_enabled", bone_id, !enabled);
-		undo_redo->add_undo_method(skeleton, "set_bone_enabled", bone_id, enabled);
-		undo_redo->commit_action();
+	int selected = Skeleton3DEditor::get_singleton()->get_selected_bone();
+	List<PropertyInfo> props;
+	skeleton->get_property_list(&props);
+	for (const PropertyInfo &E : props) {
+		PackedStringArray spr = E.name.split("/");
+		if (spr.size() == 3 && spr[0] == "bones") {
+			if (spr[1].to_int() == selected) {
+				if (spr[2] == "enabled") {
+					enabled_checkbox->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
+					enabled_checkbox->update_property();
+					enabled_checkbox->update();
+				}
+				if (spr[2] == "position") {
+					position_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
+					position_property->update_property();
+					position_property->update();
+				}
+				if (spr[2] == "rotation") {
+					rotation_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
+					rotation_property->update_property();
+					rotation_property->update();
+				}
+				if (spr[2] == "scale") {
+					scale_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
+					scale_property->update_property();
+					scale_property->update();
+				}
+				if (spr[2] == "rest") {
+					rest_matrix->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
+					rest_matrix->update_property();
+					rest_matrix->update();
+				}
+			}
+		}
 	}
 }
 
@@ -334,24 +186,6 @@ void Skeleton3DEditor::set_rest_options_enabled(const bool p_rest_options_enable
 	rest_options->get_popup()->set_item_disabled(REST_OPTION_POSE_TO_REST, !p_rest_options_enabled);
 };
 
-void Skeleton3DEditor::_update_show_rest_only() {
-	_update_pose_enabled(-1);
-}
-
-void Skeleton3DEditor::_update_pose_enabled(int p_bone) {
-	if (!skeleton) {
-		return;
-	}
-	if (pose_editor) {
-		pose_editor->set_properties_read_only(skeleton->is_show_rest_only());
-
-		if (selected_bone > 0) {
-			pose_editor->set_transform_read_only(skeleton->is_show_rest_only() || !(skeleton->is_bone_enabled(selected_bone)));
-		}
-	}
-	_update_gizmo_visible();
-}
-
 void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
 	if (!skeleton) {
 		return;
@@ -398,8 +232,13 @@ void Skeleton3DEditor::init_pose() {
 	UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
 	ur->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS);
 	for (int i = 0; i < bone_len; i++) {
-		ur->add_do_method(skeleton, "set_bone_pose", i, Transform3D());
-		ur->add_undo_method(skeleton, "set_bone_pose", i, skeleton->get_bone_pose(i));
+		Transform3D rest = skeleton->get_bone_rest(i);
+		ur->add_do_method(skeleton, "set_bone_pose_position", i, rest.origin);
+		ur->add_do_method(skeleton, "set_bone_pose_rotation", i, rest.basis.get_rotation_quaternion());
+		ur->add_do_method(skeleton, "set_bone_pose_scale", i, rest.basis.get_scale());
+		ur->add_undo_method(skeleton, "set_bone_pose_position", i, skeleton->get_bone_pose_position(i));
+		ur->add_undo_method(skeleton, "set_bone_pose_rotation", i, skeleton->get_bone_pose_rotation(i));
+		ur->add_undo_method(skeleton, "set_bone_pose_scale", i, skeleton->get_bone_pose_scale(i));
 	}
 	ur->commit_action();
 }
@@ -439,13 +278,9 @@ void Skeleton3DEditor::pose_to_rest() {
 
 	// Todo: Do method with multiple bone selection.
 	UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-	ur->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS);
-
-	ur->add_do_method(skeleton, "set_bone_pose", selected_bone, Transform3D());
-	ur->add_undo_method(skeleton, "set_bone_pose", selected_bone, skeleton->get_bone_pose(selected_bone));
-	ur->add_do_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_rest(selected_bone) * skeleton->get_bone_pose(selected_bone));
+	ur->create_action(TTR("Set Bone Rest"), UndoRedo::MERGE_ENDS);
+	ur->add_do_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_pose(selected_bone));
 	ur->add_undo_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_rest(selected_bone));
-
 	ur->commit_action();
 }
 
@@ -630,18 +465,14 @@ void Skeleton3DEditor::_joint_tree_selection_changed() {
 			const int b_idx = path.get_slicec('/', 1).to_int();
 			const String bone_path = "bones/" + itos(b_idx) + "/";
 
-			pose_editor->set_target(bone_path + "pose");
-			rest_editor->set_target(bone_path + "rest");
-
-			pose_editor->set_visible(true);
-			rest_editor->set_visible(true);
-
+			pose_editor->set_target(bone_path);
 			selected_bone = b_idx;
 		}
 	}
+	pose_editor->set_visible(selected);
 	set_rest_options_enabled(selected);
 	_update_properties();
-	_update_pose_enabled();
+	_update_gizmo_visible();
 }
 
 // May be not used with single select mode.
@@ -649,13 +480,10 @@ void Skeleton3DEditor::_joint_tree_rmb_select(const Vector2 &p_pos) {
 }
 
 void Skeleton3DEditor::_update_properties() {
-	if (rest_editor) {
-		rest_editor->_update_properties();
-	}
 	if (pose_editor) {
 		pose_editor->_update_properties();
 	}
-	_update_gizmo_transform();
+	Node3DEditor::get_singleton()->update_transform_gizmo();
 }
 
 void Skeleton3DEditor::update_joint_tree() {
@@ -782,17 +610,9 @@ void Skeleton3DEditor::create_editors() {
 	s_con->add_child(joint_tree);
 
 	pose_editor = memnew(BoneTransformEditor(skeleton));
-	pose_editor->set_label(TTR("Bone Pose"));
-	pose_editor->set_toggle_enabled(true);
-	pose_editor->set_keyable(te->has_keying());
+	pose_editor->set_label(TTR("Bone Transform"));
 	pose_editor->set_visible(false);
 	add_child(pose_editor);
-
-	rest_editor = memnew(BoneTransformEditor(skeleton));
-	rest_editor->set_label(TTR("Bone Rest"));
-	rest_editor->set_visible(false);
-	add_child(rest_editor);
-	rest_editor->set_transform_read_only(true);
 }
 
 void Skeleton3DEditor::_notification(int p_what) {
@@ -811,8 +631,8 @@ void Skeleton3DEditor::_notification(int p_what) {
 #ifdef TOOLS_ENABLED
 			skeleton->connect("pose_updated", callable_mp(this, &Skeleton3DEditor::_draw_gizmo));
 			skeleton->connect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties));
-			skeleton->connect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_update_pose_enabled));
-			skeleton->connect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_show_rest_only));
+			skeleton->connect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed));
+			skeleton->connect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible));
 #endif
 			break;
 		}
@@ -833,8 +653,6 @@ void Skeleton3DEditor::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("_node_removed"), &Skeleton3DEditor::_node_removed);
 	ClassDB::bind_method(D_METHOD("_joint_tree_selection_changed"), &Skeleton3DEditor::_joint_tree_selection_changed);
 	ClassDB::bind_method(D_METHOD("_joint_tree_rmb_select"), &Skeleton3DEditor::_joint_tree_rmb_select);
-	ClassDB::bind_method(D_METHOD("_update_show_rest_only"), &Skeleton3DEditor::_update_show_rest_only);
-	ClassDB::bind_method(D_METHOD("_update_pose_enabled"), &Skeleton3DEditor::_update_pose_enabled);
 	ClassDB::bind_method(D_METHOD("_update_properties"), &Skeleton3DEditor::_update_properties);
 	ClassDB::bind_method(D_METHOD("_on_click_skeleton_option"), &Skeleton3DEditor::_on_click_skeleton_option);
 	ClassDB::bind_method(D_METHOD("_on_click_rest_option"), &Skeleton3DEditor::_on_click_rest_option);
@@ -905,7 +723,9 @@ void Skeleton3DEditor::update_bone_original() {
 	if (skeleton->get_bone_count() == 0 || selected_bone == -1) {
 		return;
 	}
-	bone_original = skeleton->get_bone_pose(selected_bone);
+	bone_original_position = skeleton->get_bone_pose_position(selected_bone);
+	bone_original_rotation = skeleton->get_bone_pose_rotation(selected_bone);
+	bone_original_scale = skeleton->get_bone_pose_scale(selected_bone);
 }
 
 void Skeleton3DEditor::_hide_handles() {
@@ -1033,8 +853,8 @@ void Skeleton3DEditor::select_bone(int p_idx) {
 Skeleton3DEditor::~Skeleton3DEditor() {
 	if (skeleton) {
 #ifdef TOOLS_ENABLED
-		skeleton->disconnect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_show_rest_only));
-		skeleton->disconnect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_update_pose_enabled));
+		skeleton->disconnect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible));
+		skeleton->disconnect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed));
 		skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_draw_gizmo));
 		skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties));
 		skeleton->set_transform_gizmo_visible(true);
@@ -1115,9 +935,9 @@ bool Skeleton3DEditorPlugin::handles(Object *p_object) const {
 	return p_object->is_class("Skeleton3D");
 }
 
-void Skeleton3DEditor::_update_gizmo_transform() {
-	Node3DEditor::get_singleton()->update_transform_gizmo();
-};
+void Skeleton3DEditor::_bone_enabled_changed(const int p_bone_id) {
+	_update_gizmo_visible();
+}
 
 void Skeleton3DEditor::_update_gizmo_visible() {
 	_subgizmo_selection_change();
@@ -1272,7 +1092,7 @@ void Skeleton3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gi
 
 	// Apply transform.
 	skeleton->set_bone_pose_position(p_id, t.origin);
-	skeleton->set_bone_pose_rotation(p_id, t.basis.operator Quaternion());
+	skeleton->set_bone_pose_rotation(p_id, t.basis.get_rotation_quaternion());
 	skeleton->set_bone_pose_scale(p_id, t.basis.get_scale());
 }
 
@@ -1281,12 +1101,30 @@ void Skeleton3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, c
 	ERR_FAIL_COND(!skeleton);
 
 	Skeleton3DEditor *se = Skeleton3DEditor::get_singleton();
+	Node3DEditor *ne = Node3DEditor::get_singleton();
 
 	UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-	for (int i = 0; i < p_ids.size(); i++) {
-		ur->create_action(TTR("Set Bone Transform"));
-		ur->add_do_method(skeleton, "set_bone_pose", p_ids[i], skeleton->get_bone_pose(p_ids[i]));
-		ur->add_undo_method(skeleton, "set_bone_pose", p_ids[i], se->get_bone_original());
+	ur->create_action(TTR("Set Bone Transform"));
+	if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || ne->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
+		for (int i = 0; i < p_ids.size(); i++) {
+			ur->add_do_method(skeleton, "set_bone_pose_position", p_ids[i], skeleton->get_bone_pose_position(p_ids[i]));
+			ur->add_undo_method(skeleton, "set_bone_pose_position", p_ids[i], se->get_bone_original_position());
+		}
+	}
+	if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || ne->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
+		for (int i = 0; i < p_ids.size(); i++) {
+			ur->add_do_method(skeleton, "set_bone_pose_rotation", p_ids[i], skeleton->get_bone_pose_rotation(p_ids[i]));
+			ur->add_undo_method(skeleton, "set_bone_pose_rotation", p_ids[i], se->get_bone_original_rotation());
+		}
+	}
+	if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) {
+		for (int i = 0; i < p_ids.size(); i++) {
+			// If the axis is swapped by scaling, the rotation can be changed.
+			ur->add_do_method(skeleton, "set_bone_pose_rotation", p_ids[i], skeleton->get_bone_pose_rotation(p_ids[i]));
+			ur->add_undo_method(skeleton, "set_bone_pose_rotation", p_ids[i], se->get_bone_original_rotation());
+			ur->add_do_method(skeleton, "set_bone_pose_scale", p_ids[i], skeleton->get_bone_pose_scale(p_ids[i]));
+			ur->add_undo_method(skeleton, "set_bone_pose_scale", p_ids[i], se->get_bone_original_scale());
+		}
 	}
 	ur->commit_action();
 }

+ 16 - 44
editor/plugins/skeleton_3d_editor_plugin.h

@@ -52,21 +52,22 @@ class BoneTransformEditor : public VBoxContainer {
 
 	EditorInspectorSection *section = nullptr;
 
-	EditorPropertyVector3 *translation_property = nullptr;
-	EditorPropertyVector3 *rotation_property = nullptr;
+	EditorPropertyCheck *enabled_checkbox = nullptr;
+	EditorPropertyVector3 *position_property = nullptr;
+	EditorPropertyQuaternion *rotation_property = nullptr;
 	EditorPropertyVector3 *scale_property = nullptr;
-	EditorInspectorSection *transform_section = nullptr;
-	EditorPropertyTransform3D *transform_property = nullptr;
+
+	EditorInspectorSection *rest_section = nullptr;
+	EditorPropertyTransform3D *rest_matrix = nullptr;
 
 	Rect2 background_rects[5];
 
 	Skeleton3D *skeleton;
-	String property;
+	// String property;
 
 	UndoRedo *undo_redo;
 
-	Button *key_button = nullptr;
-	CheckBox *enabled_checkbox = nullptr;
+	// Button *key_button = nullptr;
 
 	bool keyable = false;
 	bool toggle_enabled = false;
@@ -76,20 +77,7 @@ class BoneTransformEditor : public VBoxContainer {
 
 	void create_editors();
 
-	// Called when one of the EditorSpinSliders are changed.
-	void _value_changed(const double p_value);
-	// Called when the one of the EditorPropertyVector3 are updated.
-	void _value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean);
-	// Called when the transform_property is updated.
-	void _value_changed_transform(const String p_property_name, const Transform3D p_transform, const StringName p_edited_property_name, const bool p_boolean);
-	// Changes the transform to the given transform and updates the UI accordingly.
-	void _change_transform(Transform3D p_new_transform);
-	// Update it is truely keyable then.
-	void _update_key_button(const bool p_keyable);
-	// Creates a Transform using the EditorPropertyVector3 properties.
-	Transform3D compute_transform_from_vector3s() const;
-
-	void update_enabled_checkbox();
+	void _value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing);
 
 protected:
 	void _notification(int p_what);
@@ -102,23 +90,6 @@ public:
 	void set_label(const String &p_label) { label = p_label; }
 
 	void _update_properties();
-	void _update_transform_properties(Transform3D p_transform);
-
-	// Transform can be keyed, whether or not to show the button.
-	void set_keyable(const bool p_keyable);
-
-	// When rest mode, pose editor are diasbled.
-	void set_properties_read_only(const bool p_readonly);
-	void set_transform_read_only(const bool p_readonly);
-
-	// Bone can be toggled enabled or disabled, whether or not to show the checkbox.
-	void set_toggle_enabled(const bool p_enabled);
-
-	// Key Transform Button pressed.
-	void _key_button_pressed();
-
-	// Bone Enabled Checkbox toggled.
-	void _checkbox_pressed();
 };
 
 class Skeleton3DEditor : public VBoxContainer {
@@ -197,13 +168,12 @@ class Skeleton3DEditor : public VBoxContainer {
 	Ref<ShaderMaterial> handle_material;
 	Ref<Shader> handle_shader;
 
-	Transform3D bone_original;
-
-	void _update_pose_enabled(int p_bone = -1);
-	void _update_show_rest_only();
+	Vector3 bone_original_position;
+	Quaternion bone_original_rotation;
+	Vector3 bone_original_scale;
 
-	void _update_gizmo_transform();
 	void _update_gizmo_visible();
+	void _bone_enabled_changed(const int p_bone_id);
 
 	void _hide_handles();
 
@@ -237,7 +207,9 @@ public:
 	bool is_edit_mode() const { return edit_mode; }
 
 	void update_bone_original();
-	Transform3D get_bone_original() { return bone_original; };
+	Vector3 get_bone_original_position() const { return bone_original_position; };
+	Quaternion get_bone_original_rotation() const { return bone_original_rotation; };
+	Vector3 get_bone_original_scale() const { return bone_original_scale; };
 
 	Skeleton3DEditor(EditorInspectorPluginSkeleton *e_plugin, EditorNode *p_editor, Skeleton3D *skeleton);
 	~Skeleton3DEditor();

+ 39 - 0
scene/3d/skeleton_3d.cpp

@@ -171,6 +171,45 @@ void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const {
 					"SkeletonModificationStack3D",
 					PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
 #endif //_3D_DISABLED
+
+	for (PropertyInfo &E : *p_list) {
+		_validate_property(E);
+	}
+}
+
+void Skeleton3D::_validate_property(PropertyInfo &property) const {
+	PackedStringArray spr = property.name.split("/");
+	if (spr.size() == 3 && spr[0] == "bones") {
+		if (spr[2] == "rest") {
+			property.usage |= PROPERTY_USAGE_READ_ONLY;
+		}
+		if (is_show_rest_only()) {
+			if (spr[2] == "enabled") {
+				property.usage |= PROPERTY_USAGE_READ_ONLY;
+			}
+			if (spr[2] == "position") {
+				property.usage |= PROPERTY_USAGE_READ_ONLY;
+			}
+			if (spr[2] == "rotation") {
+				property.usage |= PROPERTY_USAGE_READ_ONLY;
+			}
+			if (spr[2] == "scale") {
+				property.usage |= PROPERTY_USAGE_READ_ONLY;
+			}
+		} else if (!is_bone_enabled(spr[1].to_int())) {
+			if (spr[2] == "position") {
+				property.usage |= PROPERTY_USAGE_READ_ONLY;
+			}
+			if (spr[2] == "rotation") {
+				property.usage |= PROPERTY_USAGE_READ_ONLY;
+			}
+			if (spr[2] == "scale") {
+				property.usage |= PROPERTY_USAGE_READ_ONLY;
+			}
+		}
+	}
+
+	Node3D::_validate_property(property);
 }
 
 void Skeleton3D::_update_process_order() {

+ 1 - 0
scene/3d/skeleton_3d.h

@@ -153,6 +153,7 @@ protected:
 	bool _get(const StringName &p_path, Variant &r_ret) const;
 	bool _set(const StringName &p_path, const Variant &p_value);
 	void _get_property_list(List<PropertyInfo> *p_list) const;
+	virtual void _validate_property(PropertyInfo &property) const override;
 	void _notification(int p_what);
 	static void _bind_methods();