summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Gilleron <marc.gilleron@gmail.com>2017-05-01 20:57:35 +0200
committerMarc Gilleron <marc.gilleron@gmail.com>2017-05-04 01:38:12 +0200
commit442006b4bfd82247cf995bec6a33a2455cd21330 (patch)
tree92511b91fa6f376eca2876cf0dbb34a060301851
parentf527a6946285502f8d518f054b1bebc1d3fa564e (diff)
Added 3D freelook navigation mode
- Triggered by holding RMB - Can look around in FPS style - Can move with WASD - Movement speed accelerates over time - Can multiply speed with a modifier key to go faster or slower - Configurable in editor settings and shortcuts
-rw-r--r--editor/editor_settings.cpp5
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp231
-rw-r--r--editor/plugins/spatial_editor_plugin.h9
3 files changed, 122 insertions, 123 deletions
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 1b4f77419b..0acf9d069f 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -589,6 +589,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
set("editors/3d/emulate_3_button_mouse", false);
set("editors/3d/warped_mouse_panning", true);
+ set("editors/3d/freelook_base_speed", 5);
+ set("editors/3d/freelook_acceleration", 10);
+ set("editors/3d/freelook_max_speed", 100);
+ set("editors/3d/freelook_modifier_speed_factor", 1.0 / 5.0);
+
set("editors/2d/bone_width", 5);
set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.9));
set("editors/2d/bone_color2", Color(0.75, 0.75, 0.75, 0.9));
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index d73349f773..8a8add5611 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -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);
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 4302927426..c7336cef86 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -113,6 +113,7 @@ private:
bool transforming;
bool orthogonal;
float gizmo_scale;
+ real_t freelook_speed;
struct _RayResult {
@@ -168,7 +169,8 @@ private:
NAVIGATION_NONE,
NAVIGATION_PAN,
NAVIGATION_ZOOM,
- NAVIGATION_ORBIT
+ NAVIGATION_ORBIT,
+ NAVIGATION_LOOK
};
enum TransformMode {
TRANSFORM_NONE,
@@ -203,8 +205,6 @@ private:
struct Cursor {
- Vector3 cursor_pos;
-
Vector3 pos;
float x_rot, y_rot, distance;
bool region_select;
@@ -227,10 +227,12 @@ private:
//
void _update_camera();
+ Transform to_camera_transform(const Cursor &p_cursor) const;
void _draw();
void _smouseenter();
void _sinput(const InputEvent &p_ie);
+ void _update_freelook(real_t delta);
SpatialEditor *spatial_editor;
Camera *previewing;
@@ -385,7 +387,6 @@ private:
};
Button *tool_button[TOOL_MAX];
- Button *instance_button;
MenuButton *transform_menu;
MenuButton *view_menu;