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

Conversation

TokageItLab
Copy link
Member

@TokageItLab TokageItLab commented Feb 4, 2021

Skeleton's TreeEditor was implemented in #36409, but the gizmo for editing was not (ref: 584 and #1767). So, the gizmo in SkeletonEditor, which was developed in the 3.2.x branch, is now complete tentatively. This is a draft PR for porting to 4.0.

https://www.youtube.com/watch?v=RjJiEo8uqPw

Dev branch for 3.2.x is here.

Features

pr1

When you select skeleton and bone edit tool, marker circles will appear on the joints. If you select a marker, a transform gizmo will appear, which looks the same as SpatialTransformGizmo but behaves a bit differently. Basically, in character animation, there is no editing other than rotate. So to make the editing process smoother, you can make selections in all Move/Rotate/Scale modes. Instead, there is no free transform mode, which I may implement somewhere else. the behavior was unified by SubGizmo implementation.

pr2

There is a PoseMode and a RestMode; during RestMode, Pose and CustomPose are temporarily disabled, and RestMode will be canceled when you exit the SkeletonEditor. However, there is no CustomPoseMode, because there is no way to disable only the Pose while the CustomPose is enabled.

pr3

Add the following options to SkeletonButton's popups in toolber

  • Init pose
  • Insert key of all bone poses
  • Insert key of bone poses already exist track
  • Apply current pose to rest

All of these are basically applied to all bones. Init pose initializes the Pose, but not the CustomPose. Insert key is activated when the animation player has a track, similar to Spatial's KeyButton. Be careful with Apply current pose to rest. It initializes the current Pose and CustomPose, and changes Rest.

Changes/Bugfixes

SkeletonEditor

  • Added int selected_bone
  • Removed the Pose Enabled checkbox in SkeletonBoneEditor to prevent conflicts in RestMode

SpatialEditorGizmo

  • Skeleton's gizmo is now at the front of the screen when skeleton is selected
  • Show the local axis of the bones when selecting a skeleton
  • Highlight the currently selected bone
  • Added selected bone color and bone axis length to EditorSettings

SpatialEditorPlugin

  • Added Vector<Transform> external
  • Added ToolExternal to ToolMode
  • forward_spatial_gui_input() passes the id of the Viewport
  • Some private functions changed to public

These were superseded SubGizmo implementation.

AnimationTrackEditor

  • Added has_transform_track()

Done

  • Porting for 4.0
  • Fix depth drawing order in gizmo (with the shader by @lyuma )
  • Consider the size and shape of the joint marker
  • Adopt SubGizmos
  • Behavior for negative scales is not ensured
  • Set readonly to bone pose in rest mode after marge Apply set_read_only() to child classes of EditorProperty elements #51722
  • Octahedron as bone gizmo in SpatialEditorGizmo weight assignment and updated timing are strange (superseded selectable gizmo shape with Wire shape)

Other Issues (Todo in the future)

@JFonS
Copy link
Contributor

JFonS commented Feb 4, 2021

I think you missed most of the changes in your commit, I can only see a modification in skeleton_3d_editor_plugin.cpp :)

@fire
Copy link
Member

fire commented Feb 4, 2021

Can you write a description of the ExternalToolMode system? This is the api addition to Node3d gizmos we wanted to add, but it's hard to describe to other contributors.

Edited:

We finalized with a different proposal.

@Calinou Calinou added this to the 4.0 milestone Feb 4, 2021
@TokageItLab TokageItLab force-pushed the implement-skeleton-editor-gizmo branch 14 times, most recently from 63b5af1 to a1640b9 Compare February 6, 2021 14:32
@TokageItLab
Copy link
Member Author

TokageItLab commented Feb 6, 2021

@JFonS @fire Porting was done. There are a few issues that need to be fixed, but you can check that it works for now.

  • The depth drawing order in gizmo is messed up. In 3.2.x I used a hack with vertex shader to change the draw order, but this is no longer available in 4.0, so I need to find another way.
  • It was decided in discussion with reduz and others to implement SubGizmos first instead of ExternalMode in Node3DEditor.

@TokageItLab TokageItLab marked this pull request as ready for review February 6, 2021 14:50
@TokageItLab TokageItLab force-pushed the implement-skeleton-editor-gizmo branch 2 times, most recently from 0f958d3 to c1db100 Compare February 6, 2021 16:02
@TokageItLab
Copy link
Member Author

TokageItLab commented Feb 6, 2021

Depth problem was solved. It's a bit hacky so this may be a problem for some rendering engines other than vulkan, but it maintains the drawing order in 3D space. If you want to avoid hack, we need to implement a separate drawing layer for gizmo (ref: #2138).

@TokageItLab TokageItLab force-pushed the implement-skeleton-editor-gizmo branch 2 times, most recently from 8314892 to fdf17f3 Compare February 7, 2021 05:27
@TokageItLab TokageItLab requested a review from a team as a code owner February 16, 2021 11:53
@TokageItLab TokageItLab force-pushed the implement-skeleton-editor-gizmo branch 5 times, most recently from 53663af to fbc171e Compare September 8, 2021 14:24
@TokageItLab
Copy link
Member Author

TokageItLab commented Sep 9, 2021

It seems that reduz is thinking of getting rid of the bone rest. He has a point since it may be not good to allow users to easily handle posing with bone rests. However, when it comes to retargeting or adjusting axes, rest needs to be changed.

Therefore, it would be better to omit the implementation of rest mode bone manipulation, and make rest and custom poses read only in the inspector, and instead add a "Rest Option" in the 3D View menu, such as operating "Set global rest", "Unify roll axis to specific axis", "Swap axis" and etc (everything will do with changing the skin poses).

@lyuma
Copy link
Contributor

lyuma commented Sep 9, 2021

As a followup to the idea of removing bone_rest as it currently is... and just jotting down some thoughts I had recently: I've been increasingly thinking that rest_pose should become an animation concept of some sort, and added to "rotation", "position" and "scale" type tracks.

Basically, Animations could use the rest matrix (transform/rotation/scale) applied one after the other, so there is no problem with non-uniform matrices but you can still assign "identity" tracks in the animation to reset the object to the rest pose.

Another option is for the animation transform track to be separated into animation position track, rotation track and scale track (note that a Transform track internally already stores data in this form, but it requires all 10 values to be set, even though most animations only change rotation)... that way, the position would remain unchanged and the bone rest does not need to be stored.

@TokageItLab
Copy link
Member Author

Updated:

  • Omit rest mode
  • Rest and Custom Pose are forced readonly in inspector
  • Bone shape is able to be changed in EditorSetting
  • Implemented ShowRestOnly mode in Skeleton

@TokageItLab TokageItLab force-pushed the implement-skeleton-editor-gizmo branch 3 times, most recently from f379f19 to ba49f3e Compare September 13, 2021 03:43
@TokageItLab TokageItLab force-pushed the implement-skeleton-editor-gizmo branch 4 times, most recently from f019835 to 6812184 Compare October 2, 2021 04:51
Copy link
Contributor

@JFonS JFonS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in general, amazing work :)

I left some comments on minor details and some changes that need to be made, but the overall design is good.

I also found a crash while testing. It can be reproduced with an animated skeleton:

  1. Have a scene with a skeleton and an AnimationPlayer that contains an animation for the skeleton.
  2. Open animation editor with and the skeleton animation.
  3. Select the animated skeleton, so the gizmo is drawn (the animation doesn't need to be playing).
  4. Close the scene.
  5. Crash happens.

I fixed it with the following changes:

diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp	
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp	
@@ -356,6 +356,7 @@
 
 void Skeleton3DEditor::_update_show_rest_only() {
 	_update_pose_enabled(-1);
+	_update_gizmo_visible();
 }
 
 void Skeleton3DEditor::_update_pose_enabled(int p_bone) {
@@ -370,7 +371,6 @@
 			pose_editor->set_transform_read_only(skeleton->is_show_rest_only() || !(skeleton->is_bone_enabled(selected)));
 		}
 	}
-	_update_gizmo_visible();
 }
 
 void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
@@ -667,6 +667,7 @@
 	set_rest_options_enabled(selected);
 	_update_properties();
 	_update_pose_enabled();
+	_update_gizmo_visible();
 }
 
 // May be not used with single select mode.

But please check if the fix makes sense and feel free to change it if it doesn't.

doc/classes/EditorPlugin.xml Outdated Show resolved Hide resolved
doc/classes/EditorPlugin.xml Outdated Show resolved Hide resolved
doc/classes/EditorPlugin.xml Outdated Show resolved Hide resolved
editor/plugins/skeleton_3d_editor_plugin.cpp Outdated Show resolved Hide resolved
editor/plugins/skeleton_3d_editor_plugin.cpp Outdated Show resolved Hide resolved
editor/plugins/skeleton_3d_editor_plugin.h Outdated Show resolved Hide resolved
scene/3d/skeleton_3d.cpp Outdated Show resolved Hide resolved
scene/3d/skeleton_3d.cpp Outdated Show resolved Hide resolved
editor/plugins/node_3d_editor_plugin.h Outdated Show resolved Hide resolved
editor/plugins/skeleton_3d_editor_plugin.cpp Show resolved Hide resolved
@TokageItLab TokageItLab force-pushed the implement-skeleton-editor-gizmo branch 2 times, most recently from 11b2420 to 9451a68 Compare October 6, 2021 12:23
@TokageItLab
Copy link
Member Author

TokageItLab commented Oct 6, 2021

@JFonS Thank you for your reviewing and I fixed the part you reviewed.

Also, as for the crashing bug, it seems that the problem was caused by the editor generation during scene transition. That method seemed unnecessary, so I've solved it by removing it.

I'll squash it if it seems to be OK to you.

Copy link
Contributor

@JFonS JFonS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed and all my concerns were addressed.

Thanks for your great work and for putting up with my delayed reviews :)

@JFonS
Copy link
Contributor

JFonS commented Oct 6, 2021

Once the commits are squashed and CI passes it should be good to merge.

Co-authored-by: Lyuma <xn.lyuma@gmail.com>
@TokageItLab TokageItLab force-pushed the implement-skeleton-editor-gizmo branch from 2dc7955 to f2e9867 Compare October 6, 2021 16:08
@akien-mga akien-mga merged commit 164dc11 into godotengine:master Oct 6, 2021
@akien-mga
Copy link
Member

Thanks!

@Shadowblitz16
Copy link

Shadowblitz16 commented Sep 15, 2023

Why does this use embeded bone data instead of BoneAttachment3D?
And why can't we convert our meshes as relative children to the BoneAttachment3D's?

@TokageItLab
Copy link
Member Author

TokageItLab commented Sep 15, 2023

I do not understand what you are asking. FYI, as to why all bones should not be the children of the scene as an actual Node. It is written in godotengine/godot-proposals#1767 because it is mainly from a performance point of view.

If you want to generate BoneAttachment from multiple bones, I remember it is possible to add it when setting up PhysicalBone, but I don't think there was a way to add only BoneAttachment. You can open a proposal for that.

If you want to convert a gizmo to a MeshInstance, that doesn't make sense. Most 3D applications don't have that capability and Godot is the same. That doesn't have to be included in the core as a general feature. I know that Blender has such a thing as an 3rd party addon for that, so I suggest you look for an addon or make your own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants