Merge pull request #8616 from Zylann/fps_look
Added 3D freelook navigation mode
This commit is contained in:
commit
63d02067de
|
@ -591,6 +591,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));
|
||||
|
|
|
@ -58,15 +58,7 @@ void SpatialEditorViewport::_update_camera() {
|
|||
} else
|
||||
camera->set_perspective(get_fov(), get_znear(), get_zfar());
|
||||
|
||||
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);
|
||||
|
||||
if (orthogonal)
|
||||
camera_transform.translate(0, 0, 4096);
|
||||
else
|
||||
camera_transform.translate(0, 0, cursor.distance);
|
||||
Transform camera_transform = to_camera_transform(cursor);
|
||||
|
||||
if (camera->get_global_transform() != camera_transform) {
|
||||
camera->set_global_transform(camera_transform);
|
||||
|
@ -74,6 +66,20 @@ void SpatialEditorViewport::_update_camera() {
|
|||
}
|
||||
}
|
||||
|
||||
Transform SpatialEditorViewport::to_camera_transform(const Cursor &p_cursor) const {
|
||||
Transform camera_transform;
|
||||
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, p_cursor.distance);
|
||||
|
||||
return camera_transform;
|
||||
}
|
||||
|
||||
String SpatialEditorGizmo::get_handle_name(int p_idx) const {
|
||||
|
||||
if (get_script_instance() && get_script_instance()->has_method("get_handle_name"))
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue