Fix Skeleton3D edit mode usability issues

This commit is contained in:
mxtherfxcker
2026-01-08 20:07:21 +03:00
parent 76dda5c6c5
commit 14a7c0f1e5
2 changed files with 68 additions and 39 deletions

View File

@@ -1518,15 +1518,32 @@ EditorPlugin::AfterGUIInput Skeleton3DEditorPlugin::forward_3d_gui_input(Camera3
Node3DEditor *ne = Node3DEditor::get_singleton();
if (se && se->is_edit_mode()) {
const Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) {
Skeleton3D *skeleton = se->get_skeleton();
if (skeleton) {
int closest_idx = Skeleton3DGizmoPlugin::skeleton_intersect_ray(skeleton, p_camera, mb->get_position());
if (closest_idx >= 0) {
se->select_bone(closest_idx);
se->update_bone_original();
Vector<Ref<Node3DGizmo>> gizmos = skeleton->get_gizmos();
for (Ref<EditorNode3DGizmo> seg : gizmos) {
if (seg.is_valid()) {
Transform3D bone_xform = seg->get_subgizmo_transform(closest_idx);
ne->call("_set_subgizmo_selection", skeleton, seg, closest_idx, bone_xform);
break;
}
}
return EditorPlugin::AFTER_GUI_INPUT_STOP;
}
}
}
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
if (ne->get_tool_mode() != Node3DEditor::TOOL_MODE_SELECT) {
if (!ne->is_gizmo_visible()) {
return EditorPlugin::AFTER_GUI_INPUT_STOP;
}
}
if (mb->is_pressed()) {
se->update_bone_original();
}
}
return EditorPlugin::AFTER_GUI_INPUT_CUSTOM;
}
@@ -1629,19 +1646,27 @@ int Skeleton3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gi
return -1;
}
if (Node3DEditor::get_singleton()->get_tool_mode() != Node3DEditor::TOOL_MODE_SELECT) {
return -1;
int closest_idx = skeleton_intersect_ray(skeleton, p_camera, p_point);
if (closest_idx >= 0) {
se->select_bone(closest_idx);
se->update_bone_original();
return closest_idx;
}
// Select bone.
real_t grab_threshold = 4 * EDSCALE;
se->select_bone(-1);
return -1;
}
int Skeleton3DGizmoPlugin::skeleton_intersect_ray(const Skeleton3D *p_skeleton, Camera3D *p_camera, const Vector2 &p_point) {
real_t grab_threshold = 8 * EDSCALE;
Vector3 ray_from = p_camera->get_global_transform().origin;
Transform3D gt = skeleton->get_global_transform();
Transform3D gt = p_skeleton->get_global_transform();
int closest_idx = -1;
real_t closest_dist = 1e10;
const int bone_count = skeleton->get_bone_count();
const int bone_count = p_skeleton->get_bone_count();
for (int i = 0; i < bone_count; i++) {
Vector3 joint_pos_3d = gt.xform(skeleton->get_bone_global_pose(i).origin);
Vector3 joint_pos_3d = gt.xform(p_skeleton->get_bone_global_pose(i).origin);
Vector2 joint_pos_2d = p_camera->unproject_position(joint_pos_3d);
real_t dist_3d = ray_from.distance_to(joint_pos_3d);
real_t dist_2d = p_point.distance_to(joint_pos_2d);
@@ -1650,14 +1675,7 @@ int Skeleton3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gi
closest_idx = i;
}
}
if (closest_idx >= 0) {
se->select_bone(closest_idx);
return closest_idx;
}
se->select_bone(-1);
return -1;
return closest_idx;
}
Transform3D Skeleton3DGizmoPlugin::get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const {
@@ -1705,25 +1723,35 @@ void Skeleton3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, c
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Set Bone Transform"));
if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || ne->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
for (int i = 0; i < p_ids.size(); i++) {
ur->add_do_method(skeleton, "set_bone_pose_position", p_ids[i], skeleton->get_bone_pose_position(p_ids[i]));
ur->add_undo_method(skeleton, "set_bone_pose_position", p_ids[i], se->get_bone_original_position());
if (p_cancel) {
for (int id : p_ids) {
ur->add_do_method(skeleton, "set_bone_pose_position", id, se->get_bone_original_position());
ur->add_do_method(skeleton, "set_bone_pose_rotation", id, se->get_bone_original_rotation());
ur->add_do_method(skeleton, "set_bone_pose_scale", id, se->get_bone_original_scale());
ur->add_undo_method(skeleton, "set_bone_pose_position", id, skeleton->get_bone_pose_position(id));
ur->add_undo_method(skeleton, "set_bone_pose_rotation", id, skeleton->get_bone_pose_rotation(id));
ur->add_undo_method(skeleton, "set_bone_pose_scale", id, skeleton->get_bone_pose_scale(id));
}
}
if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || ne->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
for (int i = 0; i < p_ids.size(); i++) {
ur->add_do_method(skeleton, "set_bone_pose_rotation", p_ids[i], skeleton->get_bone_pose_rotation(p_ids[i]));
ur->add_undo_method(skeleton, "set_bone_pose_rotation", p_ids[i], se->get_bone_original_rotation());
} else {
Node3DEditor::ToolMode tool_mode = ne->get_tool_mode();
if (tool_mode == Node3DEditor::TOOL_MODE_SELECT || tool_mode == Node3DEditor::TOOL_MODE_MOVE || tool_mode == Node3DEditor::TOOL_MODE_TRANSFORM) {
for (int id : p_ids) {
ur->add_do_method(skeleton, "set_bone_pose_position", id, skeleton->get_bone_pose_position(id));
ur->add_undo_method(skeleton, "set_bone_pose_position", id, se->get_bone_original_position());
}
}
}
if (ne->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) {
for (int i = 0; i < p_ids.size(); i++) {
// If the axis is swapped by scaling, the rotation can be changed.
ur->add_do_method(skeleton, "set_bone_pose_rotation", p_ids[i], skeleton->get_bone_pose_rotation(p_ids[i]));
ur->add_undo_method(skeleton, "set_bone_pose_rotation", p_ids[i], se->get_bone_original_rotation());
ur->add_do_method(skeleton, "set_bone_pose_scale", p_ids[i], skeleton->get_bone_pose_scale(p_ids[i]));
ur->add_undo_method(skeleton, "set_bone_pose_scale", p_ids[i], se->get_bone_original_scale());
if (tool_mode == Node3DEditor::TOOL_MODE_SELECT || tool_mode == Node3DEditor::TOOL_MODE_ROTATE || tool_mode == Node3DEditor::TOOL_MODE_TRANSFORM) {
for (int id : p_ids) {
ur->add_do_method(skeleton, "set_bone_pose_rotation", id, skeleton->get_bone_pose_rotation(id));
ur->add_undo_method(skeleton, "set_bone_pose_rotation", id, se->get_bone_original_rotation());
}
}
if (tool_mode == Node3DEditor::TOOL_MODE_SCALE || tool_mode == Node3DEditor::TOOL_MODE_TRANSFORM) {
for (int id : p_ids) {
ur->add_do_method(skeleton, "set_bone_pose_scale", id, skeleton->get_bone_pose_scale(id));
ur->add_undo_method(skeleton, "set_bone_pose_scale", id, se->get_bone_original_scale());
}
}
}

View File

@@ -292,15 +292,16 @@ class Skeleton3DGizmoPlugin : public EditorNode3DGizmoPlugin {
public:
static Ref<ArrayMesh> get_bones_mesh(Skeleton3D *p_skeleton, int p_selected, bool p_is_selected);
static int skeleton_intersect_ray(const Skeleton3D *p_skeleton, Camera3D *p_camera, const Vector2 &p_point);
bool has_gizmo(Node3D *p_spatial) override;
String get_gizmo_name() const override;
int get_priority() const override;
int subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const override;
Transform3D get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
void set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) override;
void commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) override;
virtual int subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const override;
virtual Transform3D get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
virtual void set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) override;
virtual void commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) override;
void redraw(EditorNode3DGizmo *p_gizmo) override;