|
@@ -54,6 +54,7 @@ void BoneTransformEditor::create_editors() {
|
|
|
|
|
|
enabled_checkbox = memnew(EditorPropertyCheck());
|
|
enabled_checkbox = memnew(EditorPropertyCheck());
|
|
enabled_checkbox->set_label("Pose Enabled");
|
|
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, &BoneTransformEditor::_value_changed));
|
|
section->get_vbox()->add_child(enabled_checkbox);
|
|
section->get_vbox()->add_child(enabled_checkbox);
|
|
|
|
|
|
@@ -61,21 +62,27 @@ void BoneTransformEditor::create_editors() {
|
|
position_property = memnew(EditorPropertyVector3());
|
|
position_property = memnew(EditorPropertyVector3());
|
|
position_property->setup(-10000, 10000, 0.001f, true);
|
|
position_property->setup(-10000, 10000, 0.001f, true);
|
|
position_property->set_label("Position");
|
|
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_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
|
|
|
|
+ position_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed));
|
|
section->get_vbox()->add_child(position_property);
|
|
section->get_vbox()->add_child(position_property);
|
|
|
|
|
|
// Rotation property.
|
|
// Rotation property.
|
|
rotation_property = memnew(EditorPropertyQuaternion());
|
|
rotation_property = memnew(EditorPropertyQuaternion());
|
|
rotation_property->setup(-10000, 10000, 0.001f, true);
|
|
rotation_property->setup(-10000, 10000, 0.001f, true);
|
|
rotation_property->set_label("Rotation");
|
|
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_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
|
|
|
|
+ rotation_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed));
|
|
section->get_vbox()->add_child(rotation_property);
|
|
section->get_vbox()->add_child(rotation_property);
|
|
|
|
|
|
// Scale property.
|
|
// Scale property.
|
|
scale_property = memnew(EditorPropertyVector3());
|
|
scale_property = memnew(EditorPropertyVector3());
|
|
scale_property->setup(-10000, 10000, 0.001f, true);
|
|
scale_property->setup(-10000, 10000, 0.001f, true);
|
|
scale_property->set_label("Scale");
|
|
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_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
|
|
|
|
+ scale_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed));
|
|
section->get_vbox()->add_child(scale_property);
|
|
section->get_vbox()->add_child(scale_property);
|
|
|
|
|
|
// Transform/Matrix section.
|
|
// Transform/Matrix section.
|
|
@@ -87,6 +94,7 @@ void BoneTransformEditor::create_editors() {
|
|
rest_matrix = memnew(EditorPropertyTransform3D());
|
|
rest_matrix = memnew(EditorPropertyTransform3D());
|
|
rest_matrix->setup(-10000, 10000, 0.001f, true);
|
|
rest_matrix->setup(-10000, 10000, 0.001f, true);
|
|
rest_matrix->set_label("Transform");
|
|
rest_matrix->set_label("Transform");
|
|
|
|
+ rest_matrix->set_selectable(false);
|
|
rest_section->get_vbox()->add_child(rest_matrix);
|
|
rest_section->get_vbox()->add_child(rest_matrix);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -116,6 +124,12 @@ BoneTransformEditor::BoneTransformEditor(Skeleton3D *p_skeleton) :
|
|
undo_redo = EditorNode::get_undo_redo();
|
|
undo_redo = EditorNode::get_undo_redo();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void BoneTransformEditor::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 BoneTransformEditor::set_target(const String &p_prop) {
|
|
enabled_checkbox->set_object_and_property(skeleton, p_prop + "enabled");
|
|
enabled_checkbox->set_object_and_property(skeleton, p_prop + "enabled");
|
|
enabled_checkbox->update_property();
|
|
enabled_checkbox->update_property();
|
|
@@ -133,6 +147,23 @@ void BoneTransformEditor::set_target(const String &p_prop) {
|
|
rest_matrix->update_property();
|
|
rest_matrix->update_property();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance) {
|
|
|
|
+ AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
|
|
|
|
+ PackedStringArray split = p_path.split("/");
|
|
|
|
+ if (split.size() == 3 && split[0] == "bones") {
|
|
|
|
+ int bone_idx = split[1].to_int();
|
|
|
|
+ if (split[2] == "position") {
|
|
|
|
+ te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_POSITION_3D, skeleton->get(p_path));
|
|
|
|
+ }
|
|
|
|
+ if (split[2] == "rotation") {
|
|
|
|
+ te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_ROTATION_3D, skeleton->get(p_path));
|
|
|
|
+ }
|
|
|
|
+ if (split[2] == "scale") {
|
|
|
|
+ te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_SCALE_3D, skeleton->get(p_path));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void BoneTransformEditor::_update_properties() {
|
|
void BoneTransformEditor::_update_properties() {
|
|
if (!skeleton) {
|
|
if (!skeleton) {
|
|
return;
|
|
return;
|
|
@@ -141,30 +172,30 @@ void BoneTransformEditor::_update_properties() {
|
|
List<PropertyInfo> props;
|
|
List<PropertyInfo> props;
|
|
skeleton->get_property_list(&props);
|
|
skeleton->get_property_list(&props);
|
|
for (const PropertyInfo &E : 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") {
|
|
|
|
|
|
+ PackedStringArray split = E.name.split("/");
|
|
|
|
+ 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);
|
|
enabled_checkbox->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
enabled_checkbox->update_property();
|
|
enabled_checkbox->update_property();
|
|
enabled_checkbox->update();
|
|
enabled_checkbox->update();
|
|
}
|
|
}
|
|
- if (spr[2] == "position") {
|
|
|
|
|
|
+ if (split[2] == "position") {
|
|
position_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
position_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
position_property->update_property();
|
|
position_property->update_property();
|
|
position_property->update();
|
|
position_property->update();
|
|
}
|
|
}
|
|
- if (spr[2] == "rotation") {
|
|
|
|
|
|
+ if (split[2] == "rotation") {
|
|
rotation_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
rotation_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
rotation_property->update_property();
|
|
rotation_property->update_property();
|
|
rotation_property->update();
|
|
rotation_property->update();
|
|
}
|
|
}
|
|
- if (spr[2] == "scale") {
|
|
|
|
|
|
+ if (split[2] == "scale") {
|
|
scale_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
scale_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
scale_property->update_property();
|
|
scale_property->update_property();
|
|
scale_property->update();
|
|
scale_property->update();
|
|
}
|
|
}
|
|
- if (spr[2] == "rest") {
|
|
|
|
|
|
+ if (split[2] == "rest") {
|
|
rest_matrix->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
rest_matrix->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
|
|
rest_matrix->update_property();
|
|
rest_matrix->update_property();
|
|
rest_matrix->update();
|
|
rest_matrix->update();
|
|
@@ -178,12 +209,16 @@ Skeleton3DEditor *Skeleton3DEditor::singleton = nullptr;
|
|
|
|
|
|
void Skeleton3DEditor::set_keyable(const bool p_keyable) {
|
|
void Skeleton3DEditor::set_keyable(const bool p_keyable) {
|
|
keyable = p_keyable;
|
|
keyable = p_keyable;
|
|
- skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_INSERT_KEYS, !p_keyable);
|
|
|
|
- skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_INSERT_KEYS_EXISTED, !p_keyable);
|
|
|
|
|
|
+ if (p_keyable) {
|
|
|
|
+ animation_hb->show();
|
|
|
|
+ } else {
|
|
|
|
+ animation_hb->hide();
|
|
|
|
+ }
|
|
};
|
|
};
|
|
|
|
|
|
-void Skeleton3DEditor::set_rest_options_enabled(const bool p_rest_options_enabled) {
|
|
|
|
- rest_options->get_popup()->set_item_disabled(REST_OPTION_POSE_TO_REST, !p_rest_options_enabled);
|
|
|
|
|
|
+void Skeleton3DEditor::set_bone_options_enabled(const bool p_bone_options_enabled) {
|
|
|
|
+ skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_INIT_SELECTED_POSES, !p_bone_options_enabled);
|
|
|
|
+ skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_SELECTED_POSES_TO_RESTS, !p_bone_options_enabled);
|
|
};
|
|
};
|
|
|
|
|
|
void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
|
|
void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
|
|
@@ -192,62 +227,76 @@ void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
|
|
}
|
|
}
|
|
|
|
|
|
switch (p_skeleton_option) {
|
|
switch (p_skeleton_option) {
|
|
- case SKELETON_OPTION_CREATE_PHYSICAL_SKELETON: {
|
|
|
|
- create_physical_skeleton();
|
|
|
|
|
|
+ case SKELETON_OPTION_INIT_ALL_POSES: {
|
|
|
|
+ init_pose(true);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case SKELETON_OPTION_INIT_POSE: {
|
|
|
|
- init_pose();
|
|
|
|
|
|
+ case SKELETON_OPTION_INIT_SELECTED_POSES: {
|
|
|
|
+ init_pose(false);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case SKELETON_OPTION_INSERT_KEYS: {
|
|
|
|
- insert_keys(true);
|
|
|
|
|
|
+ case SKELETON_OPTION_ALL_POSES_TO_RESTS: {
|
|
|
|
+ pose_to_rest(true);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case SKELETON_OPTION_INSERT_KEYS_EXISTED: {
|
|
|
|
- insert_keys(false);
|
|
|
|
|
|
+ case SKELETON_OPTION_SELECTED_POSES_TO_RESTS: {
|
|
|
|
+ pose_to_rest(false);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case SKELETON_OPTION_CREATE_PHYSICAL_SKELETON: {
|
|
|
|
+ create_physical_skeleton();
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void Skeleton3DEditor::_on_click_rest_option(int p_rest_option) {
|
|
|
|
|
|
+void Skeleton3DEditor::init_pose(const bool p_all_bones) {
|
|
if (!skeleton) {
|
|
if (!skeleton) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
-
|
|
|
|
- switch (p_rest_option) {
|
|
|
|
- case REST_OPTION_POSE_TO_REST: {
|
|
|
|
- pose_to_rest();
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void Skeleton3DEditor::init_pose() {
|
|
|
|
const int bone_len = skeleton->get_bone_count();
|
|
const int bone_len = skeleton->get_bone_count();
|
|
if (!bone_len) {
|
|
if (!bone_len) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+
|
|
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
|
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
|
ur->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS);
|
|
ur->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS);
|
|
- for (int i = 0; i < bone_len; 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));
|
|
|
|
|
|
+ if (p_all_bones) {
|
|
|
|
+ for (int i = 0; i < bone_len; 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));
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ // Todo: Do method with multiple bone selection.
|
|
|
|
+ if (selected_bone == -1) {
|
|
|
|
+ ur->commit_action();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ Transform3D rest = skeleton->get_bone_rest(selected_bone);
|
|
|
|
+ ur->add_do_method(skeleton, "set_bone_pose_position", selected_bone, rest.origin);
|
|
|
|
+ ur->add_do_method(skeleton, "set_bone_pose_rotation", selected_bone, rest.basis.get_rotation_quaternion());
|
|
|
|
+ ur->add_do_method(skeleton, "set_bone_pose_scale", selected_bone, rest.basis.get_scale());
|
|
|
|
+ ur->add_undo_method(skeleton, "set_bone_pose_position", selected_bone, skeleton->get_bone_pose_position(selected_bone));
|
|
|
|
+ ur->add_undo_method(skeleton, "set_bone_pose_rotation", selected_bone, skeleton->get_bone_pose_rotation(selected_bone));
|
|
|
|
+ ur->add_undo_method(skeleton, "set_bone_pose_scale", selected_bone, skeleton->get_bone_pose_scale(selected_bone));
|
|
}
|
|
}
|
|
ur->commit_action();
|
|
ur->commit_action();
|
|
}
|
|
}
|
|
|
|
|
|
-void Skeleton3DEditor::insert_keys(bool p_all_bones) {
|
|
|
|
|
|
+void Skeleton3DEditor::insert_keys(const bool p_all_bones) {
|
|
if (!skeleton) {
|
|
if (!skeleton) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ bool pos_enabled = key_loc_button->is_pressed();
|
|
|
|
+ bool rot_enabled = key_rot_button->is_pressed();
|
|
|
|
+ bool scl_enabled = key_scale_button->is_pressed();
|
|
|
|
+
|
|
int bone_len = skeleton->get_bone_count();
|
|
int bone_len = skeleton->get_bone_count();
|
|
Node *root = EditorNode::get_singleton()->get_tree()->get_root();
|
|
Node *root = EditorNode::get_singleton()->get_tree()->get_root();
|
|
String path = root->get_path_to(skeleton);
|
|
String path = root->get_path_to(skeleton);
|
|
@@ -261,26 +310,44 @@ void Skeleton3DEditor::insert_keys(bool p_all_bones) {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!p_all_bones && !te->has_transform_track(skeleton, name)) {
|
|
|
|
- continue;
|
|
|
|
|
|
+ if (pos_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_POSITION_3D))) {
|
|
|
|
+ te->insert_transform_key(skeleton, name, Animation::TYPE_POSITION_3D, skeleton->get_bone_pose_position(i));
|
|
|
|
+ }
|
|
|
|
+ if (rot_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_ROTATION_3D))) {
|
|
|
|
+ te->insert_transform_key(skeleton, name, Animation::TYPE_ROTATION_3D, skeleton->get_bone_pose_rotation(i));
|
|
|
|
+ }
|
|
|
|
+ if (scl_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_SCALE_3D))) {
|
|
|
|
+ te->insert_transform_key(skeleton, name, Animation::TYPE_SCALE_3D, skeleton->get_bone_pose_scale(i));
|
|
}
|
|
}
|
|
-
|
|
|
|
- Transform3D tform = skeleton->get_bone_pose(i);
|
|
|
|
- te->insert_transform_key(skeleton, name, tform);
|
|
|
|
}
|
|
}
|
|
te->commit_insert_queue();
|
|
te->commit_insert_queue();
|
|
}
|
|
}
|
|
|
|
|
|
-void Skeleton3DEditor::pose_to_rest() {
|
|
|
|
|
|
+void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) {
|
|
if (!skeleton) {
|
|
if (!skeleton) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+ const int bone_len = skeleton->get_bone_count();
|
|
|
|
+ if (!bone_len) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
- // Todo: Do method with multiple bone selection.
|
|
|
|
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
|
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
|
ur->create_action(TTR("Set Bone Rest"), UndoRedo::MERGE_ENDS);
|
|
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));
|
|
|
|
|
|
+ if (p_all_bones) {
|
|
|
|
+ for (int i = 0; i < bone_len; i++) {
|
|
|
|
+ ur->add_do_method(skeleton, "set_bone_rest", i, skeleton->get_bone_pose(i));
|
|
|
|
+ ur->add_undo_method(skeleton, "set_bone_rest", i, skeleton->get_bone_rest(i));
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ // Todo: Do method with multiple bone selection.
|
|
|
|
+ if (selected_bone == -1) {
|
|
|
|
+ ur->commit_action();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ 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();
|
|
ur->commit_action();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -466,11 +533,12 @@ void Skeleton3DEditor::_joint_tree_selection_changed() {
|
|
const String bone_path = "bones/" + itos(b_idx) + "/";
|
|
const String bone_path = "bones/" + itos(b_idx) + "/";
|
|
|
|
|
|
pose_editor->set_target(bone_path);
|
|
pose_editor->set_target(bone_path);
|
|
|
|
+ pose_editor->set_keyable(keyable);
|
|
selected_bone = b_idx;
|
|
selected_bone = b_idx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pose_editor->set_visible(selected);
|
|
pose_editor->set_visible(selected);
|
|
- set_rest_options_enabled(selected);
|
|
|
|
|
|
+ set_bone_options_enabled(selected);
|
|
_update_properties();
|
|
_update_properties();
|
|
_update_gizmo_visible();
|
|
_update_gizmo_visible();
|
|
}
|
|
}
|
|
@@ -549,43 +617,82 @@ void Skeleton3DEditor::create_editors() {
|
|
skeleton_options->set_text(TTR("Skeleton3D"));
|
|
skeleton_options->set_text(TTR("Skeleton3D"));
|
|
skeleton_options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton3D"), SNAME("EditorIcons")));
|
|
skeleton_options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton3D"), SNAME("EditorIcons")));
|
|
|
|
|
|
- skeleton_options->get_popup()->add_item(TTR("Init pose"), SKELETON_OPTION_INIT_POSE);
|
|
|
|
- skeleton_options->get_popup()->add_item(TTR("Insert key of all bone poses"), SKELETON_OPTION_INSERT_KEYS);
|
|
|
|
- skeleton_options->get_popup()->add_item(TTR("Insert key of bone poses already exist track"), SKELETON_OPTION_INSERT_KEYS_EXISTED);
|
|
|
|
- skeleton_options->get_popup()->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
|
|
|
|
-
|
|
|
|
- skeleton_options->get_popup()->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_skeleton_option));
|
|
|
|
|
|
+ // Skeleton options.
|
|
|
|
+ PopupMenu *p = skeleton_options->get_popup();
|
|
|
|
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/init_all_poses", TTR("Init all Poses")), SKELETON_OPTION_INIT_ALL_POSES);
|
|
|
|
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/init_selected_poses", TTR("Init selected Poses")), SKELETON_OPTION_INIT_SELECTED_POSES);
|
|
|
|
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply all poses to rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS);
|
|
|
|
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply selected poses to rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS);
|
|
|
|
+ p->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
|
|
|
|
|
|
- // Create Rest Option in Top Menu Bar.
|
|
|
|
- rest_options = memnew(MenuButton);
|
|
|
|
- ne->add_control_to_menu_panel(rest_options);
|
|
|
|
-
|
|
|
|
- rest_options->set_text(TTR("Edit Rest"));
|
|
|
|
- rest_options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
|
|
|
|
-
|
|
|
|
- rest_options->get_popup()->add_item(TTR("Apply current pose to rest"), REST_OPTION_POSE_TO_REST);
|
|
|
|
- rest_options->get_popup()->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_rest_option));
|
|
|
|
- set_rest_options_enabled(false);
|
|
|
|
|
|
+ p->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_skeleton_option));
|
|
|
|
+ set_bone_options_enabled(false);
|
|
|
|
|
|
Vector<Variant> button_binds;
|
|
Vector<Variant> button_binds;
|
|
button_binds.resize(1);
|
|
button_binds.resize(1);
|
|
|
|
|
|
edit_mode_button = memnew(Button);
|
|
edit_mode_button = memnew(Button);
|
|
ne->add_control_to_menu_panel(edit_mode_button);
|
|
ne->add_control_to_menu_panel(edit_mode_button);
|
|
- edit_mode_button->set_tooltip(TTR("Edit Mode\nShow buttons on joints."));
|
|
|
|
- edit_mode_button->set_toggle_mode(true);
|
|
|
|
edit_mode_button->set_flat(true);
|
|
edit_mode_button->set_flat(true);
|
|
|
|
+ edit_mode_button->set_toggle_mode(true);
|
|
|
|
+ edit_mode_button->set_focus_mode(FOCUS_NONE);
|
|
|
|
+ edit_mode_button->set_tooltip(TTR("Edit Mode\nShow buttons on joints."));
|
|
edit_mode_button->connect("toggled", callable_mp(this, &Skeleton3DEditor::edit_mode_toggled));
|
|
edit_mode_button->connect("toggled", callable_mp(this, &Skeleton3DEditor::edit_mode_toggled));
|
|
|
|
|
|
edit_mode = false;
|
|
edit_mode = false;
|
|
|
|
|
|
- set_keyable(te->has_keying());
|
|
|
|
-
|
|
|
|
if (skeleton) {
|
|
if (skeleton) {
|
|
skeleton->add_child(handles_mesh_instance);
|
|
skeleton->add_child(handles_mesh_instance);
|
|
handles_mesh_instance->set_skeleton_path(NodePath(""));
|
|
handles_mesh_instance->set_skeleton_path(NodePath(""));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Keying buttons.
|
|
|
|
+ animation_hb = memnew(HBoxContainer);
|
|
|
|
+ ne->add_control_to_menu_panel(animation_hb);
|
|
|
|
+ animation_hb->add_child(memnew(VSeparator));
|
|
|
|
+ animation_hb->hide();
|
|
|
|
+
|
|
|
|
+ key_loc_button = memnew(Button);
|
|
|
|
+ key_loc_button->set_flat(true);
|
|
|
|
+ key_loc_button->set_toggle_mode(true);
|
|
|
|
+ key_loc_button->set_pressed(false);
|
|
|
|
+ key_loc_button->set_focus_mode(FOCUS_NONE);
|
|
|
|
+ key_loc_button->set_tooltip(TTR("Translation mask for inserting keys."));
|
|
|
|
+ animation_hb->add_child(key_loc_button);
|
|
|
|
+
|
|
|
|
+ key_rot_button = memnew(Button);
|
|
|
|
+ key_rot_button->set_flat(true);
|
|
|
|
+ key_rot_button->set_toggle_mode(true);
|
|
|
|
+ key_rot_button->set_pressed(true);
|
|
|
|
+ key_rot_button->set_focus_mode(FOCUS_NONE);
|
|
|
|
+ key_rot_button->set_tooltip(TTR("Rotation mask for inserting keys."));
|
|
|
|
+ animation_hb->add_child(key_rot_button);
|
|
|
|
+
|
|
|
|
+ key_scale_button = memnew(Button);
|
|
|
|
+ key_scale_button->set_flat(true);
|
|
|
|
+ key_scale_button->set_toggle_mode(true);
|
|
|
|
+ key_scale_button->set_pressed(false);
|
|
|
|
+ key_scale_button->set_focus_mode(FOCUS_NONE);
|
|
|
|
+ key_scale_button->set_tooltip(TTR("Scale mask for inserting keys."));
|
|
|
|
+ animation_hb->add_child(key_scale_button);
|
|
|
|
+
|
|
|
|
+ key_insert_button = memnew(Button);
|
|
|
|
+ key_insert_button->set_flat(true);
|
|
|
|
+ key_insert_button->set_focus_mode(FOCUS_NONE);
|
|
|
|
+ key_insert_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(false));
|
|
|
|
+ key_insert_button->set_tooltip(TTR("Insert key of bone poses already exist track."));
|
|
|
|
+ key_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTR("Insert Key (Existing Tracks)"), KEY_INSERT));
|
|
|
|
+ animation_hb->add_child(key_insert_button);
|
|
|
|
+
|
|
|
|
+ key_insert_all_button = memnew(Button);
|
|
|
|
+ key_insert_all_button->set_flat(true);
|
|
|
|
+ key_insert_all_button->set_focus_mode(FOCUS_NONE);
|
|
|
|
+ key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(true));
|
|
|
|
+ key_insert_all_button->set_tooltip(TTR("Insert key of all bone poses."));
|
|
|
|
+ key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KEY_MASK_CMD + KEY_INSERT));
|
|
|
|
+ animation_hb->add_child(key_insert_all_button);
|
|
|
|
+
|
|
|
|
+ // Bone tree.
|
|
const Color section_color = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
|
|
const Color section_color = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
|
|
|
|
|
|
EditorInspectorSection *bones_section = memnew(EditorInspectorSection);
|
|
EditorInspectorSection *bones_section = memnew(EditorInspectorSection);
|
|
@@ -613,12 +720,19 @@ void Skeleton3DEditor::create_editors() {
|
|
pose_editor->set_label(TTR("Bone Transform"));
|
|
pose_editor->set_label(TTR("Bone Transform"));
|
|
pose_editor->set_visible(false);
|
|
pose_editor->set_visible(false);
|
|
add_child(pose_editor);
|
|
add_child(pose_editor);
|
|
|
|
+
|
|
|
|
+ set_keyable(te->has_keying());
|
|
}
|
|
}
|
|
|
|
|
|
void Skeleton3DEditor::_notification(int p_what) {
|
|
void Skeleton3DEditor::_notification(int p_what) {
|
|
switch (p_what) {
|
|
switch (p_what) {
|
|
case NOTIFICATION_READY: {
|
|
case NOTIFICATION_READY: {
|
|
- edit_mode_button->set_icon(get_theme_icon("ToolBoneSelect", "EditorIcons"));
|
|
|
|
|
|
+ edit_mode_button->set_icon(get_theme_icon(SNAME("ToolBoneSelect"), SNAME("EditorIcons")));
|
|
|
|
+ key_loc_button->set_icon(get_theme_icon(SNAME("KeyPosition"), SNAME("EditorIcons")));
|
|
|
|
+ key_rot_button->set_icon(get_theme_icon(SNAME("KeyRotation"), SNAME("EditorIcons")));
|
|
|
|
+ key_scale_button->set_icon(get_theme_icon(SNAME("KeyScale"), SNAME("EditorIcons")));
|
|
|
|
+ key_insert_button->set_icon(get_theme_icon(SNAME("Key"), SNAME("EditorIcons")));
|
|
|
|
+ key_insert_all_button->set_icon(get_theme_icon(SNAME("NewKey"), SNAME("EditorIcons")));
|
|
get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Vector<Variant>(), Object::CONNECT_ONESHOT);
|
|
get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Vector<Variant>(), Object::CONNECT_ONESHOT);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -643,7 +757,6 @@ void Skeleton3DEditor::_node_removed(Node *p_node) {
|
|
if (skeleton && p_node == skeleton) {
|
|
if (skeleton && p_node == skeleton) {
|
|
skeleton = nullptr;
|
|
skeleton = nullptr;
|
|
skeleton_options->hide();
|
|
skeleton_options->hide();
|
|
- rest_options->hide();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
_update_properties();
|
|
_update_properties();
|
|
@@ -655,7 +768,6 @@ void Skeleton3DEditor::_bind_methods() {
|
|
ClassDB::bind_method(D_METHOD("_joint_tree_rmb_select"), &Skeleton3DEditor::_joint_tree_rmb_select);
|
|
ClassDB::bind_method(D_METHOD("_joint_tree_rmb_select"), &Skeleton3DEditor::_joint_tree_rmb_select);
|
|
ClassDB::bind_method(D_METHOD("_update_properties"), &Skeleton3DEditor::_update_properties);
|
|
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_skeleton_option"), &Skeleton3DEditor::_on_click_skeleton_option);
|
|
- ClassDB::bind_method(D_METHOD("_on_click_rest_option"), &Skeleton3DEditor::_on_click_rest_option);
|
|
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &Skeleton3DEditor::get_drag_data_fw);
|
|
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &Skeleton3DEditor::get_drag_data_fw);
|
|
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &Skeleton3DEditor::can_drop_data_fw);
|
|
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &Skeleton3DEditor::can_drop_data_fw);
|
|
@@ -866,6 +978,11 @@ Skeleton3DEditor::~Skeleton3DEditor() {
|
|
|
|
|
|
Node3DEditor *ne = Node3DEditor::get_singleton();
|
|
Node3DEditor *ne = Node3DEditor::get_singleton();
|
|
|
|
|
|
|
|
+ if (animation_hb) {
|
|
|
|
+ ne->remove_control_from_menu_panel(animation_hb);
|
|
|
|
+ memdelete(animation_hb);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (separator) {
|
|
if (separator) {
|
|
ne->remove_control_from_menu_panel(separator);
|
|
ne->remove_control_from_menu_panel(separator);
|
|
memdelete(separator);
|
|
memdelete(separator);
|
|
@@ -876,11 +993,6 @@ Skeleton3DEditor::~Skeleton3DEditor() {
|
|
memdelete(skeleton_options);
|
|
memdelete(skeleton_options);
|
|
}
|
|
}
|
|
|
|
|
|
- if (rest_options) {
|
|
|
|
- ne->remove_control_from_menu_panel(rest_options);
|
|
|
|
- memdelete(rest_options);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (edit_mode_button) {
|
|
if (edit_mode_button) {
|
|
ne->remove_control_from_menu_panel(edit_mode_button);
|
|
ne->remove_control_from_menu_panel(edit_mode_button);
|
|
memdelete(edit_mode_button);
|
|
memdelete(edit_mode_button);
|