|
@@ -58,20 +58,26 @@ void SpatialEditorViewport::_update_camera() {
|
|
|
} else
|
|
|
camera->set_perspective(get_fov(), get_znear(), get_zfar());
|
|
|
|
|
|
+ Transform camera_transform = to_camera_transform(cursor);
|
|
|
+
|
|
|
+ if (camera->get_global_transform() != camera_transform) {
|
|
|
+ camera->set_global_transform(camera_transform);
|
|
|
+ update_transform_gizmo_view();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Transform SpatialEditorViewport::to_camera_transform(const Cursor &p_cursor) const {
|
|
|
Transform camera_transform;
|
|
|
- camera_transform.translate(cursor.pos);
|
|
|
- camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
|
|
|
- camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
|
|
|
+ camera_transform.translate(p_cursor.pos);
|
|
|
+ camera_transform.basis.rotate(Vector3(1, 0, 0), -p_cursor.x_rot);
|
|
|
+ camera_transform.basis.rotate(Vector3(0, 1, 0), -p_cursor.y_rot);
|
|
|
|
|
|
if (orthogonal)
|
|
|
camera_transform.translate(0, 0, 4096);
|
|
|
else
|
|
|
- camera_transform.translate(0, 0, cursor.distance);
|
|
|
+ camera_transform.translate(0, 0, p_cursor.distance);
|
|
|
|
|
|
- if (camera->get_global_transform() != camera_transform) {
|
|
|
- camera->set_global_transform(camera_transform);
|
|
|
- update_transform_gizmo_view();
|
|
|
- }
|
|
|
+ return camera_transform;
|
|
|
}
|
|
|
|
|
|
String SpatialEditorGizmo::get_handle_name(int p_idx) const {
|
|
@@ -669,8 +675,7 @@ void SpatialEditorViewport::_list_select(InputEventMouseButton b) {
|
|
|
selection_menu->add_item(spat->get_name());
|
|
|
selection_menu->set_item_icon(i, icon);
|
|
|
selection_menu->set_item_metadata(i, node_path);
|
|
|
- selection_menu->set_item_tooltip(i, String(spat->get_name()) +
|
|
|
- "\nType: " + spat->get_class() + "\nPath: " + node_path);
|
|
|
+ selection_menu->set_item_tooltip(i, String(spat->get_name()) + "\nType: " + spat->get_class() + "\nPath: " + node_path);
|
|
|
}
|
|
|
|
|
|
selection_menu->set_global_position(Vector2(b.global_x, b.global_y));
|
|
@@ -729,76 +734,6 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
|
|
|
|
|
|
if (_edit.mode == TRANSFORM_NONE && b.pressed) {
|
|
|
|
|
|
- Plane cursor_plane(cursor.cursor_pos, _get_camera_normal());
|
|
|
-
|
|
|
- Vector3 ray_origin = _get_ray_pos(Vector2(b.x, b.y));
|
|
|
- Vector3 ray_dir = _get_ray(Vector2(b.x, b.y));
|
|
|
-
|
|
|
- //gizmo modify
|
|
|
-
|
|
|
- if (b.mod.control) {
|
|
|
-
|
|
|
- Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_ray(ray_origin, ray_dir, get_tree()->get_root()->get_world()->get_scenario());
|
|
|
-
|
|
|
- Plane p(ray_origin, _get_camera_normal());
|
|
|
-
|
|
|
- float min_d = 1e10;
|
|
|
- bool found = false;
|
|
|
-
|
|
|
- for (int i = 0; i < instances.size(); i++) {
|
|
|
-
|
|
|
- Object *obj = ObjectDB::get_instance(instances[i]);
|
|
|
-
|
|
|
- if (!obj)
|
|
|
- continue;
|
|
|
-
|
|
|
- VisualInstance *vi = obj->cast_to<VisualInstance>();
|
|
|
- if (!vi)
|
|
|
- continue;
|
|
|
-
|
|
|
- //optimize by checking AABB (although should pre sort by distance)
|
|
|
- Rect3 aabb = vi->get_global_transform().xform(vi->get_aabb());
|
|
|
- if (p.distance_to(aabb.get_support(-ray_dir)) > min_d)
|
|
|
- continue;
|
|
|
-
|
|
|
- PoolVector<Face3> faces = vi->get_faces(VisualInstance::FACES_SOLID);
|
|
|
- int c = faces.size();
|
|
|
- if (c > 0) {
|
|
|
- PoolVector<Face3>::Read r = faces.read();
|
|
|
-
|
|
|
- for (int j = 0; j < c; j++) {
|
|
|
-
|
|
|
- Vector3 inters;
|
|
|
- if (r[j].intersects_ray(ray_origin, ray_dir, &inters)) {
|
|
|
-
|
|
|
- float d = p.distance_to(inters);
|
|
|
- if (d < 0)
|
|
|
- continue;
|
|
|
-
|
|
|
- if (d < min_d) {
|
|
|
- min_d = d;
|
|
|
- found = true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (found) {
|
|
|
-
|
|
|
- //cursor.cursor_pos=ray_origin+ray_dir*min_d;
|
|
|
- //VisualServer::get_singleton()->instance_set_transform(cursor_instance,Transform(Matrix3(),cursor.cursor_pos));
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- Vector3 new_pos;
|
|
|
- if (cursor_plane.intersects_ray(ray_origin, ray_dir, &new_pos)) {
|
|
|
-
|
|
|
- //cursor.cursor_pos=new_pos;
|
|
|
- //VisualServer::get_singleton()->instance_set_transform(cursor_instance,Transform(Matrix3(),cursor.cursor_pos));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
if (b.mod.alt) {
|
|
|
|
|
|
if (nav_scheme == NAVIGATION_MAYA)
|
|
@@ -1344,6 +1279,8 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
|
|
|
|
|
|
if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
|
|
|
nav_mode = NAVIGATION_ZOOM;
|
|
|
+ } else {
|
|
|
+ nav_mode = NAVIGATION_LOOK;
|
|
|
}
|
|
|
|
|
|
} else if (m.button_mask & 4) {
|
|
@@ -1453,6 +1390,29 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
|
|
|
_update_name();
|
|
|
} break;
|
|
|
|
|
|
+ case NAVIGATION_LOOK: {
|
|
|
+ // Freelook only works properly in perspective.
|
|
|
+ // It technically works too in ortho, but it's awful for a user due to fov being near zero
|
|
|
+ if (!orthogonal) {
|
|
|
+ cursor.x_rot += m.relative_y / 120.0;
|
|
|
+ cursor.y_rot += m.relative_x / 120.0;
|
|
|
+ if (cursor.x_rot > Math_PI / 2.0)
|
|
|
+ cursor.x_rot = Math_PI / 2.0;
|
|
|
+ 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
|
|
|
+ Transform camera_transform = to_camera_transform(cursor);
|
|
|
+ Vector3 pos = camera_transform.xform(Vector3(0, 0, 0));
|
|
|
+ Vector3 diff = camera->get_translation() - pos;
|
|
|
+ cursor.pos += diff;
|
|
|
+
|
|
|
+ name = "";
|
|
|
+ _update_name();
|
|
|
+ }
|
|
|
+
|
|
|
+ } break;
|
|
|
+
|
|
|
default: {}
|
|
|
}
|
|
|
} break;
|
|
@@ -1543,6 +1503,75 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void SpatialEditorViewport::_update_freelook(real_t delta) {
|
|
|
+
|
|
|
+ const Input &input = *Input::get_singleton();
|
|
|
+
|
|
|
+ if (!input.is_mouse_button_pressed(BUTTON_RIGHT))
|
|
|
+ return;
|
|
|
+
|
|
|
+ Vector3 forward = camera->get_transform().basis.xform(Vector3(0, 0, -1));
|
|
|
+ Vector3 right = camera->get_transform().basis.xform(Vector3(1, 0, 0));
|
|
|
+ Vector3 up = Vector3(0, 1, 0);
|
|
|
+
|
|
|
+ int key_left = ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), KEY_A)->get_shortcut().key.scancode;
|
|
|
+ int key_right = ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D)->get_shortcut().key.scancode;
|
|
|
+ int key_forward = ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W)->get_shortcut().key.scancode;
|
|
|
+ int key_backwards = ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S)->get_shortcut().key.scancode;
|
|
|
+ int key_up = ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_Q)->get_shortcut().key.scancode;
|
|
|
+ int key_down = ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E)->get_shortcut().key.scancode;
|
|
|
+ int key_speed_modifier = ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT)->get_shortcut().key.scancode;
|
|
|
+
|
|
|
+ Vector3 velocity;
|
|
|
+ bool pressed = false;
|
|
|
+ bool speed_modifier = false;
|
|
|
+
|
|
|
+ if (input.is_key_pressed(key_left)) {
|
|
|
+ velocity -= right;
|
|
|
+ pressed = true;
|
|
|
+ }
|
|
|
+ if (input.is_key_pressed(key_right)) {
|
|
|
+ velocity += right;
|
|
|
+ pressed = true;
|
|
|
+ }
|
|
|
+ if (input.is_key_pressed(key_forward)) {
|
|
|
+ velocity += forward;
|
|
|
+ pressed = true;
|
|
|
+ }
|
|
|
+ if (input.is_key_pressed(key_backwards)) {
|
|
|
+ velocity -= forward;
|
|
|
+ pressed = true;
|
|
|
+ }
|
|
|
+ if (input.is_key_pressed(key_up)) {
|
|
|
+ velocity += up;
|
|
|
+ pressed = true;
|
|
|
+ }
|
|
|
+ if (input.is_key_pressed(key_down)) {
|
|
|
+ velocity -= up;
|
|
|
+ pressed = true;
|
|
|
+ }
|
|
|
+ if (input.is_key_pressed(key_speed_modifier)) {
|
|
|
+ speed_modifier = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ const EditorSettings &s = *EditorSettings::get_singleton();
|
|
|
+
|
|
|
+ real_t base_speed = s.get("editors/3d/freelook_base_speed");
|
|
|
+ real_t acceleration = s.get("editors/3d/freelook_acceleration");
|
|
|
+ real_t max_speed = s.get("editors/3d/freelook_max_speed");
|
|
|
+ real_t modifier_speed_factor = s.get("editors/3d/freelook_modifier_speed_factor");
|
|
|
+
|
|
|
+ if (pressed) {
|
|
|
+ velocity.normalize();
|
|
|
+ freelook_speed += acceleration * delta;
|
|
|
+ if (freelook_speed > max_speed)
|
|
|
+ freelook_speed = max_speed;
|
|
|
+ cursor.pos += velocity * ((freelook_speed * (speed_modifier ? modifier_speed_factor : 1.0) * delta));
|
|
|
+ } else {
|
|
|
+ freelook_speed = base_speed;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void SpatialEditorViewport::set_message(String p_message, float p_time) {
|
|
|
|
|
|
message = p_message;
|
|
@@ -1579,6 +1608,8 @@ void SpatialEditorViewport::_notification(int p_what) {
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
+ _update_freelook(get_tree()->get_idle_process_time());
|
|
|
+
|
|
|
_update_camera();
|
|
|
|
|
|
Map<Node *, Object *> &selection = editor_selection->get_selection();
|
|
@@ -2204,6 +2235,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
|
|
|
previewing = NULL;
|
|
|
preview = NULL;
|
|
|
gizmo_scale = 1.0;
|
|
|
+ freelook_speed = 0;
|
|
|
|
|
|
selection_menu = memnew(PopupMenu);
|
|
|
add_child(selection_menu);
|
|
@@ -3149,36 +3181,6 @@ void SpatialEditor::_finish_indicators() {
|
|
|
VisualServer::get_singleton()->free(cursor_mesh);
|
|
|
}
|
|
|
|
|
|
-void SpatialEditor::_instance_scene() {
|
|
|
-#if 0
|
|
|
- EditorNode *en = get_scene()->get_root_node()->cast_to<EditorNode>();
|
|
|
- ERR_FAIL_COND(!en);
|
|
|
- String path = en->get_filesystem_dock()->get_selected_path();
|
|
|
- if (path=="") {
|
|
|
- set_message(TTR("No scene selected to instance!"));
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- undo_redo->create_action(TTR("Instance at Cursor"));
|
|
|
-
|
|
|
- Node* scene = en->request_instance_scene(path);
|
|
|
-
|
|
|
- if (!scene) {
|
|
|
- set_message(TTR("Could not instance scene!"));
|
|
|
- undo_redo->commit_action(); //bleh
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- Spatial *s = scene->cast_to<Spatial>();
|
|
|
- if (s) {
|
|
|
-
|
|
|
- undo_redo->add_do_method(s,"set_global_transform",Transform(Matrix3(),cursor.cursor_pos));
|
|
|
- }
|
|
|
-
|
|
|
- undo_redo->commit_action();
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
void SpatialEditor::_unhandled_key_input(InputEvent p_event) {
|
|
|
|
|
|
if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
|
|
@@ -3242,8 +3244,6 @@ void SpatialEditor::_notification(int p_what) {
|
|
|
tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons"));
|
|
|
tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons"));
|
|
|
tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_icon("ListSelect", "EditorIcons"));
|
|
|
- instance_button->set_icon(get_icon("SpatialAdd", "EditorIcons"));
|
|
|
- instance_button->hide();
|
|
|
|
|
|
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_icon("Panels1", "EditorIcons"));
|
|
|
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_icon("Panels2", "EditorIcons"));
|
|
@@ -3383,7 +3383,6 @@ void SpatialEditor::_bind_methods() {
|
|
|
ClassDB::bind_method("_node_removed", &SpatialEditor::_node_removed);
|
|
|
ClassDB::bind_method("_menu_item_pressed", &SpatialEditor::_menu_item_pressed);
|
|
|
ClassDB::bind_method("_xform_dialog_action", &SpatialEditor::_xform_dialog_action);
|
|
|
- ClassDB::bind_method("_instance_scene", &SpatialEditor::_instance_scene);
|
|
|
ClassDB::bind_method("_get_editor_data", &SpatialEditor::_get_editor_data);
|
|
|
ClassDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo);
|
|
|
ClassDB::bind_method("_default_light_angle_input", &SpatialEditor::_default_light_angle_input);
|
|
@@ -3520,12 +3519,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
|
|
|
tool_button[TOOL_MODE_SCALE]->connect("pressed", this, "_menu_item_pressed", button_binds);
|
|
|
tool_button[TOOL_MODE_SCALE]->set_tooltip(TTR("Scale Mode (R)"));
|
|
|
|
|
|
- instance_button = memnew(Button);
|
|
|
- hbc_menu->add_child(instance_button);
|
|
|
- instance_button->set_flat(true);
|
|
|
- instance_button->connect("pressed", this, "_instance_scene");
|
|
|
- instance_button->hide();
|
|
|
-
|
|
|
VSeparator *vs = memnew(VSeparator);
|
|
|
hbc_menu->add_child(vs);
|
|
|
|