Browse Source

Merge pull request #8616 from Zylann/fps_look

Added 3D freelook navigation mode
Rémi Verschelde 8 years ago
parent
commit
63d02067de

+ 5 - 0
editor/editor_settings.cpp

@@ -591,6 +591,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	set("editors/3d/emulate_3_button_mouse", false);
 	set("editors/3d/emulate_3_button_mouse", false);
 	set("editors/3d/warped_mouse_panning", true);
 	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_width", 5);
 	set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.9));
 	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));
 	set("editors/2d/bone_color2", Color(0.75, 0.75, 0.75, 0.9));

+ 112 - 119
editor/plugins/spatial_editor_plugin.cpp

@@ -58,20 +58,26 @@ void SpatialEditorViewport::_update_camera() {
 	} else
 	} else
 		camera->set_perspective(get_fov(), get_znear(), get_zfar());
 		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;
 	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)
 	if (orthogonal)
 		camera_transform.translate(0, 0, 4096);
 		camera_transform.translate(0, 0, 4096);
 	else
 	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 {
 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->add_item(spat->get_name());
 			selection_menu->set_item_icon(i, icon);
 			selection_menu->set_item_icon(i, icon);
 			selection_menu->set_item_metadata(i, node_path);
 			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));
 		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) {
 					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 (b.mod.alt) {
 
 
 							if (nav_scheme == NAVIGATION_MAYA)
 							if (nav_scheme == NAVIGATION_MAYA)
@@ -1344,6 +1279,8 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
 
 
 				if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
 				if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
 					nav_mode = NAVIGATION_ZOOM;
 					nav_mode = NAVIGATION_ZOOM;
+				} else {
+					nav_mode = NAVIGATION_LOOK;
 				}
 				}
 
 
 			} else if (m.button_mask & 4) {
 			} else if (m.button_mask & 4) {
@@ -1453,6 +1390,29 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
 					_update_name();
 					_update_name();
 				} break;
 				} 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: {}
 				default: {}
 			}
 			}
 		} break;
 		} 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) {
 void SpatialEditorViewport::set_message(String p_message, float p_time) {
 
 
 	message = p_message;
 	message = p_message;
@@ -1579,6 +1608,8 @@ void SpatialEditorViewport::_notification(int p_what) {
 		}
 		}
 		*/
 		*/
 
 
+		_update_freelook(get_tree()->get_idle_process_time());
+
 		_update_camera();
 		_update_camera();
 
 
 		Map<Node *, Object *> &selection = editor_selection->get_selection();
 		Map<Node *, Object *> &selection = editor_selection->get_selection();
@@ -2204,6 +2235,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
 	previewing = NULL;
 	previewing = NULL;
 	preview = NULL;
 	preview = NULL;
 	gizmo_scale = 1.0;
 	gizmo_scale = 1.0;
+	freelook_speed = 0;
 
 
 	selection_menu = memnew(PopupMenu);
 	selection_menu = memnew(PopupMenu);
 	add_child(selection_menu);
 	add_child(selection_menu);
@@ -3149,36 +3181,6 @@ void SpatialEditor::_finish_indicators() {
 	VisualServer::get_singleton()->free(cursor_mesh);
 	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) {
 void SpatialEditor::_unhandled_key_input(InputEvent p_event) {
 
 
 	if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
 	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_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons"));
 		tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_icon("ToolScale", "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"));
 		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_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"));
 		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("_node_removed", &SpatialEditor::_node_removed);
 	ClassDB::bind_method("_menu_item_pressed", &SpatialEditor::_menu_item_pressed);
 	ClassDB::bind_method("_menu_item_pressed", &SpatialEditor::_menu_item_pressed);
 	ClassDB::bind_method("_xform_dialog_action", &SpatialEditor::_xform_dialog_action);
 	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("_get_editor_data", &SpatialEditor::_get_editor_data);
 	ClassDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo);
 	ClassDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo);
 	ClassDB::bind_method("_default_light_angle_input", &SpatialEditor::_default_light_angle_input);
 	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]->connect("pressed", this, "_menu_item_pressed", button_binds);
 	tool_button[TOOL_MODE_SCALE]->set_tooltip(TTR("Scale Mode (R)"));
 	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);
 	VSeparator *vs = memnew(VSeparator);
 	hbc_menu->add_child(vs);
 	hbc_menu->add_child(vs);
 
 

+ 5 - 4
editor/plugins/spatial_editor_plugin.h

@@ -113,6 +113,7 @@ private:
 	bool transforming;
 	bool transforming;
 	bool orthogonal;
 	bool orthogonal;
 	float gizmo_scale;
 	float gizmo_scale;
+	real_t freelook_speed;
 
 
 	struct _RayResult {
 	struct _RayResult {
 
 
@@ -168,7 +169,8 @@ private:
 		NAVIGATION_NONE,
 		NAVIGATION_NONE,
 		NAVIGATION_PAN,
 		NAVIGATION_PAN,
 		NAVIGATION_ZOOM,
 		NAVIGATION_ZOOM,
-		NAVIGATION_ORBIT
+		NAVIGATION_ORBIT,
+		NAVIGATION_LOOK
 	};
 	};
 	enum TransformMode {
 	enum TransformMode {
 		TRANSFORM_NONE,
 		TRANSFORM_NONE,
@@ -203,8 +205,6 @@ private:
 
 
 	struct Cursor {
 	struct Cursor {
 
 
-		Vector3 cursor_pos;
-
 		Vector3 pos;
 		Vector3 pos;
 		float x_rot, y_rot, distance;
 		float x_rot, y_rot, distance;
 		bool region_select;
 		bool region_select;
@@ -227,10 +227,12 @@ private:
 
 
 	//
 	//
 	void _update_camera();
 	void _update_camera();
+	Transform to_camera_transform(const Cursor &p_cursor) const;
 	void _draw();
 	void _draw();
 
 
 	void _smouseenter();
 	void _smouseenter();
 	void _sinput(const InputEvent &p_ie);
 	void _sinput(const InputEvent &p_ie);
+	void _update_freelook(real_t delta);
 	SpatialEditor *spatial_editor;
 	SpatialEditor *spatial_editor;
 
 
 	Camera *previewing;
 	Camera *previewing;
@@ -385,7 +387,6 @@ private:
 	};
 	};
 
 
 	Button *tool_button[TOOL_MAX];
 	Button *tool_button[TOOL_MAX];
-	Button *instance_button;
 
 
 	MenuButton *transform_menu;
 	MenuButton *transform_menu;
 	MenuButton *view_menu;
 	MenuButton *view_menu;