diff options
| -rw-r--r-- | editor/plugins/skeleton_3d_editor_plugin.cpp | 396 | ||||
| -rw-r--r-- | editor/plugins/skeleton_3d_editor_plugin.h | 60 | ||||
| -rw-r--r-- | scene/3d/skeleton_3d.cpp | 39 | ||||
| -rw-r--r-- | scene/3d/skeleton_3d.h | 1 | 
4 files changed, 173 insertions, 323 deletions
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index f9c46d35c4..708eaf2c46 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/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();  } diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h index 2c21aab739..3b4dd362fb 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.h +++ b/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(); diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 9b28d7aff8..14506fd9bd 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/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() { diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index f3cf551af7..f7bc3df94e 100644 --- a/scene/3d/skeleton_3d.h +++ b/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();  |