Tweak/Add skeleton modifier keying button to top of the Viewport

This commit is contained in:
Silc Lizard (Tokage) Renew
2025-11-21 00:23:37 +09:00
parent 7716a4cba0
commit f4244fd61c
7 changed files with 105 additions and 28 deletions

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M.997 4v2h1v2h3v-2h2.133c.553 2.139 2.734 3.426 4.873 2.873s3.425-2.734 2.872-4.873-2.734-3.425-4.873-2.873c-1.408.364-2.509 1.464-2.873 2.873zm9.999-1c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2zM5.169 12.594c-.224.222-.225.583-.003.807 0 0 .001.002.003.002l2.426 2.43c.222.223.583.224.807.002 0-.001.001-.002.002-.002l2.427-2.429c.225-.222.225-.583.003-.807-.001-.001-.001-.002-.003-.002l-2.426-2.428c-.222-.225-.582-.227-.806-.005-.001.002-.002.003-.004.005z"/></svg>

After

Width:  |  Height:  |  Size: 567 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="m.997 4v2h1v2h3v-2h2.133c.552 2.139 2.733 3.426 4.873 2.873s3.425-2.734 2.872-4.873-2.734-3.425-4.873-2.873c-1.408.364-2.509 1.464-2.873 2.873zm9.999-1c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .897-2 2-2z"/><path fill="#fc7f7f" d="m4 11.5v-1.5h-4v1.5h1.25v3h-1.25v1.5h4v-1.5h-1.25v-3zm6 .001v-1.501h-1.5l-2 1.691v-1.691h-1.5v6h1.5v-1.688l2 1.688h1.5v-1.499h-.949l-1.776-1.501 1.774-1.499z"/><path fill="#e0e0e0" d="m10.169 12.594c-.225.223-.226.584-.003.807 0 0 .001.002.003.002l2.426 2.431c.222.224.583.224.807.002 0-.001.001-.002.002-.002l2.428-2.429c.225-.223.225-.584.003-.807-.001-.002-.001-.002-.003-.002l-2.427-2.429c-.222-.226-.581-.228-.806-.005-.001.002-.002.003-.004.005z"/></svg>

After

Width:  |  Height:  |  Size: 780 B

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2zm-3 .723A2 2 0 1 1 13 8h1v2h.445a4 4 0 1 0-7.314-3H1v2h1v2h3V9h2.133A4 4 0 0 0 8 10.627V10h2z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="m5.169 12.594c-.224.222-.225.583-.003.807 0 0 .001.002.003.002l2.426 2.43c.222.223.583.224.807.002 0-.001.001-.002.002-.002l2.427-2.429c.225-.222.225-.583.003-.807-.001-.001-.001-.002-.003-.002l-2.426-2.428c-.222-.225-.582-.227-.806-.005-.001.002-.002.003-.004.005z"/><path fill="#5fff97" d="m13.333 5v1.333h-1.333v1.333h1.333v1.334h1.334v-1.334h1.333v-1.333h-1.333v-1.333z"/><path fill="#e0e0e0" d="m12.333 8.666h-1.333v-1.666c-.001 0-.003 0-.004 0-1.104 0-2-.896-2-2s.896-2 2-2c.738 0 1.376.405 1.723 1h2.156c-.553-2.139-2.734-3.425-4.873-2.873-1.408.364-2.509 1.464-2.873 2.873h-6.132v2h1v2h3v-2h2.133c.553 2.139 2.734 3.426 4.873 2.873.116-.03.22-.083.331-.122v-.085z"/></svg>

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 768 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#fc7f7f" d="m4 11.5v-1.5h-4v1.5h1.25v3h-1.25v1.5h4v-1.5h-1.25v-3zm6 .001v-1.501h-1.5l-2 1.691v-1.691h-1.5v6h1.5v-1.688l2 1.688h1.5v-1.499h-.949l-1.776-1.501 1.774-1.499z"/><path fill="#e0e0e0" d="m10.169 12.594c-.225.223-.226.584-.003.807 0 0 .001.002.003.002l2.426 2.431c.222.224.583.224.807.002 0-.001.001-.002.002-.002l2.428-2.429c.225-.223.225-.584.003-.807-.001-.002-.001-.002-.003-.002l-2.427-2.429c-.222-.226-.581-.228-.806-.005-.001.002-.002.003-.004.005z"/><path fill="#5fff97" d="m13.333 5v1.333h-1.333v1.333h1.333v1.334h1.334v-1.334h1.333v-1.333h-1.333v-1.333z"/><path fill="#e0e0e0" d="m12.333 8.666h-1.333v-1.666c-.001 0-.003 0-.004 0-1.104 0-2-.896-2-2s.896-2 2-2c.738 0 1.376.405 1.723 1h2.156c-.553-2.139-2.734-3.425-4.873-2.873-1.408.364-2.509 1.464-2.873 2.873h-6.132v2h1v2h3v-2h2.133c.553 2.139 2.733 3.426 4.873 2.873.116-.029.22-.083.331-.122z"/></svg>

After

Width:  |  Height:  |  Size: 949 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M8.445 9.308v-3.001c1.613-.944 2.156-3.016 1.213-4.631-.603-1.033-1.709-1.67-2.905-1.676h-3.385c-1.869.008-3.377 1.532-3.368 3.401.005 1.197.643 2.301 1.676 2.906v3.001c0 .934.758 1.692 1.692 1.692h3.385c.935 0 1.692-.758 1.692-1.692zm-4.23-5.077h1.692v.846h-1.692zm-2.539-.846c0-.468.378-.846.847-.846.468 0 .846.378.846.846 0 .467-.378.846-.846.846-.469 0-.847-.379-.847-.846zm5.923 5.923h-.846v-.847h-.846v.846h-1.692v-.846h-.847v.846h-.846v-3.384h.846v.846h.847v-.846h1.692v.846h.846v-.846h.846zm-.846-5.923c0-.468.378-.846.846-.846s.846.378.846.846c0 .467-.378.846-.846.846s-.846-.379-.846-.846zM15.294 8.617c-.198-.132-.424-.219-.658-.251-.122-.867-.921-1.471-1.787-1.351s-1.472.921-1.353 1.788c.034.235.119.46.251.658l-2.286 2.286c-.729-.484-1.712-.287-2.195.443-.486.727-.287 1.71.441 2.194.198.131.423.217.659.25.121.865.922 1.471 1.787 1.35.866-.12 1.471-.919 1.351-1.786-.034-.235-.118-.46-.25-.658l2.286-2.286c.728.483 1.712.285 2.195-.443.484-.727.287-1.711-.441-2.194z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -366,9 +366,7 @@ void Skeleton3DEditor::_bind_methods() {
}
void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
if (!skeleton) {
return;
}
ERR_FAIL_COND(!skeleton);
switch (p_skeleton_option) {
case SKELETON_OPTION_RESET_ALL_POSES: {
@ -399,9 +397,8 @@ void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
}
void Skeleton3DEditor::reset_pose(const bool p_all_bones) {
if (!skeleton) {
return;
}
ERR_FAIL_COND(!skeleton);
const int bone_count = skeleton->get_bone_count();
if (!bone_count) {
return;
@ -434,16 +431,34 @@ void Skeleton3DEditor::reset_pose(const bool p_all_bones) {
ur->commit_action();
}
void Skeleton3DEditor::insert_keys(const bool p_all_bones) {
void Skeleton3DEditor::insert_keys(const bool p_all_bones, const bool p_enable_modifier) {
ERR_FAIL_COND(!skeleton);
AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
bool is_read_only = te->is_read_only();
if (is_read_only) {
te->popup_read_only_dialog();
return;
}
if (!skeleton) {
return;
if (p_enable_modifier) {
if (!skeleton->is_connected(SceneStringName(skeleton_updated), callable_mp(this, &Skeleton3DEditor::_insert_keys).bind(p_all_bones))) {
skeleton->connect(SceneStringName(skeleton_updated), callable_mp(this, &Skeleton3DEditor::_insert_keys).bind(p_all_bones), CONNECT_ONE_SHOT);
} else {
WARN_PRINT_ED("A skeleton_updated signal is already connected with _insert_keys().");
}
skeleton->force_update_deferred();
skeleton->notification(Skeleton3D::NOTIFICATION_UPDATE_SKELETON);
// Force disconnecting signal if remain the connecting just in case.
if (skeleton->is_connected(SceneStringName(skeleton_updated), callable_mp(this, &Skeleton3DEditor::_insert_keys).bind(p_all_bones))) {
skeleton->disconnect(SceneStringName(skeleton_updated), callable_mp(this, &Skeleton3DEditor::_insert_keys).bind(p_all_bones));
}
} else {
_insert_keys(p_all_bones);
}
}
void Skeleton3DEditor::_insert_keys(const bool p_all_bones) {
ERR_FAIL_COND(!skeleton);
bool pos_enabled = key_loc_button->is_pressed();
bool rot_enabled = key_rot_button->is_pressed();
@ -453,6 +468,7 @@ void Skeleton3DEditor::insert_keys(const bool p_all_bones) {
Node *root = EditorNode::get_singleton()->get_tree()->get_root();
String path = String(root->get_path_to(skeleton));
AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
te->make_insert_queue();
for (int i = 0; i < bone_len; i++) {
const String name = skeleton->get_bone_name(i);
@ -475,9 +491,8 @@ void Skeleton3DEditor::insert_keys(const bool p_all_bones) {
}
void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) {
if (!skeleton) {
return;
}
ERR_FAIL_COND(!skeleton);
const int bone_count = skeleton->get_bone_count();
if (!bone_count) {
return;
@ -1053,42 +1068,67 @@ void Skeleton3DEditor::create_editors() {
key_loc_button = memnew(Button);
key_loc_button->set_theme_type_variation(SceneStringName(FlatButton));
key_loc_button->set_toggle_mode(true);
key_loc_button->set_pressed(false);
key_loc_button->set_pressed(editor_plugin->loc_pressed);
key_loc_button->set_focus_mode(FOCUS_ACCESSIBILITY);
key_loc_button->set_tooltip_text(TTR("Translation mask for inserting keys."));
animation_hb->add_child(key_loc_button);
if (!key_loc_button->is_connected(SceneStringName(toggled), callable_mp(this, &Skeleton3DEditor::_loc_toggled))) {
key_loc_button->connect(SceneStringName(toggled), callable_mp(this, &Skeleton3DEditor::_loc_toggled));
}
key_rot_button = memnew(Button);
key_rot_button->set_theme_type_variation(SceneStringName(FlatButton));
key_rot_button->set_toggle_mode(true);
key_rot_button->set_pressed(true);
key_rot_button->set_pressed(editor_plugin->rot_pressed);
key_rot_button->set_focus_mode(FOCUS_ACCESSIBILITY);
key_rot_button->set_tooltip_text(TTR("Rotation mask for inserting keys."));
animation_hb->add_child(key_rot_button);
if (!key_rot_button->is_connected(SceneStringName(toggled), callable_mp(this, &Skeleton3DEditor::_rot_toggled))) {
key_rot_button->connect(SceneStringName(toggled), callable_mp(this, &Skeleton3DEditor::_rot_toggled));
}
key_scale_button = memnew(Button);
key_scale_button->set_theme_type_variation(SceneStringName(FlatButton));
key_scale_button->set_toggle_mode(true);
key_scale_button->set_pressed(false);
key_scale_button->set_pressed(editor_plugin->scl_pressed);
key_scale_button->set_focus_mode(FOCUS_ACCESSIBILITY);
key_scale_button->set_tooltip_text(TTR("Scale mask for inserting keys."));
animation_hb->add_child(key_scale_button);
if (!key_scale_button->is_connected(SceneStringName(toggled), callable_mp(this, &Skeleton3DEditor::_scl_toggled))) {
key_scale_button->connect(SceneStringName(toggled), callable_mp(this, &Skeleton3DEditor::_scl_toggled));
}
key_insert_button = memnew(Button);
key_insert_button->set_theme_type_variation(SceneStringName(FlatButton));
key_insert_button->set_focus_mode(FOCUS_ACCESSIBILITY);
key_insert_button->connect(SceneStringName(pressed), callable_mp(this, &Skeleton3DEditor::insert_keys).bind(false));
key_insert_button->connect(SceneStringName(pressed), callable_mp(this, &Skeleton3DEditor::insert_keys).bind(false, false));
key_insert_button->set_tooltip_text(TTRC("Insert key (based on mask) for bones with an existing track."));
key_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTRC("Insert Key (Existing Tracks)"), Key::INSERT));
animation_hb->add_child(key_insert_button);
key_insert_all_button = memnew(Button);
key_insert_all_button->set_theme_type_variation(SceneStringName(FlatButton));
key_insert_all_button->set_focus_mode(FOCUS_ACCESSIBILITY);
key_insert_all_button->connect(SceneStringName(pressed), callable_mp(this, &Skeleton3DEditor::insert_keys).bind(true));
key_insert_all_button->set_tooltip_text(TTRC("Insert key (based on mask) for all bones."));
key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTRC("Insert Key (All Bones)"), KeyModifierMask::CMD_OR_CTRL + Key::INSERT));
animation_hb->add_child(key_insert_all_button);
key_insert_new_button = memnew(Button);
key_insert_new_button->set_theme_type_variation(SceneStringName(FlatButton));
key_insert_new_button->set_focus_mode(FOCUS_ACCESSIBILITY);
key_insert_new_button->connect(SceneStringName(pressed), callable_mp(this, &Skeleton3DEditor::insert_keys).bind(true, false));
key_insert_new_button->set_tooltip_text(TTRC("Insert key (based on mask) for all bones."));
key_insert_new_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTRC("Insert Key (All Bones)"), KeyModifierMask::CMD_OR_CTRL + Key::INSERT));
animation_hb->add_child(key_insert_new_button);
key_mod_insert_button = memnew(Button);
key_mod_insert_button->set_theme_type_variation(SceneStringName(FlatButton));
key_mod_insert_button->set_focus_mode(FOCUS_ACCESSIBILITY);
key_mod_insert_button->connect(SceneStringName(pressed), callable_mp(this, &Skeleton3DEditor::insert_keys).bind(false, true));
key_mod_insert_button->set_tooltip_text(TTRC("Insert key (based on mask) for modified bones with an existing track."));
key_mod_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTRC("Insert Key (Existing Tracks)"), Key::INSERT));
animation_hb->add_child(key_mod_insert_button);
key_mod_insert_new_button = memnew(Button);
key_mod_insert_new_button->set_theme_type_variation(SceneStringName(FlatButton));
key_mod_insert_new_button->set_focus_mode(FOCUS_ACCESSIBILITY);
key_mod_insert_new_button->connect(SceneStringName(pressed), callable_mp(this, &Skeleton3DEditor::insert_keys).bind(true, true));
key_mod_insert_new_button->set_tooltip_text(TTRC("Insert new key (based on mask) for all modified bones."));
key_mod_insert_new_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTRC("Insert Key (All Bones)"), KeyModifierMask::CMD_OR_CTRL + Key::INSERT));
animation_hb->add_child(key_mod_insert_new_button);
// Bone tree.
bones_section = memnew(EditorInspectorSection);
@ -1122,6 +1162,25 @@ void Skeleton3DEditor::create_editors() {
set_keyable(te->has_keying());
}
void Skeleton3DEditor::_loc_toggled(bool p_toggled_on) {
if (!editor_plugin) {
return;
}
editor_plugin->loc_pressed = p_toggled_on;
}
void Skeleton3DEditor::_rot_toggled(bool p_toggled_on) {
if (!editor_plugin) {
return;
}
editor_plugin->rot_pressed = p_toggled_on;
}
void Skeleton3DEditor::_scl_toggled(bool p_toggled_on) {
if (!editor_plugin) {
return;
}
editor_plugin->scl_pressed = p_toggled_on;
}
void Skeleton3DEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@ -1148,8 +1207,10 @@ void Skeleton3DEditor::_notification(int p_what) {
key_loc_button->set_button_icon(get_editor_theme_icon(SNAME("KeyPosition")));
key_rot_button->set_button_icon(get_editor_theme_icon(SNAME("KeyRotation")));
key_scale_button->set_button_icon(get_editor_theme_icon(SNAME("KeyScale")));
key_insert_button->set_button_icon(get_editor_theme_icon(SNAME("Key")));
key_insert_all_button->set_button_icon(get_editor_theme_icon(SNAME("NewKey")));
key_insert_button->set_button_icon(get_editor_theme_icon(SNAME("InsertKey")));
key_insert_new_button->set_button_icon(get_editor_theme_icon(SNAME("NewKey")));
key_mod_insert_button->set_button_icon(get_editor_theme_icon(SNAME("InsertModKey")));
key_mod_insert_new_button->set_button_icon(get_editor_theme_icon(SNAME("NewModKey")));
bones_section->set_bg_color(get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
update_joint_tree();

View File

@ -147,7 +147,14 @@ class Skeleton3DEditor : public VBoxContainer {
Button *key_rot_button = nullptr;
Button *key_scale_button = nullptr;
Button *key_insert_button = nullptr;
Button *key_insert_all_button = nullptr;
Button *key_insert_new_button = nullptr;
Button *key_mod_insert_button = nullptr;
Button *key_mod_insert_new_button = nullptr;
// To maintain the status while running editor.
void _loc_toggled(bool p_toggled_on);
void _rot_toggled(bool p_toggled_on);
void _scl_toggled(bool p_toggled_on);
EditorInspectorSection *bones_section = nullptr;
@ -172,7 +179,8 @@ class Skeleton3DEditor : public VBoxContainer {
void reset_pose(const bool p_all_bones);
void pose_to_rest(const bool p_all_bones);
void insert_keys(const bool p_all_bones);
void _insert_keys(const bool p_all_bones);
void insert_keys(const bool p_all_bones, const bool p_enable_modifier);
void create_physical_skeleton();
PhysicalBone3D *create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos);
@ -247,6 +255,10 @@ class EditorInspectorPluginSkeleton : public EditorInspectorPlugin {
Skeleton3DEditor *skel_editor = nullptr;
public:
bool loc_pressed = false;
bool rot_pressed = true;
bool scl_pressed = false;
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
};