mirror of
https://github.com/godotengine/godot.git
synced 2026-02-08 03:38:29 +00:00
Fix IKModifier/ JointLimitation gizmo on root bone and dirty handling
This commit is contained in:
@@ -98,12 +98,15 @@ void ChainIK3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> mesh = get_joints_mesh(skeleton, ik, p_gizmo->is_selected());
|
||||
Ref<ArrayMesh> skeleton_mesh;
|
||||
Ref<ArrayMesh> mesh;
|
||||
get_joints_mesh(skeleton, ik, p_gizmo->is_selected(), skeleton_mesh, mesh);
|
||||
Transform3D skel_tr = ik->get_global_transform().inverse() * skeleton->get_global_transform();
|
||||
p_gizmo->add_mesh(mesh, Ref<Material>(), skel_tr, skeleton->register_skin(skeleton->create_skin_from_rest_transforms()));
|
||||
p_gizmo->add_mesh(skeleton_mesh, Ref<Material>(), skel_tr, skeleton->register_skin(skeleton->create_skin_from_rest_transforms()));
|
||||
p_gizmo->add_mesh(mesh, Ref<Material>(), skel_tr);
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> ChainIK3DGizmoPlugin::get_joints_mesh(Skeleton3D *p_skeleton, ChainIK3D *p_ik, bool p_is_selected) {
|
||||
void ChainIK3DGizmoPlugin::get_joints_mesh(Skeleton3D *p_skeleton, ChainIK3D *p_ik, bool p_is_selected, Ref<ArrayMesh> &r_skinned_mesh, Ref<ArrayMesh> &r_mesh) {
|
||||
Color bone_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/ik_chain");
|
||||
static const Color limitation_x_axis_color = Color(1, 0, 0, 1);
|
||||
static const Color limitation_z_axis_color = Color(0, 0, 1, 1);
|
||||
@@ -114,11 +117,17 @@ Ref<ArrayMesh> ChainIK3DGizmoPlugin::get_joints_mesh(Skeleton3D *p_skeleton, Cha
|
||||
surface_tool.instantiate();
|
||||
surface_tool->begin(Mesh::PRIMITIVE_LINES);
|
||||
|
||||
Ref<SurfaceTool> surface_tool_without_skin;
|
||||
surface_tool_without_skin.instantiate();
|
||||
surface_tool_without_skin->begin(Mesh::PRIMITIVE_LINES);
|
||||
|
||||
if (p_is_selected) {
|
||||
surface_tool->set_material(selection_materials.selected_mat);
|
||||
surface_tool_without_skin->set_material(selection_materials.selected_mat);
|
||||
} else {
|
||||
selection_materials.unselected_mat->set_albedo(bone_color);
|
||||
surface_tool->set_material(selection_materials.unselected_mat);
|
||||
surface_tool_without_skin->set_material(selection_materials.unselected_mat);
|
||||
}
|
||||
|
||||
PackedInt32Array bones;
|
||||
@@ -164,25 +173,24 @@ Ref<ArrayMesh> ChainIK3DGizmoPlugin::get_joints_mesh(Skeleton3D *p_skeleton, Cha
|
||||
|
||||
// Draw parent limitation shape.
|
||||
Ref<JointLimitation3D> lim = it_ik->get_joint_limitation(i, prev_joint);
|
||||
if (lim.is_valid()) {
|
||||
if (lim.is_valid() && prev_bone >= 0) {
|
||||
// Limitation space should bind parent bone rest.
|
||||
if (prev_bone >= 0) {
|
||||
int parent = p_skeleton->get_bone_parent(prev_bone);
|
||||
if (parent >= 0) {
|
||||
bones.write[0] = parent;
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
}
|
||||
int parent = p_skeleton->get_bone_parent(prev_bone);
|
||||
Ref<SurfaceTool> limitation_surface_tool = parent >= 0 ? surface_tool : surface_tool_without_skin;
|
||||
if (parent >= 0) {
|
||||
bones.write[0] = parent;
|
||||
limitation_surface_tool->set_bones(bones);
|
||||
limitation_surface_tool->set_weights(weights);
|
||||
}
|
||||
Transform3D tr = anc_global_pose;
|
||||
tr.basis *= it_ik->get_joint_limitation_space(i, prev_joint, bone_vector.normalized());
|
||||
float sl = MIN(current_length, prev_length);
|
||||
lim->draw_shape(surface_tool, tr, sl, bone_color);
|
||||
lim->draw_shape(limitation_surface_tool, tr, sl, bone_color);
|
||||
sl *= 0.1;
|
||||
Vector3 x_axis = tr.basis.get_column(Vector3::AXIS_X).normalized() * sl;
|
||||
Vector3 z_axis = tr.basis.get_column(Vector3::AXIS_Z).normalized() * sl;
|
||||
draw_line(surface_tool, tr.origin + x_axis * 2, tr.origin + x_axis * 3, limitation_x_axis_color); // Offset 20%.
|
||||
draw_line(surface_tool, tr.origin + z_axis * 2, tr.origin + z_axis * 3, limitation_z_axis_color); // Offset 20%.
|
||||
draw_line(limitation_surface_tool, tr.origin + x_axis * 2, tr.origin + x_axis * 3, limitation_x_axis_color); // Offset 20%.
|
||||
draw_line(limitation_surface_tool, tr.origin + z_axis * 2, tr.origin + z_axis * 3, limitation_z_axis_color); // Offset 20%.
|
||||
}
|
||||
}
|
||||
prev_length = current_length;
|
||||
@@ -207,25 +215,24 @@ Ref<ArrayMesh> ChainIK3DGizmoPlugin::get_joints_mesh(Skeleton3D *p_skeleton, Cha
|
||||
if (it_ik) {
|
||||
// Draw limitation shape.
|
||||
Ref<JointLimitation3D> lim = it_ik->get_joint_limitation(i, j);
|
||||
if (lim.is_valid()) {
|
||||
if (lim.is_valid() && current_bone >= 0) {
|
||||
// Limitation space should bind parent bone rest.
|
||||
if (current_bone >= 0) {
|
||||
int parent = p_skeleton->get_bone_parent(current_bone);
|
||||
if (parent >= 0) {
|
||||
bones.write[0] = parent;
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
}
|
||||
int parent = p_skeleton->get_bone_parent(current_bone);
|
||||
Ref<SurfaceTool> limitation_surface_tool = parent >= 0 ? surface_tool : surface_tool_without_skin;
|
||||
if (parent >= 0) {
|
||||
bones.write[0] = parent;
|
||||
limitation_surface_tool->set_bones(bones);
|
||||
limitation_surface_tool->set_weights(weights);
|
||||
}
|
||||
Transform3D tr = anc_global_pose;
|
||||
tr.basis *= it_ik->get_joint_limitation_space(i, j, bone_vector.normalized());
|
||||
float sl = MIN(current_length, prev_length);
|
||||
lim->draw_shape(surface_tool, tr, sl, bone_color);
|
||||
lim->draw_shape(limitation_surface_tool, tr, sl, bone_color);
|
||||
sl *= 0.1;
|
||||
Vector3 x_axis = tr.basis.get_column(Vector3::AXIS_X).normalized() * sl;
|
||||
Vector3 z_axis = tr.basis.get_column(Vector3::AXIS_Z).normalized() * sl;
|
||||
draw_line(surface_tool, tr.origin + x_axis * 2, tr.origin + x_axis * 3, limitation_x_axis_color); // Offset 20%.
|
||||
draw_line(surface_tool, tr.origin + z_axis * 2, tr.origin + z_axis * 3, limitation_z_axis_color); // Offset 20%.
|
||||
draw_line(limitation_surface_tool, tr.origin + x_axis * 2, tr.origin + x_axis * 3, limitation_x_axis_color); // Offset 20%.
|
||||
draw_line(limitation_surface_tool, tr.origin + z_axis * 2, tr.origin + z_axis * 3, limitation_z_axis_color); // Offset 20%.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -257,7 +264,8 @@ Ref<ArrayMesh> ChainIK3DGizmoPlugin::get_joints_mesh(Skeleton3D *p_skeleton, Cha
|
||||
}
|
||||
}
|
||||
|
||||
return surface_tool->commit();
|
||||
r_skinned_mesh = surface_tool->commit();
|
||||
r_mesh = surface_tool_without_skin->commit();
|
||||
}
|
||||
|
||||
void ChainIK3DGizmoPlugin::draw_line(Ref<SurfaceTool> &p_surface_tool, const Vector3 &p_begin_pos, const Vector3 &p_end_pos, const Color &p_color) {
|
||||
|
||||
@@ -46,7 +46,7 @@ class ChainIK3DGizmoPlugin : public EditorNode3DGizmoPlugin {
|
||||
static SelectionMaterials selection_materials;
|
||||
|
||||
public:
|
||||
static Ref<ArrayMesh> get_joints_mesh(Skeleton3D *p_skeleton, ChainIK3D *p_ik, bool p_is_selected);
|
||||
static void get_joints_mesh(Skeleton3D *p_skeleton, ChainIK3D *p_ik, bool p_is_selected, Ref<ArrayMesh> &r_skinned_mesh, Ref<ArrayMesh> &r_mesh);
|
||||
static void draw_line(Ref<SurfaceTool> &p_surface_tool, const Vector3 &p_begin_pos, const Vector3 &p_end_pos, const Color &p_color);
|
||||
|
||||
bool has_gizmo(Node3D *p_spatial) override;
|
||||
|
||||
@@ -71,11 +71,11 @@ void IKModifier3D::_set_active(bool p_active) {
|
||||
}
|
||||
|
||||
void IKModifier3D::_skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) {
|
||||
if (p_old && p_old->is_connected(SNAME("rest_updated"), callable_mp(this, &IKModifier3D::_make_all_joints_dirty))) {
|
||||
p_old->disconnect(SNAME("rest_updated"), callable_mp(this, &IKModifier3D::_make_all_joints_dirty));
|
||||
if (p_old && p_old->is_connected(SNAME("rest_updated"), callable_mp(this, &IKModifier3D::_rest_updated))) {
|
||||
p_old->disconnect(SNAME("rest_updated"), callable_mp(this, &IKModifier3D::_rest_updated));
|
||||
}
|
||||
if (p_new && !p_new->is_connected(SNAME("rest_updated"), callable_mp(this, &IKModifier3D::_make_all_joints_dirty))) {
|
||||
p_new->connect(SNAME("rest_updated"), callable_mp(this, &IKModifier3D::_make_all_joints_dirty));
|
||||
if (p_new && !p_new->is_connected(SNAME("rest_updated"), callable_mp(this, &IKModifier3D::_rest_updated))) {
|
||||
p_new->connect(SNAME("rest_updated"), callable_mp(this, &IKModifier3D::_rest_updated));
|
||||
}
|
||||
_make_all_joints_dirty();
|
||||
}
|
||||
@@ -84,6 +84,22 @@ void IKModifier3D::_validate_bone_names() {
|
||||
//
|
||||
}
|
||||
|
||||
void IKModifier3D::_rest_updated() {
|
||||
_make_all_joints_dirty();
|
||||
if (is_inside_tree()) {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (skeleton) {
|
||||
for (uint32_t i = 0; i < settings.size(); i++) {
|
||||
_init_joints(skeleton, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef TOOLS_ENABLED
|
||||
_update_mutable_info();
|
||||
_make_gizmo_dirty();
|
||||
#endif // TOOLS_ENABLED
|
||||
}
|
||||
|
||||
void IKModifier3D::_make_all_joints_dirty() {
|
||||
//
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ protected:
|
||||
|
||||
virtual void _validate_bone_names() override;
|
||||
|
||||
void _rest_updated();
|
||||
virtual void _make_all_joints_dirty();
|
||||
virtual void _init_joints(Skeleton3D *p_skeleton, int p_index);
|
||||
virtual void _update_joints(int p_index);
|
||||
|
||||
Reference in New Issue
Block a user