Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Skeleton Editor Gizmo #45699

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions doc/classes/EditorPlugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
</description>
</method>
<method name="_forward_3d_gui_input" qualifiers="virtual">
<return type="bool" />
<return type="int" />
<argument index="0" name="viewport_camera" type="Camera3D" />
<argument index="1" name="event" type="InputEvent" />
<description>
Expand All @@ -105,13 +105,13 @@
[gdscript]
# Prevents the InputEvent to reach other Editor classes.
func _forward_3d_gui_input(camera, event):
return true
return EditorPlugin.AFTER_GUI_INPUT_STOP
[/gdscript]
[csharp]
// Prevents the InputEvent to reach other Editor classes.
public override bool _Forward3dGuiInput(Camera3D camera, InputEvent @event)
{
return true;
return EditorPlugin.AFTER_GUI_INPUT_STOP;
}
[/csharp]
[/codeblocks]
Expand Down Expand Up @@ -185,12 +185,12 @@
Called when there is a root node in the current edited scene, [method _handles] is implemented and an [InputEvent] happens in the 2D viewport. Intercepts the [InputEvent], if [code]return true[/code] [EditorPlugin] consumes the [code]event[/code], otherwise forwards [code]event[/code] to other Editor classes. Example:
[codeblocks]
[gdscript]
# Prevents the InputEvent to reach other Editor classes
# Prevents the InputEvent to reach other Editor classes.
func _forward_canvas_gui_input(event):
return true
[/gdscript]
[csharp]
// Prevents the InputEvent to reach other Editor classes
// Prevents the InputEvent to reach other Editor classes.
public override bool ForwardCanvasGuiInput(InputEvent @event)
{
return true;
Expand All @@ -202,13 +202,18 @@
[gdscript]
# Consumes InputEventMouseMotion and forwards other InputEvent types.
func _forward_canvas_gui_input(event):
return event is InputEventMouseMotion
if (event is InputEventMouseMotion):
return true
return false
[/gdscript]
[csharp]
// Consumes InputEventMouseMotion and forwards other InputEvent types.
public override bool ForwardCanvasGuiInput(InputEvent @event)
{
return @event is InputEventMouseMotion;
if (@event is InputEventMouseMotion) {
return true;
}
return false
}
[/csharp]
[/codeblocks]
Expand Down
9 changes: 9 additions & 0 deletions doc/classes/Node3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,15 @@
Sets whether the node notifies about its global and local transformation changes. [Node3D] will not propagate this by default, unless it is in the editor context and it has a valid gizmo.
</description>
</method>
<method name="set_subgizmo_selection">
<return type="void" />
<argument index="0" name="gizmo" type="Node3DGizmo" />
<argument index="1" name="id" type="int" />
<argument index="2" name="transform" type="Transform3D" />
<description>
Set subgizmo selection for this node in the editor.
</description>
</method>
<method name="show">
<return type="void" />
<description>
Expand Down
26 changes: 26 additions & 0 deletions doc/classes/Skeleton3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,13 @@
This is helper function to make using [method Transform3D.looking_at] easier with bone poses.
</description>
</method>
<method name="is_bone_enabled" qualifiers="const">
<return type="bool" />
<argument index="0" name="bone_idx" type="int" />
<description>
Returns whether the bone pose for the bone at [code]bone_idx[/code] is enabled.
</description>
</method>
<method name="is_bone_rest_disabled" qualifiers="const">
<return type="bool" />
<argument index="0" name="bone_idx" type="int" />
Expand Down Expand Up @@ -282,6 +289,14 @@
Disables the rest pose for the bone at [code]bone_idx[/code] if [code]true[/code], enables the bone rest if [code]false[/code].
</description>
</method>
<method name="set_bone_enabled">
<return type="void" />
<argument index="0" name="bone_idx" type="int" />
<argument index="1" name="enabled" type="bool" default="true" />
<description>
Disables the pose for the bone at [code]bone_idx[/code] if [code]false[/code], enables the bone pose if [code]true[/code].
</description>
</method>
<method name="set_bone_global_pose_override">
<return type="void" />
<argument index="0" name="bone_idx" type="int" />
Expand Down Expand Up @@ -365,8 +380,15 @@
<members>
<member name="animate_physical_bones" type="bool" setter="set_animate_physical_bones" getter="get_animate_physical_bones" default="true">
</member>
<member name="show_rest_only" type="bool" setter="set_show_rest_only" getter="is_show_rest_only" default="false">
</member>
</members>
<signals>
<signal name="bone_enabled_changed">
<argument index="0" name="bone_idx" type="int" />
<description>
</description>
</signal>
<signal name="bone_pose_changed">
<argument index="0" name="bone_idx" type="int" />
<description>
Expand All @@ -377,6 +399,10 @@
<description>
</description>
</signal>
<signal name="show_rest_only_changed">
<description>
</description>
</signal>
</signals>
<constants>
<constant name="NOTIFICATION_UPDATE_SKELETON" value="50">
Expand Down
47 changes: 36 additions & 11 deletions editor/animation_track_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3359,7 +3359,7 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
insert_data.push_back(p_id);

bool reset_allowed = true;
AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
if (player->has_animation("RESET") && player->get_animation("RESET") == animation) {
// Avoid messing with the reset animation itself
reset_allowed = false;
Expand Down Expand Up @@ -3528,6 +3528,31 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
_query_insert(id);
}

bool AnimationTrackEditor::has_transform_track(Node3D *p_node, const String &p_sub) {
if (!keying) {
return false;
}
if (!animation.is_valid()) {
return false;
}
if (!root) {
return false;
}

//let's build a node path
String path = root->get_path_to(p_node);
if (p_sub != "") {
path += ":" + p_sub;
}
int track_id = animation->find_track(path);
if (track_id >= 0) {
if (animation->track_get_type(track_id) == Animation::TYPE_TRANSFORM3D) {
return true;
}
}
return false;
}

void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant &p_value) {
String path = p_path;

Expand Down Expand Up @@ -3571,7 +3596,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
String path = root->get_path_to(node);

if (Object::cast_to<AnimationPlayer>(node) && p_property == "current_animation") {
if (node == AnimationPlayerEditor::singleton->get_player()) {
if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
Expand Down Expand Up @@ -3672,7 +3697,7 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
String path = root->get_path_to(node);

if (Object::cast_to<AnimationPlayer>(node) && p_property == "current_animation") {
if (node == AnimationPlayerEditor::singleton->get_player()) {
if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
Expand Down Expand Up @@ -3752,17 +3777,17 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
}

Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
if (player->has_animation("RESET")) {
return player->get_animation("RESET");
} else {
Ref<Animation> reset_anim;
reset_anim.instantiate();
reset_anim->set_length(ANIM_MIN_LENGTH);
undo_redo->add_do_method(player, "add_animation", "RESET", reset_anim);
undo_redo->add_do_method(AnimationPlayerEditor::singleton, "_animation_player_changed", player);
undo_redo->add_do_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player);
undo_redo->add_undo_method(player, "remove_animation", "RESET");
undo_redo->add_undo_method(AnimationPlayerEditor::singleton, "_animation_player_changed", player);
undo_redo->add_undo_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player);
return reset_anim;
}
}
Expand Down Expand Up @@ -4446,7 +4471,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
return;
}

if (node == AnimationPlayerEditor::singleton->get_player()) {
if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
Expand Down Expand Up @@ -5173,7 +5198,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
}

void AnimationTrackEditor::_edit_menu_about_to_popup() {
AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), !player->can_apply_reset());
}

Expand Down Expand Up @@ -5517,7 +5542,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
goto_prev_step(false);
} break;
case EDIT_APPLY_RESET: {
AnimationPlayerEditor::singleton->get_player()->apply_reset(true);
AnimationPlayerEditor::get_singleton()->get_player()->apply_reset(true);

} break;
case EDIT_OPTIMIZE_ANIMATION: {
Expand All @@ -5537,9 +5562,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
case EDIT_CLEAN_UP_ANIMATION_CONFIRM: {
if (cleanup_all->is_pressed()) {
List<StringName> names;
AnimationPlayerEditor::singleton->get_player()->get_animation_list(&names);
AnimationPlayerEditor::get_singleton()->get_player()->get_animation_list(&names);
for (const StringName &E : names) {
_cleanup_animation(AnimationPlayerEditor::singleton->get_player()->get_animation(E));
_cleanup_animation(AnimationPlayerEditor::get_singleton()->get_player()->get_animation(E));
}
} else {
_cleanup_animation(animation);
Expand Down
1 change: 1 addition & 0 deletions editor/animation_track_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ class AnimationTrackEditor : public VBoxContainer {
void insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists = false);
void insert_value_key(const String &p_property, const Variant &p_value, bool p_advance);
void insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform);
bool has_transform_track(Node3D *p_node, const String &p_sub);

void show_select_node_warning(bool p_show);

Expand Down
16 changes: 10 additions & 6 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6930,7 +6930,7 @@ EditorNode::EditorNode() {
add_child(editor_interface);

//more visually meaningful to have this later
raise_bottom_panel_item(AnimationPlayerEditor::singleton);
raise_bottom_panel_item(AnimationPlayerEditor::get_singleton());

add_editor_plugin(VersionControlEditorPlugin::get_singleton());
add_editor_plugin(memnew(ShaderEditorPlugin(this)));
Expand Down Expand Up @@ -7204,20 +7204,24 @@ bool EditorPluginList::forward_gui_input(const Ref<InputEvent> &p_event) {
return discard;
}

bool EditorPluginList::forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled) {
bool discard = false;
EditorPlugin::AfterGUIInput EditorPluginList::forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled) {
EditorPlugin::AfterGUIInput after = EditorPlugin::AFTER_GUI_INPUT_PASS;

for (int i = 0; i < plugins_list.size(); i++) {
if ((!serve_when_force_input_enabled) && plugins_list[i]->is_input_event_forwarding_always_enabled()) {
continue;
}

if (plugins_list[i]->forward_spatial_gui_input(p_camera, p_event)) {
discard = true;
EditorPlugin::AfterGUIInput current_after = plugins_list[i]->forward_spatial_gui_input(p_camera, p_event);
if (current_after == EditorPlugin::AFTER_GUI_INPUT_STOP) {
after = EditorPlugin::AFTER_GUI_INPUT_STOP;
}
if (after != EditorPlugin::AFTER_GUI_INPUT_STOP && current_after == EditorPlugin::AFTER_GUI_INPUT_DESELECT) {
after = EditorPlugin::AFTER_GUI_INPUT_DESELECT;
}
}

return discard;
return after;
}

void EditorPluginList::forward_canvas_draw_over_viewport(Control *p_overlay) {
Expand Down
2 changes: 1 addition & 1 deletion editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -942,7 +942,7 @@ class EditorPluginList : public Object {
bool forward_gui_input(const Ref<InputEvent> &p_event);
void forward_canvas_draw_over_viewport(Control *p_overlay);
void forward_canvas_force_draw_over_viewport(Control *p_overlay);
bool forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled);
EditorPlugin::AfterGUIInput forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled);
void forward_spatial_draw_over_viewport(Control *p_overlay);
void forward_spatial_force_draw_over_viewport(Control *p_overlay);
void add_plugin(EditorPlugin *p_plugin);
Expand Down
8 changes: 4 additions & 4 deletions editor/editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,14 +593,14 @@ int EditorPlugin::update_overlays() const {
}
}

bool EditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) {
bool success;
EditorPlugin::AfterGUIInput EditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) {
int success;

if (GDVIRTUAL_CALL(_forward_3d_gui_input, p_camera, p_event, success)) {
return success;
return static_cast<EditorPlugin::AfterGUIInput>(success);
}

return false;
return EditorPlugin::AFTER_GUI_INPUT_PASS;
}

void EditorPlugin::forward_spatial_draw_over_viewport(Control *p_overlay) {
Expand Down
10 changes: 8 additions & 2 deletions editor/editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class EditorPlugin : public Node {
GDVIRTUAL1R(bool, _forward_canvas_gui_input, Ref<InputEvent>)
GDVIRTUAL1(_forward_canvas_draw_over_viewport, Control *)
GDVIRTUAL1(_forward_canvas_force_draw_over_viewport, Control *)
GDVIRTUAL2R(bool, _forward_3d_gui_input, Camera3D *, Ref<InputEvent>)
GDVIRTUAL2R(int, _forward_3d_gui_input, Camera3D *, Ref<InputEvent>)
GDVIRTUAL1(_forward_3d_draw_over_viewport, Control *)
GDVIRTUAL1(_forward_3d_force_draw_over_viewport, Control *)
GDVIRTUAL0RC(String, _get_plugin_name)
Expand Down Expand Up @@ -200,6 +200,12 @@ class EditorPlugin : public Node {
DOCK_SLOT_MAX
};

enum AfterGUIInput {
AFTER_GUI_INPUT_PASS,
AFTER_GUI_INPUT_STOP,
AFTER_GUI_INPUT_DESELECT
};

TokageItLab marked this conversation as resolved.
Show resolved Hide resolved
//TODO: send a resource for editing to the editor node?

void add_control_to_container(CustomControlContainer p_location, Control *p_control);
Expand Down Expand Up @@ -228,7 +234,7 @@ class EditorPlugin : public Node {
virtual void forward_canvas_draw_over_viewport(Control *p_overlay);
virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay);

virtual bool forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event);
virtual EditorPlugin::AfterGUIInput forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event);
virtual void forward_spatial_draw_over_viewport(Control *p_overlay);
virtual void forward_spatial_force_draw_over_viewport(Control *p_overlay);

Expand Down
1 change: 1 addition & 0 deletions editor/editor_themes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
exceptions.insert("EditorPivot");
exceptions.insert("EditorHandle");
exceptions.insert("Editor3DHandle");
exceptions.insert("EditorBoneHandle");
exceptions.insert("Godot");
exceptions.insert("Sky");
exceptions.insert("EditorControlAnchor");
Expand Down
1 change: 1 addition & 0 deletions editor/icons/EditorBoneHandle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions editor/icons/ToolBoneSelect.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions editor/inspector_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,15 +383,15 @@ void InspectorDock::_menu_expandall() {
}

void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
AnimationPlayerEditor::singleton->get_track_editor()->insert_value_key(p_keyed, p_value, p_advance);
AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_value_key(p_keyed, p_value, p_advance);
}

void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform3D &p_key) {
Node3D *s = Object::cast_to<Node3D>(sp);
if (!s) {
return;
}
AnimationPlayerEditor::singleton->get_track_editor()->insert_transform_key(s, p_sub, p_key);
AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, p_key);
}

void InspectorDock::_warning_pressed() {
Expand Down Expand Up @@ -545,7 +545,7 @@ void InspectorDock::go_back() {
void InspectorDock::update_keying() {
bool valid = false;

if (AnimationPlayerEditor::singleton->get_track_editor()->has_keying()) {
if (AnimationPlayerEditor::get_singleton()->get_track_editor()->has_keying()) {
EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
if (editor_history->get_path_size() >= 1) {
Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0));
Expand Down
Loading