diff options
Diffstat (limited to 'editor/plugins/spatial_editor_plugin.cpp')
| -rw-r--r-- | editor/plugins/spatial_editor_plugin.cpp | 734 |
1 files changed, 475 insertions, 259 deletions
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 7a43c41b0e..f96cbabde7 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -49,19 +49,22 @@ #define DISTANCE_DEFAULT 4 -#define GIZMO_ARROW_SIZE 0.3 +#define GIZMO_ARROW_SIZE 0.35 #define GIZMO_RING_HALF_WIDTH 0.1 //#define GIZMO_SCALE_DEFAULT 0.28 #define GIZMO_SCALE_DEFAULT 0.15 #define GIZMO_PLANE_SIZE 0.2 #define GIZMO_PLANE_DST 0.3 -#define GIZMO_CIRCLE_SIZE 0.9 +#define GIZMO_CIRCLE_SIZE 1.1 +#define GIZMO_SCALE_OFFSET (GIZMO_CIRCLE_SIZE + 0.3) +#define GIZMO_ARROW_OFFSET (GIZMO_CIRCLE_SIZE + 0.3) #define ZOOM_MIN_DISTANCE 0.001 #define ZOOM_MULTIPLIER 1.08 #define ZOOM_INDICATOR_DELAY_S 1.5 -#define FREELOOK_MIN_SPEED 0.1 +#define FREELOOK_MIN_SPEED 0.01 +#define FREELOOK_SPEED_MULTIPLIER 1.08 #define MIN_Z 0.01 #define MAX_Z 10000 @@ -70,53 +73,93 @@ #define MAX_FOV 179 void SpatialEditorViewport::_update_camera(float p_interp_delta) { - if (orthogonal) { - //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar()); - camera->set_orthogonal(2 * cursor.distance, 0.1, 8192); - } else - camera->set_perspective(get_fov(), get_znear(), get_zfar()); - //when not being manipulated, move softly - float free_orbit_inertia = EDITOR_DEF("editors/3d/free_orbit_inertia", 0.15); - float free_translation_inertia = EDITOR_DEF("editors/3d/free_translation_inertia", 0.15); - //when being manipulated, move more quickly - float manip_orbit_inertia = EDITOR_DEF("editors/3d/manipulation_orbit_inertia", 0.075); - float manip_translation_inertia = EDITOR_DEF("editors/3d/manipulation_translation_inertia", 0.075); - - //determine if being manipulated - bool manipulated = (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL); - - float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia); - float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia); + bool is_orthogonal = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL; Cursor old_camera_cursor = camera_cursor; camera_cursor = cursor; - camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); - camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + if (p_interp_delta > 0) { + + //------- + // Perform smoothing + + if (is_freelook_active()) { - camera_cursor.pos = old_camera_cursor.pos.linear_interpolate(cursor.pos, MIN(1.f, p_interp_delta * (1 / translation_inertia))); - camera_cursor.distance = Math::lerp(old_camera_cursor.distance, cursor.distance, MIN(1.f, p_interp_delta * (1 / translation_inertia))); + // Higher inertia should increase "lag" (lerp with factor between 0 and 1) + // Inertia of zero should produce instant movement (lerp with factor of 1) in this case it returns a really high value and gets clamped to 1. + real_t inertia = EDITOR_GET("editors/3d/freelook/freelook_inertia"); + inertia = MAX(0.001, inertia); + real_t factor = (1.0 / inertia) * p_interp_delta; - if (p_interp_delta == 0 || is_freelook_active()) { - camera_cursor = cursor; + // We interpolate a different point here, because in freelook mode the focus point (cursor.pos) orbits around eye_pos + camera_cursor.eye_pos = old_camera_cursor.eye_pos.linear_interpolate(cursor.eye_pos, CLAMP(factor, 0, 1)); + //camera_cursor.pos = camera_cursor.eye_pos + (cursor.pos - cursor.eye_pos); + + float orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia"); + orbit_inertia = MAX(0.0001, orbit_inertia); + camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + + Vector3 forward = to_camera_transform(camera_cursor).basis.xform(Vector3(0, 0, -1)); + camera_cursor.pos = camera_cursor.eye_pos + forward * camera_cursor.distance; + + } else { + + //when not being manipulated, move softly + float free_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia"); + float free_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/translation_inertia"); + //when being manipulated, move more quickly + float manip_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_orbit_inertia"); + float manip_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_translation_inertia"); + + float zoom_inertia = EDITOR_GET("editors/3d/navigation_feel/zoom_inertia"); + + //determine if being manipulated + bool manipulated = Input::get_singleton()->get_mouse_button_mask() & (2 | 4); + manipulated |= Input::get_singleton()->is_key_pressed(KEY_SHIFT); + manipulated |= Input::get_singleton()->is_key_pressed(KEY_ALT); + manipulated |= Input::get_singleton()->is_key_pressed(KEY_CONTROL); + + float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia); + float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia); + zoom_inertia = MAX(0.0001, zoom_inertia); + + camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + + camera_cursor.pos = old_camera_cursor.pos.linear_interpolate(cursor.pos, MIN(1.f, p_interp_delta * (1 / translation_inertia))); + camera_cursor.distance = Math::lerp(old_camera_cursor.distance, cursor.distance, MIN(1.f, p_interp_delta * (1 / zoom_inertia))); + } } - float tolerance = 0.0001; + //------- + // Apply camera transform + + float tolerance = 0.001; bool equal = true; - if (Math::abs(old_camera_cursor.x_rot - camera_cursor.x_rot) > tolerance || Math::abs(old_camera_cursor.y_rot - camera_cursor.y_rot) > tolerance) + if (Math::abs(old_camera_cursor.x_rot - camera_cursor.x_rot) > tolerance || Math::abs(old_camera_cursor.y_rot - camera_cursor.y_rot) > tolerance) { equal = false; + } - if (equal && old_camera_cursor.pos.distance_squared_to(camera_cursor.pos) > tolerance * tolerance) + if (equal && old_camera_cursor.pos.distance_squared_to(camera_cursor.pos) > tolerance * tolerance) { equal = false; + } - if (equal && Math::abs(old_camera_cursor.distance - camera_cursor.distance) > tolerance) + if (equal && Math::abs(old_camera_cursor.distance - camera_cursor.distance) > tolerance) { equal = false; + } - if (!equal || p_interp_delta == 0 || is_freelook_active()) { + if (!equal || p_interp_delta == 0 || is_freelook_active() || is_orthogonal != orthogonal) { camera->set_global_transform(to_camera_transform(camera_cursor)); update_transform_gizmo_view(); + + if (orthogonal) { + //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar()); + camera->set_orthogonal(2 * cursor.distance, 0.1, 8192); + } else + camera->set_perspective(get_fov(), get_znear(), get_zfar()); } } @@ -217,7 +260,7 @@ Transform SpatialEditorViewport::_get_camera_transform() const { return camera->get_global_transform(); } -Vector3 SpatialEditorViewport::_get_camera_pos() const { +Vector3 SpatialEditorViewport::_get_camera_position() const { return _get_camera_transform().origin; } @@ -464,8 +507,7 @@ void SpatialEditorViewport::_select_region() { Vector<Plane> frustum; - Vector3 cam_pos = _get_camera_pos(); - Set<Ref<SpatialEditorGizmo> > found_gizmos; + Vector3 cam_pos = _get_camera_position(); for (int i = 0; i < 4; i++) { @@ -485,6 +527,9 @@ void SpatialEditorViewport::_select_region() { frustum.push_back(far); Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world()->get_scenario()); + Vector<Spatial *> selected; + + Node *edited_scene = get_tree()->get_edited_scene_root(); for (int i = 0; i < instances.size(); i++) { @@ -497,11 +542,14 @@ void SpatialEditorViewport::_select_region() { if (!seg.is_valid()) continue; - if (found_gizmos.has(seg)) - continue; + Spatial *root_sp = sp; + while (root_sp && root_sp != edited_scene && root_sp->get_owner() != edited_scene && !edited_scene->is_editable_instance(root_sp->get_owner())) { + root_sp = Object::cast_to<Spatial>(root_sp->get_owner()); + } - if (seg->intersect_frustum(camera, frustum)) - _select(sp, true, false); + if (selected.find(root_sp) == -1) + if (seg->intersect_frustum(camera, frustum)) + _select(root_sp, true, false); } } @@ -525,8 +573,6 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) { List<Node *> &selection = editor_selection->get_selected_node_list(); - //Vector3 center; - //int nc=0; for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to<Spatial>(E->get()); @@ -538,14 +584,8 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) { continue; se->original = se->sp->get_global_transform(); - //center+=se->original.origin; - //nc++; + se->original_local = se->sp->get_transform(); } - - /* - if (nc) - _edit.center=center/float(nc); - */ } static int _get_key_modifier_setting(const String &p_property) { @@ -596,7 +636,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig for (int i = 0; i < 3; i++) { - Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs; + Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs * (GIZMO_ARROW_OFFSET + (GIZMO_ARROW_SIZE * 0.5)); float grabber_radius = gs * GIZMO_ARROW_SIZE; Vector3 r; @@ -611,7 +651,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig } bool is_plane_translate = false; - // second try + // plane select if (col_axis == -1) { col_d = 1e20; @@ -697,6 +737,43 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig } } + if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE) { + + int col_axis = -1; + float col_d = 1e20; + + for (int i = 0; i < 3; i++) { + + Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs * GIZMO_SCALE_OFFSET; + float grabber_radius = gs * GIZMO_ARROW_SIZE; + + Vector3 r; + + if (Geometry::segment_intersects_sphere(ray_pos, ray_pos + ray * 10000.0, grabber_pos, grabber_radius, &r)) { + float d = r.distance_to(ray_pos); + if (d < col_d) { + col_d = d; + col_axis = i; + } + } + } + + if (col_axis != -1) { + + if (p_highlight_only) { + + spatial_editor->select_gizmo_highlight_axis(col_axis + 9); + + } else { + //handle scale + _edit.mode = TRANSFORM_SCALE; + _compute_edit(Point2(p_screenpos.x, p_screenpos.y)); + _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis); + } + return true; + } + } + if (p_highlight_only) spatial_editor->select_gizmo_highlight_axis(-1); @@ -797,20 +874,26 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { - + float zoom_factor = 1 + (ZOOM_MULTIPLIER - 1) * b->get_factor(); switch (b->get_button_index()) { case BUTTON_WHEEL_UP: { - scale_cursor_distance(is_freelook_active() ? ZOOM_MULTIPLIER : 1.0 / ZOOM_MULTIPLIER); + if (is_freelook_active()) + scale_freelook_speed(zoom_factor); + else + scale_cursor_distance(1.0 / zoom_factor); } break; case BUTTON_WHEEL_DOWN: { - scale_cursor_distance(is_freelook_active() ? 1.0 / ZOOM_MULTIPLIER : ZOOM_MULTIPLIER); + if (is_freelook_active()) + scale_freelook_speed(1.0 / zoom_factor); + else + scale_cursor_distance(zoom_factor); } break; case BUTTON_RIGHT: { - NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int(); + NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); if (b->is_pressed() && _edit.gizmo.is_valid()) { //restore @@ -856,11 +939,11 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (b->is_pressed()) { int mod = _get_key_modifier(b); - if (mod == _get_key_modifier_setting("editors/3d/freelook_activation_modifier")) { - freelook_active = true; + if (mod == _get_key_modifier_setting("editors/3d/freelook/freelook_activation_modifier")) { + set_freelook_active(true); } } else { - freelook_active = false; + set_freelook_active(false); } if (freelook_active && !surface->has_focus()) { @@ -908,7 +991,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (b->is_pressed()) { - NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int(); + NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->get_alt()) { break; } @@ -1117,7 +1200,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { _gizmo_select(_edit.mouse_pos, true); } - NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int(); + NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); NavigationMode nav_mode = NAVIGATION_NONE; if (_edit.gizmo.is_valid()) { @@ -1169,7 +1252,28 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { case TRANSFORM_SCALE: { - Plane plane = Plane(_edit.center, _get_camera_normal()); + Vector3 motion_mask; + Plane plane; + bool plane_mv; + + switch (_edit.plane) { + case TRANSFORM_VIEW: + motion_mask = Vector3(0, 0, 0); + plane = Plane(_edit.center, _get_camera_normal()); + break; + case TRANSFORM_X_AXIS: + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0); + plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized()); + break; + case TRANSFORM_Y_AXIS: + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1); + plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized()); + break; + case TRANSFORM_Z_AXIS: + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2); + plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized()); + break; + } Vector3 intersection; if (!plane.intersects_ray(ray_pos, ray, &intersection)) @@ -1179,42 +1283,78 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (!plane.intersects_ray(_edit.click_ray_pos, _edit.click_ray, &click)) break; - float center_click_dist = click.distance_to(_edit.center); - float center_inters_dist = intersection.distance_to(_edit.center); - if (center_click_dist == 0) - break; + Vector3 motion = intersection - click; + print_line(String(intersection) + " --- " + String(click)); + if (motion_mask != Vector3()) { - float scale = (center_inters_dist / center_click_dist) * 100.0; + motion = motion_mask.dot(motion) * motion_mask; + } else { - if (_edit.snap || spatial_editor->is_snap_enabled()) { + float center_click_dist = click.distance_to(_edit.center); + float center_inters_dist = intersection.distance_to(_edit.center); + if (center_click_dist == 0) + break; - scale = Math::stepify(scale, spatial_editor->get_scale_snap()); + float scale = center_inters_dist - center_click_dist; + motion = Vector3(scale, scale, scale); } - set_message(vformat(TTR("Scaling to %s%%."), String::num(scale, 1))); - scale /= 100.0; + List<Node *> &selection = editor_selection->get_selected_node_list(); - Transform r; - r.basis.scale(Vector3(scale, scale, scale)); + bool local_coords = (spatial_editor->are_local_coords_enabled() && motion_mask != Vector3()); // Disable local transformation for TRANSFORM_VIEW - List<Node *> &selection = editor_selection->get_selected_node_list(); + float snap = 0; + if (_edit.snap || spatial_editor->is_snap_enabled()) { + + snap = spatial_editor->get_scale_snap() / 100; + } for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to<Spatial>(E->get()); - if (!sp) + if (!sp) { continue; + } SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp); - if (!se) + if (!se) { continue; + } Transform original = se->original; - + Transform original_local = se->original_local; Transform base = Transform(Basis(), _edit.center); - Transform t = base * (r * (base.inverse() * original)); + Transform t; + Vector3 local_scale; - sp->set_global_transform(t); + if (local_coords) { + + Basis g = original.basis.orthonormalized(); + Vector3 local_motion = g.inverse().xform(motion); + + if (_edit.snap || spatial_editor->is_snap_enabled()) { + local_motion.snap(Vector3(snap, snap, snap)); + } + + local_scale = original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1)); + + } else { + + if (_edit.snap || spatial_editor->is_snap_enabled()) { + motion.snap(Vector3(snap, snap, snap)); + } + + Transform r; + r.basis.scale(motion + Vector3(1, 1, 1)); + t = base * (r * (base.inverse() * original)); + } + + // Apply scale + if (local_coords) { + sp->set_scale(local_scale); + } else { + sp->set_global_transform(t); + } } surface->update(); @@ -1341,6 +1481,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { case TRANSFORM_ROTATE: { Plane plane; + Vector3 axis; switch (_edit.plane) { case TRANSFORM_VIEW: @@ -1348,12 +1489,15 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { break; case TRANSFORM_X_AXIS: plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(0)); + axis = Vector3(1, 0, 0); break; case TRANSFORM_Y_AXIS: plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(1)); + axis = Vector3(0, 1, 0); break; case TRANSFORM_Z_AXIS: plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2)); + axis = Vector3(0, 0, 1); break; } @@ -1369,6 +1513,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Vector3 x_axis = plane.normal.cross(y_axis).normalized(); float angle = Math::atan2(x_axis.dot(intersection - _edit.center), y_axis.dot(intersection - _edit.center)); + if (_edit.snap || spatial_editor->is_snap_enabled()) { float snap = spatial_editor->get_rotate_snap(); @@ -1385,11 +1530,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { set_message(vformat(TTR("Rotating %s degrees."), rtos(Math::rad2deg(angle)))); } - Transform r; - r.basis.rotate(plane.normal, angle); - List<Node *> &selection = editor_selection->get_selected_node_list(); + bool local_coords = spatial_editor->are_local_coords_enabled(); + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to<Spatial>(E->get()); @@ -1400,27 +1544,33 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (!se) continue; - Transform original = se->original; + Transform t; - Transform base = Transform(Basis(), _edit.center); - Transform t = base * r * base.inverse() * original; + if (local_coords) { - sp->set_global_transform(t); + Transform original_local = se->original_local; + Basis rot = Basis(axis, angle); + + t.basis = original_local.get_basis() * rot; + t.origin = original_local.origin; + + sp->set_transform(t); + + } else { + + Transform original = se->original; + Transform r; + Transform base = Transform(Basis(), _edit.center); + + r.basis.rotate(plane.normal, angle); + t = base * r * base.inverse() * original; + + sp->set_global_transform(t); + } } surface->update(); - /* - VisualServer::get_singleton()->poly_clear(indicators); - - Vector<Vector3> points; - Vector<Vector3> empty; - Vector<Color> colors; - points.push_back(intersection); - points.push_back(_edit.original.origin); - colors.push_back( Color(255,155,100) ); - colors.push_back( Color(255,155,100) ); - VisualServer::get_singleton()->poly_add_primitive(indicators,points,empty,colors,empty); - */ + } break; default: {} } @@ -1440,11 +1590,11 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { int mod = _get_key_modifier(m); - if (mod == _get_key_modifier_setting("editors/3d/pan_modifier")) + if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) nav_mode = NAVIGATION_PAN; - else if (mod == _get_key_modifier_setting("editors/3d/zoom_modifier")) + else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) nav_mode = NAVIGATION_ZOOM; - else if (mod == _get_key_modifier_setting("editors/3d/orbit_modifier")) + else if (mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) nav_mode = NAVIGATION_ORBIT; } else if (nav_scheme == NAVIGATION_MAYA) { @@ -1452,16 +1602,16 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { nav_mode = NAVIGATION_PAN; } - } else if (EditorSettings::get_singleton()->get("editors/3d/emulate_3_button_mouse")) { + } else if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_3_button_mouse")) { // Handle trackpad (no external mouse) use case int mod = _get_key_modifier(m); if (mod) { - if (mod == _get_key_modifier_setting("editors/3d/pan_modifier")) + if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) nav_mode = NAVIGATION_PAN; - else if (mod == _get_key_modifier_setting("editors/3d/zoom_modifier")) + else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) nav_mode = NAVIGATION_ZOOM; - else if (mod == _get_key_modifier_setting("editors/3d/orbit_modifier")) + else if (mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) nav_mode = NAVIGATION_ORBIT; } } @@ -1494,7 +1644,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (nav_scheme == NAVIGATION_MAYA && m->get_shift()) zoom_speed *= zoom_speed_modifier; - NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/zoom_style").operator int(); + NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/navigation/zoom_style").operator int(); if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) { if (m->get_relative().x > 0) scale_cursor_distance(1 - m->get_relative().x * zoom_speed); @@ -1512,7 +1662,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { case NAVIGATION_ORBIT: { Point2i relative = _get_warped_mouse_motion(m); - real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/orbit_sensitivity"); + real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); cursor.x_rot += relative.y * radians_per_pixel; @@ -1531,9 +1681,12 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (!orthogonal) { Point2i relative = _get_warped_mouse_motion(m); - real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/orbit_sensitivity"); + real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag". + Transform prev_camera_transform = to_camera_transform(cursor); + cursor.x_rot += relative.y * radians_per_pixel; cursor.y_rot += relative.x * radians_per_pixel; if (cursor.x_rot > Math_PI / 2.0) @@ -1541,12 +1694,12 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (cursor.x_rot < -Math_PI / 2.0) cursor.x_rot = -Math_PI / 2.0; - // Look is like Orbit, except the cursor translates, not the camera + // Look is like the opposite of Orbit: the focus point rotates around the camera Transform camera_transform = to_camera_transform(cursor); Vector3 pos = camera_transform.xform(Vector3(0, 0, 0)); - Vector3 diff = camera->get_translation() - pos; + Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0)); + Vector3 diff = prev_pos - pos; cursor.pos += diff; - freelook_target_position += diff; name = ""; _update_name(); @@ -1644,23 +1797,57 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } +void SpatialEditorViewport::set_freelook_active(bool active_now) { + + if (!freelook_active && active_now) { + // Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential + cursor = camera_cursor; + + // Make sure eye_pos is synced, because freelook referential is eye pos rather than orbit pos + Vector3 forward = to_camera_transform(cursor).basis.xform(Vector3(0, 0, -1)); + cursor.eye_pos = cursor.pos - cursor.distance * forward; + // Also sync the camera cursor, otherwise switching to freelook will be trippy if inertia is active + camera_cursor.eye_pos = cursor.eye_pos; + + if (EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_speed_zoom_link")) { + // Re-adjust freelook speed from the current zoom level + real_t base_speed = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_base_speed"); + freelook_speed = base_speed * cursor.distance; + } + + } else if (freelook_active && !active_now) { + // Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential + cursor = camera_cursor; + } + + freelook_active = active_now; +} + void SpatialEditorViewport::scale_cursor_distance(real_t scale) { // Prevents zero distance which would short-circuit any scaling if (cursor.distance < ZOOM_MIN_DISTANCE) cursor.distance = ZOOM_MIN_DISTANCE; - real_t prev_distance = cursor.distance; cursor.distance *= scale; if (cursor.distance < ZOOM_MIN_DISTANCE) cursor.distance = ZOOM_MIN_DISTANCE; - if (is_freelook_active()) { - // In freelook mode, cursor reference is reversed so it needs to be adjusted - Vector3 forward = camera->get_transform().basis.xform(Vector3(0, 0, -1)); - cursor.pos += (cursor.distance - prev_distance) * forward; - } + zoom_indicator_delay = ZOOM_INDICATOR_DELAY_S; + surface->update(); +} + +void SpatialEditorViewport::scale_freelook_speed(real_t scale) { + + // Prevents zero distance which would short-circuit any scaling + if (freelook_speed < FREELOOK_MIN_SPEED) + freelook_speed = FREELOOK_MIN_SPEED; + + freelook_speed *= scale; + + if (freelook_speed < FREELOOK_MIN_SPEED) + freelook_speed = FREELOOK_MIN_SPEED; zoom_indicator_delay = ZOOM_INDICATOR_DELAY_S; surface->update(); @@ -1668,7 +1855,7 @@ void SpatialEditorViewport::scale_cursor_distance(real_t scale) { Point2i SpatialEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const { Point2i relative; - if (bool(EDITOR_DEF("editors/3d/warped_mouse_panning", false))) { + if (bool(EDITOR_DEF("editors/3d/navigation/warped_mouse_panning", false))) { relative = Input::get_singleton()->warp_mouse_motion(p_ev_mouse_motion, surface->get_global_rect()); } else { relative = p_ev_mouse_motion->get_relative(); @@ -1679,7 +1866,6 @@ Point2i SpatialEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMous void SpatialEditorViewport::_update_freelook(real_t delta) { if (!is_freelook_active()) { - freelook_target_position = cursor.pos; return; } @@ -1722,21 +1908,15 @@ void SpatialEditorViewport::_update_freelook(real_t delta) { speed_modifier = true; } - real_t inertia = EDITOR_DEF("editors/3d/freelook_inertia", 0.2); - inertia = MAX(0, inertia); - const real_t base_speed = EDITOR_DEF("editors/3d/freelook_base_speed", 0.5); - const real_t modifier_speed_factor = EDITOR_DEF("editors/3d/freelook_modifier_speed_factor", 5); - - real_t speed = base_speed * cursor.distance; - if (speed_modifier) + real_t speed = freelook_speed; + if (speed_modifier) { + real_t modifier_speed_factor = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_modifier_speed_factor"); speed *= modifier_speed_factor; + } - // Higher inertia should increase "lag" (lerp with factor between 0 and 1) - // Inertia of zero should produce instant movement (lerp with factor of 1) in this case it returns a really high value and gets clamped to 1. - - freelook_target_position += direction * speed; - real_t factor = (1.0 / (inertia + 0.001)) * delta; - cursor.pos = cursor.pos.linear_interpolate(freelook_target_position, CLAMP(factor, 0, 1)); + Vector3 motion = direction * speed * delta; + cursor.pos += motion; + cursor.eye_pos += motion; } void SpatialEditorViewport::set_message(String p_message, float p_time) { @@ -1775,7 +1955,7 @@ void SpatialEditorViewport::_notification(int p_what) { } */ - real_t delta = get_tree()->get_idle_process_time(); + real_t delta = get_process_delta_time(); if (zoom_indicator_delay > 0) { zoom_indicator_delay -= delta; @@ -1786,7 +1966,7 @@ void SpatialEditorViewport::_notification(int p_what) { _update_freelook(delta); - _update_camera(get_process_delta_time()); + _update_camera(delta); Map<Node *, Object *> &selection = editor_selection->get_selection(); @@ -1837,7 +2017,7 @@ void SpatialEditorViewport::_notification(int p_what) { last_message = message; } - message_time -= get_fixed_process_delta_time(); + message_time -= get_physics_process_delta_time(); if (message_time < 0) surface->update(); } @@ -1915,7 +2095,7 @@ void SpatialEditorViewport::_notification(int p_what) { } // TODO That should be part of the drawing API... -static void stroke_rect(CanvasItem *ci, Rect2 rect, Color color, real_t width = 1.0) { +static void stroke_rect(CanvasItem &ci, Rect2 rect, Color color, real_t width = 1.0) { // a---b // | | @@ -1925,10 +2105,31 @@ static void stroke_rect(CanvasItem *ci, Rect2 rect, Color color, real_t width = Vector2 c(rect.position.x, rect.position.y + rect.size.y); Vector2 d(rect.position + rect.size); - ci->draw_line(a, b, color, width); - ci->draw_line(b, d, color, width); - ci->draw_line(d, c, color, width); - ci->draw_line(c, a, color, width); + ci.draw_line(a, b, color, width); + ci.draw_line(b, d, color, width); + ci.draw_line(d, c, color, width); + ci.draw_line(c, a, color, width); +} + +static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture> icon) { + + // Adjust bar size from control height + Vector2 surface_size = surface.get_size(); + real_t h = surface_size.y / 2.0; + real_t y = (surface_size.y - h) / 2.0; + + Rect2 r(10, y, 6, h); + real_t sy = r.size.y * fill; + + // Note: because this bar appears over the viewport, it has to stay readable for any background color + // Draw both neutral dark and bright colors to account this + surface.draw_rect(r, Color(1, 1, 1, 0.2)); + surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6)); + stroke_rect(surface, r.grow(1), Color(0, 0, 0, 0.7)); + + Vector2 icon_size = icon->get_size(); + Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2); + surface.draw_texture(icon, icon_pos); } void SpatialEditorViewport::_draw() { @@ -1987,35 +2188,47 @@ void SpatialEditorViewport::_draw() { draw_rect = Rect2(Vector2(), s).clip(draw_rect); - stroke_rect(surface, draw_rect, Color(0.6, 0.6, 0.1, 0.5), 2.0); + stroke_rect(*surface, draw_rect, Color(0.6, 0.6, 0.1, 0.5), 2.0); } else { if (zoom_indicator_delay > 0.0) { - // Show indicative zoom factor - real_t min_distance = ZOOM_MIN_DISTANCE; // TODO Why not pick znear to limit zoom? - real_t max_distance = camera->get_zfar(); - real_t scale_length = (max_distance - min_distance); + if (is_freelook_active()) { + // Show speed + + real_t min_speed = FREELOOK_MIN_SPEED; + real_t max_speed = camera->get_zfar(); + real_t scale_length = (max_speed - min_speed); + + if (Math::abs(scale_length) > CMP_EPSILON) { + real_t logscale_t = 1.0 - Math::log(1 + freelook_speed - min_speed) / Math::log(1 + scale_length); + + // There is no real maximum speed so that factor can become negative, + // Let's make it look asymptotic instead (will decrease slower and slower). + if (logscale_t < 0.25) + logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); + + draw_indicator_bar(*surface, 1.0 - logscale_t, get_icon("ViewportSpeed", "EditorIcons")); + } - if (Math::abs(scale_length) > CMP_EPSILON) { - real_t logscale_t = 1.0 - Math::log(1 + cursor.distance - min_distance) / Math::log(1 + scale_length); + } else { + // Show zoom - // There is no real maximum distance so that factor can become negative, - // Let's make it look asymptotic instead (will decrease slower and slower). - if (logscale_t < 0.25) - logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); + real_t min_distance = ZOOM_MIN_DISTANCE; // TODO Why not pick znear to limit zoom? + real_t max_distance = camera->get_zfar(); + real_t scale_length = (max_distance - min_distance); - Vector2 surface_size = surface->get_size(); - real_t h = surface_size.y / 2.0; - real_t y = (surface_size.y - h) / 2.0; + if (Math::abs(scale_length) > CMP_EPSILON) { + real_t logscale_t = 1.0 - Math::log(1 + cursor.distance - min_distance) / Math::log(1 + scale_length); - Rect2 r(10, y, 6, h); - real_t sy = r.size.y * logscale_t; + // There is no real maximum distance so that factor can become negative, + // Let's make it look asymptotic instead (will decrease slower and slower). + if (logscale_t < 0.25) + logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); - surface->draw_rect(r, Color(1, 1, 1, 0.2)); - surface->draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6)); - stroke_rect(surface, r.grow(1), Color(0, 0, 0, 0.7)); + draw_indicator_bar(*surface, logscale_t, get_icon("ViewportZoom", "EditorIcons")); + } } } } @@ -2258,6 +2471,14 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) { //VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true); VS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); VS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i], layer); + + scale_gizmo_instance[i] = VS::get_singleton()->instance_create(); + VS::get_singleton()->instance_set_base(scale_gizmo_instance[i], spatial_editor->get_scale_gizmo(i)->get_rid()); + VS::get_singleton()->instance_set_scenario(scale_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); + VS::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false); + //VS::get_singleton()->instance_geometry_set_flag(scale_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true); + VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); + VS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer); } } @@ -2267,6 +2488,7 @@ void SpatialEditorViewport::_finish_gizmo_instances() { VS::get_singleton()->free(move_gizmo_instance[i]); VS::get_singleton()->free(move_plane_gizmo_instance[i]); VS::get_singleton()->free(rotate_gizmo_instance[i]); + VS::get_singleton()->free(scale_gizmo_instance[i]); } } void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { @@ -2361,14 +2583,16 @@ void SpatialEditorViewport::update_transform_gizmo_view() { VisualServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE)); VisualServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform); VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE)); + VisualServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform); + VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE)); } } void SpatialEditorViewport::set_state(const Dictionary &p_state) { - cursor.pos = p_state["pos"]; - cursor.x_rot = p_state["x_rot"]; - cursor.y_rot = p_state["y_rot"]; + cursor.pos = p_state["position"]; + cursor.x_rot = p_state["x_rotation"]; + cursor.y_rot = p_state["y_rotation"]; cursor.distance = p_state["distance"]; bool env = p_state["use_environment"]; bool orth = p_state["use_orthogonal"]; @@ -2410,9 +2634,9 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) { Dictionary SpatialEditorViewport::get_state() const { Dictionary d; - d["pos"] = cursor.pos; - d["x_rot"] = cursor.x_rot; - d["y_rot"] = cursor.y_rot; + d["position"] = cursor.pos; + d["x_rotation"] = cursor.x_rot; + d["y_rotation"] = cursor.y_rot; d["distance"] = cursor.distance; d["use_environment"] = camera->get_environment().is_valid(); d["use_orthogonal"] = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL; @@ -2454,6 +2678,7 @@ void SpatialEditorViewport::reset() { cursor.y_rot = 0.5; cursor.distance = 4; cursor.region_select = false; + cursor.pos = Vector3(); _update_name(); } @@ -2540,8 +2765,14 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const normal = hit_normal; } } - Vector3 center = preview_bounds->get_size() * 0.5; - return point + (center * normal); + Vector3 offset = Vector3(); + for (int i = 0; i < 3; i++) { + if (normal[i] > 0.0) + offset[i] = (preview_bounds->get_size()[i] - (preview_bounds->get_size()[i] + preview_bounds->get_position()[i])); + else if (normal[i] < 0.0) + offset[i] = -(preview_bounds->get_size()[i] + preview_bounds->get_position()[i]); + } + return point + offset; } Rect3 SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, const Rect3 p_bounds) { @@ -2829,7 +3060,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed ViewportContainer *c = memnew(ViewportContainer); c->set_stretch(true); add_child(c); - c->set_area_as_parent_rect(); + c->set_anchors_and_margins_preset(Control::PRESET_WIDE); viewport = memnew(Viewport); viewport->set_disable_input(true); @@ -2837,7 +3068,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed surface = memnew(Control); surface->set_drag_forwarding(this); add_child(surface); - surface->set_area_as_parent_rect(); + surface->set_anchors_and_margins_preset(Control::PRESET_WIDE); surface->set_clip_contents(true); camera = memnew(Camera); camera->set_disable_gizmo(true); @@ -2914,6 +3145,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed accept = NULL; freelook_active = false; + freelook_speed = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_base_speed"); selection_menu = memnew(PopupMenu); add_child(selection_menu); @@ -3246,6 +3478,7 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) { move_gizmo[i]->surface_set_material(0, i == p_axis ? gizmo_hl : gizmo_color[i]); move_plane_gizmo[i]->surface_set_material(0, (i + 6) == p_axis ? gizmo_hl : plane_gizmo_color[i]); rotate_gizmo[i]->surface_set_material(0, (i + 3) == p_axis ? gizmo_hl : gizmo_color[i]); + scale_gizmo[i]->surface_set_material(0, (i + 9) == p_axis ? gizmo_hl : gizmo_color[i]); } } @@ -3256,7 +3489,7 @@ void SpatialEditor::update_transform_gizmo() { bool first = true; Basis gizmo_basis; - bool local_gizmo_coords = transform_menu->get_popup()->is_item_checked(transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS)); + bool local_gizmo_coords = are_local_coords_enabled(); for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { @@ -3707,20 +3940,13 @@ void SpatialEditor::_menu_item_pressed(int p_option) { void SpatialEditor::_init_indicators() { - //RID mat = VisualServer::get_singleton()->fixed_material_create(); - ///VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA,true); - //VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true); - { indicator_mat.instance(); indicator_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - //indicator_mat->set_flag(SpatialMaterial::FLAG_ONTOP,true); indicator_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); indicator_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - indicator_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - PoolVector<Color> grid_colors[3]; PoolVector<Vector3> grid_points[3]; Vector<Color> origin_colors; @@ -3740,50 +3966,31 @@ void SpatialEditor::_init_indicators() { origin_colors.push_back(Color(axis.x, axis.y, axis.z)); origin_points.push_back(axis * 4096); origin_points.push_back(axis * -4096); -#define ORIGIN_GRID_SIZE 100 +#define ORIGIN_GRID_SIZE 50 for (int j = -ORIGIN_GRID_SIZE; j <= ORIGIN_GRID_SIZE; j++) { - for (int k = -ORIGIN_GRID_SIZE; k <= ORIGIN_GRID_SIZE; k++) { - - Vector3 p = axis_n1 * j + axis_n2 * k; - float trans = Math::pow(MAX(0, 1.0 - (Vector2(j, k).length() / ORIGIN_GRID_SIZE)), 2); - - Vector3 pj = axis_n1 * (j + 1) + axis_n2 * k; - float transj = Math::pow(MAX(0, 1.0 - (Vector2(j + 1, k).length() / ORIGIN_GRID_SIZE)), 2); - - Vector3 pk = axis_n1 * j + axis_n2 * (k + 1); - float transk = Math::pow(MAX(0, 1.0 - (Vector2(j, k + 1).length() / ORIGIN_GRID_SIZE)), 2); + Vector3 p1 = axis_n1 * j + axis_n2 * -ORIGIN_GRID_SIZE; + Vector3 p1_dest = p1 * (-axis_n2 + axis_n1); + Vector3 p2 = axis_n2 * j + axis_n1 * -ORIGIN_GRID_SIZE; + Vector3 p2_dest = p2 * (-axis_n1 + axis_n2); - Color trans_color = grid_color; - trans_color.a *= trans; - - Color transk_color = grid_color; - transk_color.a *= transk; - - Color transj_color = grid_color; - transj_color.a *= transj; - - if (j % 10 == 0 || k % 10 == 0) { - trans_color.a *= 2; - } - if ((k + 1) % 10 == 0) { - transk_color.a *= 2; - } - if ((j + 1) % 10 == 0) { - transj_color.a *= 2; - } + Color line_color = grid_color; + if (j == 0) { + continue; + } else if (j % 10 == 0) { + line_color *= 1.5; + } - grid_points[i].push_back(p); - grid_points[i].push_back(pk); - grid_colors[i].push_back(trans_color); - grid_colors[i].push_back(transk_color); + grid_points[i].push_back(p1); + grid_points[i].push_back(p1_dest); + grid_colors[i].push_back(line_color); + grid_colors[i].push_back(line_color); - grid_points[i].push_back(p); - grid_points[i].push_back(pj); - grid_colors[i].push_back(trans_color); - grid_colors[i].push_back(transj_color); - } + grid_points[i].push_back(p2); + grid_points[i].push_back(p2_dest); + grid_colors[i].push_back(line_color); + grid_colors[i].push_back(line_color); } grid[i] = VisualServer::get_singleton()->mesh_create(); @@ -3827,32 +4034,6 @@ void SpatialEditor::_init_indicators() { } { - cursor_mesh = VisualServer::get_singleton()->mesh_create(); - PoolVector<Vector3> cursor_points; - float cs = 0.25; - cursor_points.push_back(Vector3(+cs, 0, 0)); - cursor_points.push_back(Vector3(-cs, 0, 0)); - cursor_points.push_back(Vector3(0, +cs, 0)); - cursor_points.push_back(Vector3(0, -cs, 0)); - cursor_points.push_back(Vector3(0, 0, +cs)); - cursor_points.push_back(Vector3(0, 0, -cs)); - cursor_material.instance(); - cursor_material->set_albedo(Color(0, 1, 1)); - cursor_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - - Array d; - d.resize(VS::ARRAY_MAX); - d[VS::ARRAY_VERTEX] = cursor_points; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(cursor_mesh, VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(cursor_mesh, 0, cursor_material->get_rid()); - - cursor_instance = VisualServer::get_singleton()->instance_create2(cursor_mesh, get_tree()->get_root()->get_world()->get_scenario()); - VS::get_singleton()->instance_set_layer_mask(cursor_instance, 1 << SpatialEditorViewport::GIZMO_GRID_LAYER); - - VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(cursor_instance, VS::SHADOW_CASTING_SETTING_OFF); - } - - { //move gizmo @@ -3870,6 +4051,7 @@ void SpatialEditor::_init_indicators() { move_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); move_plane_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); rotate_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); + scale_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); Ref<SpatialMaterial> mat = memnew(SpatialMaterial); mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); @@ -3892,25 +4074,25 @@ void SpatialEditor::_init_indicators() { Vector3 ivec3; ivec3[(i + 2) % 3] = 1; + //translate { Ref<SurfaceTool> surftool = memnew(SurfaceTool); surftool->begin(Mesh::PRIMITIVE_TRIANGLES); - //translate - + // Arrow profile const int arrow_points = 5; Vector3 arrow[5] = { nivec * 0.0 + ivec * 0.0, nivec * 0.01 + ivec * 0.0, - nivec * 0.01 + ivec * 1.0, - nivec * 0.1 + ivec * 1.0, - nivec * 0.0 + ivec * (1 + GIZMO_ARROW_SIZE), + nivec * 0.01 + ivec * GIZMO_ARROW_OFFSET, + nivec * 0.065 + ivec * GIZMO_ARROW_OFFSET, + nivec * 0.0 + ivec * (GIZMO_ARROW_OFFSET + GIZMO_ARROW_SIZE), }; int arrow_sides = 6; - for (int k = 0; k < 7; k++) { + for (int k = 0; k < 6; k++) { Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides); Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides); @@ -3937,7 +4119,7 @@ void SpatialEditor::_init_indicators() { surftool->commit(move_gizmo[i]); } - // plane translation + // Plane Translation { Ref<SurfaceTool> surftool = memnew(SurfaceTool); surftool->begin(Mesh::PRIMITIVE_TRIANGLES); @@ -3980,6 +4162,7 @@ void SpatialEditor::_init_indicators() { surftool->commit(move_plane_gizmo[i]); } + // Rotate { Ref<SurfaceTool> surftool = memnew(SurfaceTool); @@ -3993,7 +4176,7 @@ void SpatialEditor::_init_indicators() { ivec * 0.02 + ivec2 * 0.02 + ivec2 * GIZMO_CIRCLE_SIZE, }; - for (int k = 0; k < 33; k++) { + for (int k = 0; k < 32; k++) { Basis ma(ivec, Math_PI * 2 * float(k) / 32); Basis mb(ivec, Math_PI * 2 * float(k + 1) / 32); @@ -4019,19 +4202,55 @@ void SpatialEditor::_init_indicators() { surftool->set_material(mat); surftool->commit(rotate_gizmo[i]); } - } - } - /*for(int i=0;i<4;i++) { + // Scale + { + Ref<SurfaceTool> surftool = memnew(SurfaceTool); + surftool->begin(Mesh::PRIMITIVE_TRIANGLES); - viewports[i]->init_gizmo_instance(i); - }*/ + // Cube arrow profile + const int arrow_points = 6; + Vector3 arrow[6] = { + nivec * 0.0 + ivec * 0.0, + nivec * 0.01 + ivec * 0.0, + nivec * 0.01 + ivec * 1.0 * GIZMO_SCALE_OFFSET, + nivec * 0.07 + ivec * 1.0 * GIZMO_SCALE_OFFSET, + nivec * 0.07 + ivec * 1.11 * GIZMO_SCALE_OFFSET, + nivec * 0.0 + ivec * 1.11 * GIZMO_SCALE_OFFSET, + }; - _generate_selection_box(); + int arrow_sides = 4; + + for (int k = 0; k < 4; k++) { + + Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides); + Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides); - //Object::cast_to<EditorNode>(get_scene()->get_root_node())->get_scene_root()->add_child(camera); + for (int j = 0; j < arrow_points - 1; j++) { - //current_camera=camera; + Vector3 points[4] = { + ma.xform(arrow[j]), + mb.xform(arrow[j]), + mb.xform(arrow[j + 1]), + ma.xform(arrow[j + 1]), + }; + surftool->add_vertex(points[0]); + surftool->add_vertex(points[1]); + surftool->add_vertex(points[2]); + + surftool->add_vertex(points[0]); + surftool->add_vertex(points[2]); + surftool->add_vertex(points[3]); + } + } + + surftool->set_material(mat); + surftool->commit(scale_gizmo[i]); + } + } + } + + _generate_selection_box(); } void SpatialEditor::_finish_indicators() { @@ -4045,9 +4264,6 @@ void SpatialEditor::_finish_indicators() { //VisualServer::get_singleton()->free(poly); //VisualServer::get_singleton()->free(indicators_instance); //VisualServer::get_singleton()->free(indicators); - - VisualServer::get_singleton()->free(cursor_instance); - VisualServer::get_singleton()->free(cursor_mesh); } bool SpatialEditor::is_any_freelook_active() const { @@ -4209,7 +4425,7 @@ void SpatialEditor::_toggle_maximize_view(Object *p_viewport) { for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { if (i == (uint32_t)index) - viewports[i]->set_area_as_parent_rect(); + viewports[i]->set_anchors_and_margins_preset(Control::PRESET_WIDE); else viewports[i]->hide(); } @@ -4644,7 +4860,7 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) { spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor->get_viewport()->add_child(spatial_editor); - //spatial_editor->set_area_as_parent_rect(); + //spatial_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE); spatial_editor->hide(); spatial_editor->connect("transform_key_request", editor, "_transform_keyed"); |
