diff options
author | Silc Renew <tokage.it.lab@gmail.com> | 2021-02-04 17:20:26 +0900 |
---|---|---|
committer | Silc Renew <tokage.it.lab@gmail.com> | 2021-10-07 01:07:46 +0900 |
commit | f2e9867e9f6dc58ab3a016c7b2a90bc9c3b5f1b6 (patch) | |
tree | 7d0e5165f8c8b9efd98d0fc0c7f0ede66b9d6ddd /scene | |
parent | ce0268a0c1d2a73dd9d59ed339a76bec6a429edd (diff) |
Implemented SkeletonEditorGizmo
Co-authored-by: Lyuma <xn.lyuma@gmail.com>
Diffstat (limited to 'scene')
-rw-r--r-- | scene/3d/node_3d.cpp | 13 | ||||
-rw-r--r-- | scene/3d/node_3d.h | 4 | ||||
-rw-r--r-- | scene/3d/skeleton_3d.cpp | 75 | ||||
-rw-r--r-- | scene/3d/skeleton_3d.h | 6 | ||||
-rw-r--r-- | scene/scene_string_names.cpp | 3 | ||||
-rw-r--r-- | scene/scene_string_names.h | 3 |
6 files changed, 81 insertions, 23 deletions
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 12470939f5..272a06bce4 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -376,6 +376,18 @@ void Node3D::update_gizmos() { #endif } +void Node3D::set_subgizmo_selection(Ref<Node3DGizmo> p_gizmo, int p_id, Transform3D p_transform) { +#ifdef TOOLS_ENABLED + if (!is_inside_world()) { + return; + } + + if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) { + get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_set_subgizmo_selection, this, p_gizmo, p_id, p_transform); + } +#endif +} + void Node3D::clear_subgizmo_selection() { #ifdef TOOLS_ENABLED if (!is_inside_world()) { @@ -792,6 +804,7 @@ void Node3D::_bind_methods() { ClassDB::bind_method(D_METHOD("add_gizmo", "gizmo"), &Node3D::add_gizmo); ClassDB::bind_method(D_METHOD("get_gizmos"), &Node3D::get_gizmos_bind); ClassDB::bind_method(D_METHOD("clear_gizmos"), &Node3D::clear_gizmos); + ClassDB::bind_method(D_METHOD("set_subgizmo_selection", "gizmo", "id", "transform"), &Node3D::set_subgizmo_selection); ClassDB::bind_method(D_METHOD("clear_subgizmo_selection"), &Node3D::clear_subgizmo_selection); ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Node3D::set_visible); diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index 0fd0c4e205..d6dcdd96fe 100644 --- a/scene/3d/node_3d.h +++ b/scene/3d/node_3d.h @@ -92,6 +92,7 @@ class Node3D : public Node { Vector<Ref<Node3DGizmo>> gizmos; bool gizmos_disabled = false; bool gizmos_dirty = false; + bool transform_gizmo_visible = true; #endif } data; @@ -145,6 +146,8 @@ public: #ifdef TOOLS_ENABLED virtual Transform3D get_global_gizmo_transform() const; virtual Transform3D get_local_gizmo_transform() const; + virtual void set_transform_gizmo_visible(bool p_enabled) { data.transform_gizmo_visible = p_enabled; }; + virtual bool is_transform_gizmo_visible() const { return data.transform_gizmo_visible; }; #endif void set_as_top_level(bool p_enabled); @@ -155,6 +158,7 @@ public: void set_disable_gizmos(bool p_enabled); void update_gizmos(); + void set_subgizmo_selection(Ref<Node3DGizmo> p_gizmo, int p_id, Transform3D p_transform = Transform3D()); void clear_subgizmo_selection(); Vector<Ref<Node3DGizmo>> get_gizmos() const; Array get_gizmos_bind() const; diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index b7a79a2645..0a19e1d07b 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -32,6 +32,7 @@ #include "core/object/message_queue.h" #include "core/variant/type_info.h" +#include "editor/plugins/skeleton_3d_editor_plugin.h" #include "scene/3d/physics_body_3d.h" #include "scene/resources/skeleton_modification_3d.h" #include "scene/resources/surface_tool.h" @@ -178,7 +179,7 @@ void Skeleton3D::_update_process_order() { for (int i = 0; i < len; i++) { if (bonesptr[i].parent >= len) { - //validate this just in case + // Validate this just in case. ERR_PRINT("Bone " + itos(i) + " has invalid parent: " + itos(bonesptr[i].parent)); bonesptr[i].parent = -1; } @@ -186,9 +187,9 @@ void Skeleton3D::_update_process_order() { if (bonesptr[i].parent != -1) { int parent_bone_idx = bonesptr[i].parent; - // Check to see if this node is already added to the parent: + // Check to see if this node is already added to the parent. if (bonesptr[parent_bone_idx].child_bones.find(i) < 0) { - // Add the child node + // Add the child node. bonesptr[parent_bone_idx].child_bones.push_back(i); } else { ERR_PRINT("Skeleton3D parenthood graph is cyclic"); @@ -210,10 +211,10 @@ void Skeleton3D::_notification(int p_what) { int len = bones.size(); dirty = false; - // Update bone transforms + // Update bone transforms. force_update_all_bone_transforms(); - //update skins + // Update skins. for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { const Skin *skin = E->get()->skin.operator->(); RID skeleton = E->get()->skeleton; @@ -231,7 +232,7 @@ void Skeleton3D::_notification(int p_what) { StringName bind_name = skin->get_bind_name(i); if (bind_name != StringName()) { - //bind name used, use this + // Bind name used, use this. bool found = false; for (int j = 0; j < len; j++) { if (bonesptr[j].name == bind_name) { @@ -453,7 +454,8 @@ int Skeleton3D::get_bone_axis_forward_enum(int p_bone) { return bones[p_bone].rest_bone_forward_axis; } -// skeleton creation api +// Skeleton creation api + void Skeleton3D::add_bone(const String &p_name) { ERR_FAIL_COND(p_name == "" || p_name.find(":") != -1 || p_name.find("/") != -1); @@ -626,6 +628,7 @@ void Skeleton3D::set_bone_enabled(int p_bone, bool p_enabled) { ERR_FAIL_INDEX(p_bone, bone_size); bones.write[p_bone].enabled = p_enabled; + emit_signal(SceneStringNames::get_singleton()->bone_enabled_changed, p_bone); _make_dirty(); } @@ -635,6 +638,16 @@ bool Skeleton3D::is_bone_enabled(int p_bone) const { return bones[p_bone].enabled; } +void Skeleton3D::set_show_rest_only(bool p_enabled) { + show_rest_only = p_enabled; + emit_signal(SceneStringNames::get_singleton()->show_rest_only_changed); + _make_dirty(); +} + +bool Skeleton3D::is_show_rest_only() const { + return show_rest_only; +} + void Skeleton3D::clear_bones() { bones.clear(); process_order_dirty = true; @@ -642,7 +655,7 @@ void Skeleton3D::clear_bones() { _make_dirty(); } -// posing api +// Posing api void Skeleton3D::set_bone_pose(int p_bone, const Transform3D &p_pose) { const int bone_size = bones.size(); @@ -697,7 +710,7 @@ void Skeleton3D::localize_rests() { set_bone_rest(current_bone_idx, bones[bones[current_bone_idx].parent].rest.affine_inverse() * bones[current_bone_idx].rest); } - // Add the bone's children to the list of bones to be processed + // Add the bone's children to the list of bones to be processed. int child_bone_size = bones[current_bone_idx].child_bones.size(); for (int i = 0; i < child_bone_size; i++) { bones_to_process.push_back(bones[current_bone_idx].child_bones[i]); @@ -831,7 +844,7 @@ void Skeleton3D::physical_bones_start_simulation_on(const TypedArray<StringName> Vector<int> sim_bones; if (p_bones.size() <= 0) { - sim_bones.push_back(0); // if no bones is specified, activate ragdoll on full body + sim_bones.push_back(0); // If no bones is specified, activate ragdoll on full body. } else { sim_bones.resize(p_bones.size()); int c = 0; @@ -884,19 +897,19 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { Ref<Skin> skin = p_skin; if (skin.is_null()) { - //need to create one from existing code, this is for compatibility only - //when skeletons did not support skins. It is also used by gizmo - //to display the skeleton. + // Need to create one from existing code, this is for compatibility only + // when skeletons did not support skins. It is also used by gizmo + // to display the skeleton. skin.instantiate(); skin->set_bind_count(bones.size()); - _update_process_order(); //just in case + _update_process_order(); // Just in case. - // pose changed, rebuild cache of inverses + // Pose changed, rebuild cache of inverses. const Bone *bonesptr = bones.ptr(); int len = bones.size(); - // calculate global rests and invert them + // Calculate global rests and invert them. LocalVector<int> bones_to_process; bones_to_process = get_parentless_bones(); while (bones_to_process.size() > 0) { @@ -919,7 +932,7 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { } for (int i = 0; i < len; i++) { - //the inverse is what is actually required + // The inverse is what is actually required. skin->set_bind_bone(i, i); skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse()); } @@ -940,11 +953,17 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { skin->connect("changed", Callable(skin_ref.operator->(), "_skin_changed")); - _make_dirty(); //skin needs to be updated, so update skeleton + _make_dirty(); // Skin needs to be updated, so update skeleton. return skin_ref; } +void Skeleton3D::force_update_all_dirty_bones() { + if (dirty) { + const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); + } +} + void Skeleton3D::force_update_all_bone_transforms() { _update_process_order(); @@ -966,9 +985,10 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { bones_to_process.erase(current_bone_idx); Bone &b = bonesptr[current_bone_idx]; + bool bone_enabled = b.enabled && !show_rest_only; if (b.disable_rest) { - if (b.enabled) { + if (bone_enabled) { Transform3D pose = b.pose; if (b.custom_pose_enable) { pose = b.custom_pose * pose; @@ -991,7 +1011,7 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { } } else { - if (b.enabled) { + if (bone_enabled) { Transform3D pose = b.pose; if (b.custom_pose_enable) { pose = b.custom_pose * pose; @@ -1035,7 +1055,7 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { b.global_pose_override_amount = 0.0; } - // Add the bone's children to the list of bones to be processed + // Add the bone's children to the list of bones to be processed. int child_bone_size = b.child_bones.size(); for (int i = 0; i < child_bone_size; i++) { bones_to_process.push_back(b.child_bones[i]); @@ -1045,7 +1065,7 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { } } -// helper functions +// Helper functions Transform3D Skeleton3D::global_pose_to_world_transform(Transform3D p_global_pose) { return get_global_transform() * p_global_pose; @@ -1175,6 +1195,9 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton3D::get_bone_pose); ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton3D::set_bone_pose); + ClassDB::bind_method(D_METHOD("is_bone_enabled", "bone_idx"), &Skeleton3D::is_bone_enabled); + ClassDB::bind_method(D_METHOD("set_bone_enabled", "bone_idx", "enabled"), &Skeleton3D::set_bone_enabled, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override"), &Skeleton3D::clear_bones_global_pose_override); ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_global_pose_override, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_bone_global_pose_override", "bone_idx"), &Skeleton3D::get_bone_global_pose_override); @@ -1198,6 +1221,9 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("local_pose_to_global_pose", "bone_idx", "local_pose"), &Skeleton3D::local_pose_to_global_pose); ClassDB::bind_method(D_METHOD("global_pose_z_forward_to_bone_forward", "bone_idx", "basis"), &Skeleton3D::global_pose_z_forward_to_bone_forward); + ClassDB::bind_method(D_METHOD("set_show_rest_only"), &Skeleton3D::set_show_rest_only); + ClassDB::bind_method(D_METHOD("is_show_rest_only"), &Skeleton3D::is_show_rest_only); + ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton3D::set_animate_physical_bones); ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton3D::get_animate_physical_bones); @@ -1212,6 +1238,7 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("execute_modifications", "delta", "execution_mode"), &Skeleton3D::execute_modifications); #ifndef _3D_DISABLED + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_rest_only"), "set_show_rest_only", "is_show_rest_only"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); #endif // _3D_DISABLED @@ -1220,6 +1247,8 @@ void Skeleton3D::_bind_methods() { #endif // TOOLS_ENABLED ADD_SIGNAL(MethodInfo("bone_pose_changed", PropertyInfo(Variant::INT, "bone_idx"))); + ADD_SIGNAL(MethodInfo("bone_enabled_changed", PropertyInfo(Variant::INT, "bone_idx"))); + ADD_SIGNAL(MethodInfo("show_rest_only_changed")); BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); } @@ -1228,7 +1257,7 @@ Skeleton3D::Skeleton3D() { } Skeleton3D::~Skeleton3D() { - //some skins may remain bound + // Some skins may remain bound. for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { E->get()->skeleton_node = nullptr; } diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index c8a19db813..a50dc158f3 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -137,6 +137,8 @@ private: void _make_dirty(); bool dirty = false; + bool show_rest_only = false; + uint64_t version = 1; void _update_process_order(); @@ -197,6 +199,9 @@ public: void set_bone_enabled(int p_bone, bool p_enabled); bool is_bone_enabled(int p_bone) const; + + void set_show_rest_only(bool p_enabled); + bool is_show_rest_only() const; void clear_bones(); // posing api @@ -219,6 +224,7 @@ public: Ref<SkinReference> register_skin(const Ref<Skin> &p_skin); + void force_update_all_dirty_bones(); void force_update_all_bone_transforms(); void force_update_bone_children_transforms(int bone_idx); diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index b283749ffa..23d257d9af 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -64,6 +64,8 @@ SceneStringNames::SceneStringNames() { pose_updated = StaticCString::create("pose_updated"); bone_pose_changed = StaticCString::create("bone_pose_changed"); + bone_enabled_changed = StaticCString::create("bone_enabled_changed"); + show_rest_only_changed = StaticCString::create("show_rest_only_changed"); mouse_entered = StaticCString::create("mouse_entered"); mouse_exited = StaticCString::create("mouse_exited"); @@ -134,6 +136,7 @@ SceneStringNames::SceneStringNames() { _spatial_editor_group = StaticCString::create("_spatial_editor_group"); _request_gizmo = StaticCString::create("_request_gizmo"); + _set_subgizmo_selection = StaticCString::create("_set_subgizmo_selection"); _clear_subgizmo_selection = StaticCString::create("_clear_subgizmo_selection"); offset = StaticCString::create("offset"); diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 2923351eab..cf116aa140 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -99,6 +99,8 @@ public: StringName pose_updated; StringName bone_pose_changed; + StringName bone_enabled_changed; + StringName show_rest_only_changed; StringName body_shape_entered; StringName body_entered; @@ -154,6 +156,7 @@ public: StringName _spatial_editor_group; StringName _request_gizmo; + StringName _set_subgizmo_selection; StringName _clear_subgizmo_selection; StringName offset; |