You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-15 13:51:40 +00:00
Implemented SkeletonEditorGizmo
Co-authored-by: Lyuma <xn.lyuma@gmail.com>
This commit is contained in:
@@ -2070,169 +2070,6 @@ void Position3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
||||
p_gizmo->add_collision_segments(cursor_points);
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
Skeleton3DGizmoPlugin::Skeleton3DGizmoPlugin() {
|
||||
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/skeleton", Color(1, 0.8, 0.4));
|
||||
create_material("skeleton_material", gizmo_color);
|
||||
}
|
||||
|
||||
bool Skeleton3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
|
||||
return Object::cast_to<Skeleton3D>(p_spatial) != nullptr;
|
||||
}
|
||||
|
||||
String Skeleton3DGizmoPlugin::get_gizmo_name() const {
|
||||
return "Skeleton3D";
|
||||
}
|
||||
|
||||
int Skeleton3DGizmoPlugin::get_priority() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
||||
Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_gizmo->get_spatial_node());
|
||||
|
||||
p_gizmo->clear();
|
||||
|
||||
Ref<Material> material = get_material("skeleton_material", p_gizmo);
|
||||
|
||||
Ref<SurfaceTool> surface_tool(memnew(SurfaceTool));
|
||||
|
||||
surface_tool->begin(Mesh::PRIMITIVE_LINES);
|
||||
surface_tool->set_material(material);
|
||||
LocalVector<Transform3D> grests;
|
||||
grests.resize(skel->get_bone_count());
|
||||
|
||||
LocalVector<int> bones;
|
||||
LocalVector<float> weights;
|
||||
bones.resize(4);
|
||||
weights.resize(4);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
bones[i] = 0;
|
||||
weights[i] = 0;
|
||||
}
|
||||
|
||||
weights[0] = 1;
|
||||
|
||||
AABB aabb;
|
||||
|
||||
Color bonecolor = Color(1.0, 0.4, 0.4, 0.3);
|
||||
Color rootcolor = Color(0.4, 1.0, 0.4, 0.1);
|
||||
|
||||
LocalVector<int> bones_to_process;
|
||||
bones_to_process = skel->get_parentless_bones();
|
||||
|
||||
while (bones_to_process.size() > 0) {
|
||||
int current_bone_idx = bones_to_process[0];
|
||||
bones_to_process.erase(current_bone_idx);
|
||||
|
||||
LocalVector<int> child_bones_vector;
|
||||
child_bones_vector = skel->get_bone_children(current_bone_idx);
|
||||
int child_bones_size = child_bones_vector.size();
|
||||
|
||||
if (skel->get_bone_parent(current_bone_idx) < 0) {
|
||||
grests[current_bone_idx] = skel->get_bone_rest(current_bone_idx);
|
||||
}
|
||||
|
||||
for (int i = 0; i < child_bones_size; i++) {
|
||||
int child_bone_idx = child_bones_vector[i];
|
||||
|
||||
grests[child_bone_idx] = grests[current_bone_idx] * skel->get_bone_rest(child_bone_idx);
|
||||
Vector3 v0 = grests[current_bone_idx].origin;
|
||||
Vector3 v1 = grests[child_bone_idx].origin;
|
||||
Vector3 d = (v1 - v0).normalized();
|
||||
real_t dist = v0.distance_to(v1);
|
||||
|
||||
// Find closest axis.
|
||||
int closest = -1;
|
||||
real_t closest_d = 0.0;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
real_t dp = Math::abs(grests[current_bone_idx].basis[j].normalized().dot(d));
|
||||
if (j == 0 || dp > closest_d) {
|
||||
closest = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Find closest other.
|
||||
Vector3 first;
|
||||
Vector3 points[4];
|
||||
int point_idx = 0;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
bones[0] = current_bone_idx;
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
surface_tool->set_color(rootcolor);
|
||||
surface_tool->add_vertex(v0 - grests[current_bone_idx].basis[j].normalized() * dist * 0.05);
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
surface_tool->set_color(rootcolor);
|
||||
surface_tool->add_vertex(v0 + grests[current_bone_idx].basis[j].normalized() * dist * 0.05);
|
||||
|
||||
if (j == closest) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector3 axis;
|
||||
if (first == Vector3()) {
|
||||
axis = d.cross(d.cross(grests[current_bone_idx].basis[j])).normalized();
|
||||
first = axis;
|
||||
} else {
|
||||
axis = d.cross(first).normalized();
|
||||
}
|
||||
|
||||
for (int k = 0; k < 2; k++) {
|
||||
if (k == 1) {
|
||||
axis = -axis;
|
||||
}
|
||||
Vector3 point = v0 + d * dist * 0.2;
|
||||
point += axis * dist * 0.1;
|
||||
|
||||
bones[0] = current_bone_idx;
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
surface_tool->set_color(bonecolor);
|
||||
surface_tool->add_vertex(v0);
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
surface_tool->set_color(bonecolor);
|
||||
surface_tool->add_vertex(point);
|
||||
|
||||
bones[0] = current_bone_idx;
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
surface_tool->set_color(bonecolor);
|
||||
surface_tool->add_vertex(point);
|
||||
bones[0] = child_bone_idx;
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
surface_tool->set_color(bonecolor);
|
||||
surface_tool->add_vertex(v1);
|
||||
points[point_idx++] = point;
|
||||
}
|
||||
}
|
||||
SWAP(points[1], points[2]);
|
||||
for (int j = 0; j < 4; j++) {
|
||||
bones[0] = current_bone_idx;
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
surface_tool->set_color(bonecolor);
|
||||
surface_tool->add_vertex(points[j]);
|
||||
surface_tool->set_bones(bones);
|
||||
surface_tool->set_weights(weights);
|
||||
surface_tool->set_color(bonecolor);
|
||||
surface_tool->add_vertex(points[(j + 1) % 4]);
|
||||
}
|
||||
|
||||
// Add the bone's children to the list of bones to be processed.
|
||||
bones_to_process.push_back(child_bones_vector[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> m = surface_tool->commit();
|
||||
p_gizmo->add_mesh(m, Ref<Material>(), Transform3D(), skel->register_skin(Ref<Skin>()));
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
PhysicalBone3DGizmoPlugin::PhysicalBone3DGizmoPlugin() {
|
||||
|
||||
Reference in New Issue
Block a user