diff options
Diffstat (limited to 'editor/plugins/node_3d_editor_plugin.cpp')
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 273 |
1 files changed, 158 insertions, 115 deletions
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 78805324c9..65563bd1a3 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1675,6 +1675,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (_edit.mode != TRANSFORM_NONE && b->is_pressed()) { cancel_transform(); + break; } if (b->is_pressed()) { @@ -2007,7 +2008,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { _edit.mode = TRANSFORM_TRANSLATE; } - if (_edit.mode == TRANSFORM_NONE) { + if (_edit.mode == TRANSFORM_NONE || _edit.numeric_input != 0 || _edit.numeric_next_decimal != 0) { return; } @@ -2145,6 +2146,43 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { return; } + if (_edit.instant) { + // In a Blender-style transform, numbers set the magnitude of the transform. + // E.g. pressing g4.5x means "translate 4.5 units along the X axis". + // Use the Unicode value because we care about the text, not the actual keycode. + // This ensures numbers work consistently across different keyboard language layouts. + bool processed = true; + Key key = k->get_physical_keycode(); + char32_t unicode = k->get_unicode(); + if (unicode >= '0' && unicode <= '9') { + uint32_t value = uint32_t(unicode - Key::KEY_0); + if (_edit.numeric_next_decimal < 0) { + _edit.numeric_input = _edit.numeric_input + value * Math::pow(10.0, _edit.numeric_next_decimal--); + } else { + _edit.numeric_input = _edit.numeric_input * 10 + value; + } + update_transform_numeric(); + } else if (unicode == '-') { + _edit.numeric_negate = !_edit.numeric_negate; + update_transform_numeric(); + } else if (unicode == '.') { + if (_edit.numeric_next_decimal == 0) { + _edit.numeric_next_decimal = -1; + } + } else if (key == Key::ENTER || key == Key::KP_ENTER || key == Key::SPACE) { + commit_transform(); + } else { + processed = false; + } + + if (processed) { + // Ignore mouse inputs once we receive a numeric input. + set_process_input(false); + accept_event(); + return; + } + } + if (EDITOR_GET("editors/3d/navigation/emulate_numpad")) { const Key code = k->get_physical_keycode(); if (code >= Key::KEY_0 && code <= Key::KEY_9) { @@ -2165,26 +2203,19 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } else { // We're actively transforming, handle keys specially TransformPlane new_plane = TRANSFORM_VIEW; - String new_message; if (ED_IS_SHORTCUT("spatial_editor/lock_transform_x", p_event)) { new_plane = TRANSFORM_X_AXIS; - new_message = TTR("X-Axis Transform."); } else if (ED_IS_SHORTCUT("spatial_editor/lock_transform_y", p_event)) { new_plane = TRANSFORM_Y_AXIS; - new_message = TTR("Y-Axis Transform."); } else if (ED_IS_SHORTCUT("spatial_editor/lock_transform_z", p_event)) { new_plane = TRANSFORM_Z_AXIS; - new_message = TTR("Z-Axis Transform."); } else if (_edit.mode != TRANSFORM_ROTATE) { // rotating on a plane doesn't make sense if (ED_IS_SHORTCUT("spatial_editor/lock_transform_yz", p_event)) { new_plane = TRANSFORM_YZ; - new_message = TTR("YZ-Plane Transform."); } else if (ED_IS_SHORTCUT("spatial_editor/lock_transform_xz", p_event)) { new_plane = TRANSFORM_XZ; - new_message = TTR("XZ-Plane Transform."); } else if (ED_IS_SHORTCUT("spatial_editor/lock_transform_xy", p_event)) { new_plane = TRANSFORM_XY; - new_message = TTR("XY-Plane Transform."); } } @@ -2201,8 +2232,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { _edit.plane = TRANSFORM_VIEW; spatial_editor->set_local_coords_enabled(false); } - update_transform(Input::get_singleton()->is_key_pressed(Key::SHIFT)); - set_message(new_message, 2); + if (_edit.numeric_input != 0 || _edit.numeric_next_decimal != 0) { + update_transform_numeric(); + } else { + update_transform(Input::get_singleton()->is_key_pressed(Key::SHIFT)); + } accept_event(); return; } @@ -2659,6 +2693,9 @@ void Node3DEditorViewport::_project_settings_changed() { const bool transparent_background = GLOBAL_GET("rendering/viewport/transparent_background"); viewport->set_transparent_background(transparent_background); + const bool use_hdr_2d = GLOBAL_GET("rendering/viewport/hdr_2d"); + viewport->set_use_hdr_2d(use_hdr_2d); + const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding"); viewport->set_use_debanding(use_debanding); @@ -2822,7 +2859,7 @@ void Node3DEditorViewport::_notification(int p_what) { } if (show_info) { - const String viewport_size = vformat(String::utf8("%d × %d"), viewport->get_size().x, viewport->get_size().y); + const String viewport_size = vformat(U"%d × %d", viewport->get_size().x, viewport->get_size().y); String text; text += vformat(TTR("X: %s\n"), rtos(current_camera->get_position().x).pad_decimals(1)); text += vformat(TTR("Y: %s\n"), rtos(current_camera->get_position().y).pad_decimals(1)); @@ -4572,6 +4609,43 @@ void Node3DEditorViewport::commit_transform() { set_message(""); } +void Node3DEditorViewport::apply_transform(Vector3 p_motion, double p_snap) { + bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); + List<Node *> &selection = editor_selection->get_selected_node_list(); + for (Node *E : selection) { + Node3D *sp = Object::cast_to<Node3D>(E); + if (!sp) { + continue; + } + + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp); + if (!se) { + continue; + } + + if (sp->has_meta("_edit_lock_")) { + continue; + } + + if (se->gizmo.is_valid()) { + for (KeyValue<int, Transform3D> &GE : se->subgizmos) { + Transform3D xform = GE.value; + Transform3D new_xform = _compute_transform(_edit.mode, se->original * xform, xform, p_motion, p_snap, local_coords, _edit.plane != TRANSFORM_VIEW); // Force orthogonal with subgizmo. + if (!local_coords) { + new_xform = se->original.affine_inverse() * new_xform; + } + se->gizmo->set_subgizmo_transform(GE.key, new_xform); + } + } else { + Transform3D new_xform = _compute_transform(_edit.mode, se->original, se->original_local, p_motion, p_snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS && _edit.plane != TRANSFORM_VIEW); + _transform_gizmo_apply(se->sp, new_xform, local_coords); + } + } + + spatial_editor->update_transform_gizmo(); + surface->queue_redraw(); +} + // Update the current transform operation in response to an input. void Node3DEditorViewport::update_transform(bool p_shift) { Vector3 ray_pos = _get_ray_pos(_edit.mouse_pos); @@ -4667,43 +4741,11 @@ void Node3DEditorViewport::update_transform(bool p_shift) { set_message(TTR("Scaling:") + " (" + String::num(motion_snapped.x, snap_step_decimals) + ", " + String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")"); if (local_coords) { + // TODO: needed? motion = _edit.original.basis.inverse().xform(motion); } - List<Node *> &selection = editor_selection->get_selected_node_list(); - for (Node *E : selection) { - Node3D *sp = Object::cast_to<Node3D>(E); - if (!sp) { - continue; - } - - Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp); - if (!se) { - continue; - } - - if (sp->has_meta("_edit_lock_")) { - continue; - } - - if (se->gizmo.is_valid()) { - for (KeyValue<int, Transform3D> &GE : se->subgizmos) { - Transform3D xform = GE.value; - Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original * xform, xform, motion, snap, local_coords, _edit.plane != TRANSFORM_VIEW); // Force orthogonal with subgizmo. - if (!local_coords) { - new_xform = se->original.affine_inverse() * new_xform; - } - se->gizmo->set_subgizmo_transform(GE.key, new_xform); - } - } else { - Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS && _edit.plane != TRANSFORM_VIEW); - _transform_gizmo_apply(se->sp, new_xform, local_coords); - } - } - - spatial_editor->update_transform_gizmo(); - surface->queue_redraw(); - + apply_transform(motion, snap); } break; case TRANSFORM_TRANSLATE: { @@ -4773,38 +4815,7 @@ void Node3DEditorViewport::update_transform(bool p_shift) { motion = spatial_editor->get_gizmo_transform().basis.inverse().xform(motion); } - List<Node *> &selection = editor_selection->get_selected_node_list(); - for (Node *E : selection) { - Node3D *sp = Object::cast_to<Node3D>(E); - if (!sp) { - continue; - } - - Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp); - if (!se) { - continue; - } - - if (sp->has_meta("_edit_lock_")) { - continue; - } - - if (se->gizmo.is_valid()) { - for (KeyValue<int, Transform3D> &GE : se->subgizmos) { - Transform3D xform = GE.value; - Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original * xform, xform, motion, snap, local_coords, true); // Force orthogonal with subgizmo. - new_xform = se->original.affine_inverse() * new_xform; - se->gizmo->set_subgizmo_transform(GE.key, new_xform); - } - } else { - Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original, se->original_local, motion, snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS); - _transform_gizmo_apply(se->sp, new_xform, false); - } - } - - spatial_editor->update_transform_gizmo(); - surface->queue_redraw(); - + apply_transform(motion, snap); } break; case TRANSFORM_ROTATE: { @@ -4873,53 +4884,85 @@ void Node3DEditorViewport::update_transform(bool p_shift) { bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW - List<Node *> &selection = editor_selection->get_selected_node_list(); - for (Node *E : selection) { - Node3D *sp = Object::cast_to<Node3D>(E); - if (!sp) { - continue; - } - - Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp); - if (!se) { - continue; - } - - if (sp->has_meta("_edit_lock_")) { - continue; - } - - Vector3 compute_axis = local_coords ? local_axis : global_axis; - if (se->gizmo.is_valid()) { - for (KeyValue<int, Transform3D> &GE : se->subgizmos) { - Transform3D xform = GE.value; - - Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original * xform, xform, compute_axis, angle, local_coords, true); // Force orthogonal with subgizmo. - if (!local_coords) { - new_xform = se->original.affine_inverse() * new_xform; - } - se->gizmo->set_subgizmo_transform(GE.key, new_xform); - } - } else { - Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original, se->original_local, compute_axis, angle, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS); - _transform_gizmo_apply(se->sp, new_xform, local_coords); - } - } - - spatial_editor->update_transform_gizmo(); - surface->queue_redraw(); - + Vector3 compute_axis = local_coords ? local_axis : global_axis; + apply_transform(compute_axis, angle); } break; default: { } } } +void Node3DEditorViewport::update_transform_numeric() { + Vector3 motion; + switch (_edit.plane) { + case TRANSFORM_VIEW: { + switch (_edit.mode) { + case TRANSFORM_TRANSLATE: + motion = Vector3(1, 0, 0); + break; + case TRANSFORM_ROTATE: + motion = spatial_editor->get_gizmo_transform().basis.xform_inv(_get_camera_normal()).normalized(); + break; + case TRANSFORM_SCALE: + motion = Vector3(1, 1, 1); + break; + case TRANSFORM_NONE: + ERR_FAIL_MSG("_edit.mode cannot be TRANSFORM_NONE in update_transform_numeric."); + } + break; + } + case TRANSFORM_X_AXIS: + motion = Vector3(1, 0, 0); + break; + case TRANSFORM_Y_AXIS: + motion = Vector3(0, 1, 0); + break; + case TRANSFORM_Z_AXIS: + motion = Vector3(0, 0, 1); + break; + case TRANSFORM_XY: + motion = Vector3(1, 1, 0); + break; + case TRANSFORM_XZ: + motion = Vector3(1, 0, 1); + break; + case TRANSFORM_YZ: + motion = Vector3(0, 1, 1); + break; + } + + double value = _edit.numeric_input * (_edit.numeric_negate ? -1 : 1); + double extra = 0.0; + switch (_edit.mode) { + case TRANSFORM_TRANSLATE: + motion *= value; + set_message(vformat(TTR("Translating %s."), motion)); + break; + case TRANSFORM_ROTATE: + extra = Math::deg_to_rad(value); + set_message(vformat(TTR("Rotating %f degrees."), value)); + break; + case TRANSFORM_SCALE: + // To halve the size of an object in Blender, you scale it by 0.5. + // Doing the same in Godot is considered scaling it by -0.5. + motion *= (value - 1.0); + set_message(vformat(TTR("Scaling %s."), motion)); + break; + case TRANSFORM_NONE: + ERR_FAIL_MSG("_edit.mode cannot be TRANSFORM_NONE in update_transform_numeric."); + } + + apply_transform(motion, extra); +} + // Perform cleanup after a transform operation is committed or cancelled. void Node3DEditorViewport::finish_transform() { - spatial_editor->set_local_coords_enabled(_edit.original_local); _edit.mode = TRANSFORM_NONE; _edit.instant = false; + _edit.numeric_input = 0; + _edit.numeric_next_decimal = 0; + _edit.numeric_negate = false; + spatial_editor->set_local_coords_enabled(_edit.original_local); spatial_editor->update_transform_gizmo(); surface->queue_redraw(); set_process_input(false); @@ -8126,7 +8169,7 @@ Node3DEditor::Node3DEditor() { String sct; - // Add some margin to the left for better aesthetics. + // Add some margin to the left for better esthetics. // This prevents the first button's hover/pressed effect from "touching" the panel's border, // which looks ugly. Control *margin_left = memnew(Control); |