1 /*************************************************************************/
2 /*  spatial_editor_plugin.h                                              */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #ifndef SPATIAL_EDITOR_PLUGIN_H
31 #define SPATIAL_EDITOR_PLUGIN_H
32 
33 #include "editor/editor_node.h"
34 #include "editor/editor_plugin.h"
35 #include "scene/3d/immediate_geometry.h"
36 #include "scene/3d/light.h"
37 #include "scene/3d/visual_instance.h"
38 #include "scene/gui/panel_container.h"
39 /**
40 	@author Juan Linietsky <reduzio@gmail.com>
41 */
42 
43 class Camera;
44 class SpatialEditor;
45 class SpatialEditorGizmos;
46 
47 class SpatialEditorGizmo : public SpatialGizmo {
48 
49 	OBJ_TYPE(SpatialEditorGizmo, SpatialGizmo);
50 
51 	bool selected;
52 
53 public:
set_selected(bool p_selected)54 	void set_selected(bool p_selected) { selected = p_selected; }
is_selected()55 	bool is_selected() const { return selected; }
56 
57 	virtual String get_handle_name(int p_idx) const;
58 	virtual Variant get_handle_value(int p_idx) const;
59 	virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point);
60 	virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false);
61 
62 	virtual bool intersect_frustum(const Camera *p_camera, const Vector<Plane> &p_frustum);
63 	virtual bool intersect_ray(const Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = NULL, bool p_sec_first = false);
64 	SpatialEditorGizmo();
65 };
66 
67 class SpatialEditorViewport : public Control {
68 
69 	OBJ_TYPE(SpatialEditorViewport, Control);
70 	friend class SpatialEditor;
71 	enum {
72 
73 		VIEW_TOP,
74 		VIEW_BOTTOM,
75 		VIEW_LEFT,
76 		VIEW_RIGHT,
77 		VIEW_FRONT,
78 		VIEW_REAR,
79 		VIEW_CENTER_TO_ORIGIN,
80 		VIEW_CENTER_TO_SELECTION,
81 		VIEW_ALIGN_SELECTION_WITH_VIEW,
82 		VIEW_PERSPECTIVE,
83 		VIEW_ENVIRONMENT,
84 		VIEW_ORTHOGONAL,
85 		VIEW_AUDIO_LISTENER,
86 		VIEW_GIZMOS,
87 		VIEW_FPS,
88 	};
89 
90 public:
91 	enum {
92 		GIZMO_BASE_LAYER = 27,
93 		GIZMO_EDIT_LAYER = 26,
94 		GIZMO_GRID_LAYER = 25
95 	};
96 
97 private:
98 	int index;
99 	String name;
100 	void _menu_option(int p_option);
101 	Size2 prev_size;
102 
103 	EditorNode *editor;
104 	EditorSelection *editor_selection;
105 	UndoRedo *undo_redo;
106 
107 	Button *preview_camera;
108 
109 	MenuButton *view_menu;
110 
111 	Control *surface;
112 	Viewport *viewport;
113 	Camera *camera;
114 	bool transforming;
115 	bool orthogonal;
116 	float gizmo_scale;
117 
118 	PanelContainer *fps;
119 	Label *fps_label;
120 
121 	struct _RayResult {
122 
123 		Spatial *item;
124 		float depth;
125 		int handle;
126 		_FORCE_INLINE_ bool operator<(const _RayResult &p_rr) const { return depth < p_rr.depth; }
127 	};
128 
129 	void _update_name();
130 	void _compute_edit(const Point2 &p_point);
131 	void _clear_selected();
132 	void _select_clicked(bool p_append, bool p_single);
133 	void _select(Spatial *p_node, bool p_append, bool p_single);
134 	ObjectID _select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle = NULL, bool p_alt_select = false);
135 	void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false);
136 	Vector3 _get_ray_pos(const Vector2 &p_pos) const;
137 	Vector3 _get_ray(const Vector2 &p_pos);
138 	Point2 _point_to_screen(const Vector3 &p_point);
139 	Transform _get_camera_transform() const;
140 	int get_selected_count() const;
141 
142 	Vector3 _get_camera_pos() const;
143 	Vector3 _get_camera_normal() const;
144 	Vector3 _get_screen_to_space(const Vector3 &p_vector3);
145 
146 	void _select_region();
147 	bool _gizmo_select(const Vector2 &p_screenpos, bool p_hilite_only = false);
148 
149 	float get_znear() const;
150 	float get_zfar() const;
151 	float get_fov() const;
152 
153 	ObjectID clicked;
154 	Vector<_RayResult> selection_results;
155 	bool clicked_includes_current;
156 	bool clicked_wants_append;
157 
158 	PopupMenu *selection_menu;
159 
160 	enum NavigationScheme {
161 		NAVIGATION_GODOT,
162 		NAVIGATION_MAYA,
163 		NAVIGATION_MODO,
164 	};
165 	NavigationScheme _get_navigation_schema(const String &p_property);
166 
167 	enum NavigationZoomStyle {
168 		NAVIGATION_ZOOM_VERTICAL,
169 		NAVIGATION_ZOOM_HORIZONTAL
170 	};
171 	NavigationZoomStyle _get_navigation_zoom_style(const String &p_property);
172 
173 	enum NavigationMode {
174 		NAVIGATION_NONE,
175 		NAVIGATION_PAN,
176 		NAVIGATION_ZOOM,
177 		NAVIGATION_ORBIT
178 	};
179 	enum TransformMode {
180 		TRANSFORM_NONE,
181 		TRANSFORM_ROTATE,
182 		TRANSFORM_TRANSLATE,
183 		TRANSFORM_SCALE
184 
185 	};
186 	enum TransformPlane {
187 		TRANSFORM_VIEW,
188 		TRANSFORM_X_AXIS,
189 		TRANSFORM_Y_AXIS,
190 		TRANSFORM_Z_AXIS,
191 	};
192 
193 	struct EditData {
194 		TransformMode mode;
195 		TransformPlane plane;
196 		Transform original;
197 		Vector3 click_ray;
198 		Vector3 click_ray_pos;
199 		Vector3 center;
200 		Vector3 orig_gizmo_pos;
201 		int edited_gizmo;
202 		Point2 mouse_pos;
203 		bool snap;
204 		Ref<SpatialEditorGizmo> gizmo;
205 		int gizmo_handle;
206 		Variant gizmo_initial_value;
207 		Vector3 gizmo_initial_pos;
208 	} _edit;
209 
210 	struct Cursor {
211 
212 		Vector3 cursor_pos;
213 
214 		Vector3 pos;
215 		float x_rot, y_rot, distance;
216 		bool region_select;
217 		Point2 region_begin, region_end;
218 
CursorCursor219 		Cursor() {
220 			x_rot = y_rot = 0.5;
221 			distance = 4;
222 			region_select = false;
223 		}
224 	} cursor;
225 
226 	RID move_gizmo_instance[3], rotate_gizmo_instance[3];
227 
228 	String last_message;
229 	String message;
230 	float message_time;
231 
232 	void set_message(String p_message, float p_time = 5);
233 
234 	//
235 	void _update_camera();
236 	void _draw();
237 
238 	void _smouseenter();
239 	void _sinput(const InputEvent &p_ie);
240 	SpatialEditor *spatial_editor;
241 
242 	Camera *previewing;
243 	Camera *preview;
244 
245 	void _preview_exited_scene();
246 	void _toggle_camera_preview(bool);
247 	void _init_gizmo_instance(int p_idx);
248 	void _finish_gizmo_instances();
249 	void _selection_result_pressed(int);
250 	void _selection_menu_hide();
251 	void _list_select(InputEventMouseButton b);
252 
253 protected:
254 	void _notification(int p_what);
255 	static void _bind_methods();
256 
257 public:
258 	void update_transform_gizmo_view();
259 
260 	void set_can_preview(Camera *p_preview);
261 	void set_state(const Dictionary &p_state);
262 	Dictionary get_state() const;
263 	void reset();
get_viewport_node()264 	Viewport *get_viewport_node() { return viewport; }
265 
266 	SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index);
267 };
268 
269 class SpatialEditorSelectedItem : public Object {
270 
271 	OBJ_TYPE(SpatialEditorSelectedItem, Object);
272 
273 public:
274 	AABB aabb;
275 	Transform original; // original location when moving
276 	Transform last_xform; // last transform
277 	Spatial *sp;
278 	RID sbox_instance;
279 
SpatialEditorSelectedItem()280 	SpatialEditorSelectedItem() { sp = NULL; }
281 	~SpatialEditorSelectedItem();
282 };
283 
284 class SpatialEditor : public VBoxContainer {
285 
286 	OBJ_TYPE(SpatialEditor, VBoxContainer);
287 
288 public:
289 	enum ToolMode {
290 
291 		TOOL_MODE_SELECT,
292 		TOOL_MODE_MOVE,
293 		TOOL_MODE_ROTATE,
294 		TOOL_MODE_SCALE,
295 		TOOL_MODE_LIST_SELECT,
296 		TOOL_MAX
297 
298 	};
299 
300 private:
301 	EditorNode *editor;
302 	EditorSelection *editor_selection;
303 
304 	Control *viewport_base;
305 	SpatialEditorViewport *viewports[4];
306 	VSplitContainer *shader_split;
307 	HSplitContainer *palette_split;
308 
309 	/////
310 
311 	ToolMode tool_mode;
312 	bool orthogonal;
313 
314 	VisualServer::ScenarioDebugMode scenario_debug;
315 
316 	RID light;
317 	RID light_instance;
318 	Transform light_transform;
319 
320 	RID origin;
321 	RID origin_instance;
322 	RID grid[3];
323 	RID grid_instance[3];
324 	bool grid_visible[3]; //currently visible
325 	float last_grid_snap;
326 	bool grid_enable[3]; //should be always visible if true
327 	bool grid_enabled;
328 
329 	Ref<Mesh> move_gizmo[3], rotate_gizmo[3];
330 	Ref<FixedMaterial> gizmo_color[3];
331 	Ref<FixedMaterial> gizmo_hl;
332 
333 	int over_gizmo_handle;
334 
335 	Ref<Mesh> selection_box;
336 	RID indicators;
337 	RID indicators_instance;
338 	RID cursor_mesh;
339 	RID cursor_instance;
340 	RID indicator_mat;
341 	RID cursor_material;
342 
343 	/*
344 	struct Selected {
345 		AABB aabb;
346 		Transform original; // original location when moving
347 		Transform last_xform; // last transform
348 		Spatial *sp;
349 		RID poly_instance;
350 	};
351 
352 	Map<uint32_t,Selected> selected;
353 */
354 	struct Gizmo {
355 
356 		bool visible;
357 		float scale;
358 		Transform transform;
359 	} gizmo;
360 
361 	enum MenuOption {
362 
363 		MENU_TOOL_SELECT,
364 		MENU_TOOL_MOVE,
365 		MENU_TOOL_ROTATE,
366 		MENU_TOOL_SCALE,
367 		MENU_TOOL_LIST_SELECT,
368 		MENU_TRANSFORM_USE_SNAP,
369 		MENU_TRANSFORM_CONFIGURE_SNAP,
370 		MENU_TRANSFORM_LOCAL_COORDS,
371 		MENU_TRANSFORM_DIALOG,
372 		MENU_VIEW_USE_1_VIEWPORT,
373 		MENU_VIEW_USE_2_VIEWPORTS,
374 		MENU_VIEW_USE_2_VIEWPORTS_ALT,
375 		MENU_VIEW_USE_3_VIEWPORTS,
376 		MENU_VIEW_USE_3_VIEWPORTS_ALT,
377 		MENU_VIEW_USE_4_VIEWPORTS,
378 		MENU_VIEW_USE_DEFAULT_LIGHT,
379 		MENU_VIEW_USE_DEFAULT_SRGB,
380 		MENU_VIEW_DISPLAY_NORMAL,
381 		MENU_VIEW_DISPLAY_WIREFRAME,
382 		MENU_VIEW_DISPLAY_OVERDRAW,
383 		MENU_VIEW_DISPLAY_SHADELESS,
384 		MENU_VIEW_ORIGIN,
385 		MENU_VIEW_GRID,
386 		MENU_VIEW_CAMERA_SETTINGS,
387 
388 	};
389 
390 	Button *tool_button[TOOL_MAX];
391 	Button *instance_button;
392 
393 	MenuButton *transform_menu;
394 	MenuButton *view_menu;
395 
396 	ConfirmationDialog *snap_dialog;
397 	ConfirmationDialog *xform_dialog;
398 	ConfirmationDialog *settings_dialog;
399 
400 	bool snap_enabled;
401 	LineEdit *snap_translate;
402 	LineEdit *snap_rotate;
403 	LineEdit *snap_scale;
404 	PanelContainer *menu_panel;
405 
406 	LineEdit *xform_translate[3];
407 	LineEdit *xform_rotate[3];
408 	LineEdit *xform_scale[3];
409 	OptionButton *xform_type;
410 
411 	VBoxContainer *settings_vbc;
412 	SpinBox *settings_fov;
413 	SpinBox *settings_znear;
414 	SpinBox *settings_zfar;
415 	DirectionalLight *settings_dlight;
416 	ImmediateGeometry *settings_sphere;
417 	Camera *settings_camera;
418 	float settings_default_light_rot_x;
419 	float settings_default_light_rot_y;
420 
421 	Control *settings_light_base;
422 	Viewport *settings_light_vp;
423 	ColorPickerButton *settings_ambient_color;
424 	Image settings_light_dir_image;
425 
426 	void _xform_dialog_action();
427 	void _menu_item_pressed(int p_option);
428 
429 	HBoxContainer *hbc_menu;
430 
431 	//
432 	//
433 	void _generate_selection_box();
434 	UndoRedo *undo_redo;
435 
436 	void _instance_scene();
437 	void _init_indicators();
438 	void _finish_indicators();
439 
440 	void _toggle_maximize_view(Object *p_viewport);
441 
442 	Node *custom_camera;
443 
444 	Object *_get_editor_data(Object *p_what);
445 
446 	Ref<Environment> viewport_environment;
447 
448 	Spatial *selected;
449 
450 	void _request_gizmo(Object *p_obj);
451 
452 	static SpatialEditor *singleton;
453 
454 	void _node_removed(Node *p_node);
455 	SpatialEditorGizmos *gizmos;
456 	SpatialEditor();
457 
458 	void _update_ambient_light_color(const Color &p_color);
459 	void _update_default_light_angle();
460 	void _default_light_angle_input(const InputEvent &p_event);
461 
462 protected:
463 	void _notification(int p_what);
464 	//void _input_event(InputEvent p_event);
465 	void _unhandled_key_input(InputEvent p_event);
466 
467 	static void _bind_methods();
468 
469 public:
get_singleton()470 	static SpatialEditor *get_singleton() { return singleton; }
471 	void snap_cursor_to_plane(const Plane &p_plane);
472 
get_znear()473 	float get_znear() const { return settings_znear->get_val(); }
get_zfar()474 	float get_zfar() const { return settings_zfar->get_val(); }
get_fov()475 	float get_fov() const { return settings_fov->get_val(); }
476 
get_gizmo_transform()477 	Transform get_gizmo_transform() const { return gizmo.transform; }
is_gizmo_visible()478 	bool is_gizmo_visible() const { return gizmo.visible; }
479 
get_tool_mode()480 	ToolMode get_tool_mode() const { return tool_mode; }
is_snap_enabled()481 	bool is_snap_enabled() const { return snap_enabled; }
get_translate_snap()482 	float get_translate_snap() const { return snap_translate->get_text().to_double(); }
get_rotate_snap()483 	float get_rotate_snap() const { return snap_rotate->get_text().to_double(); }
get_scale_snap()484 	float get_scale_snap() const { return snap_scale->get_text().to_double(); }
485 
get_move_gizmo(int idx)486 	Ref<Mesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }
get_rotate_gizmo(int idx)487 	Ref<Mesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; }
488 
489 	void update_transform_gizmo();
490 
491 	void select_gizmo_highlight_axis(int p_axis);
set_custom_camera(Node * p_camera)492 	void set_custom_camera(Node *p_camera) { custom_camera = p_camera; }
493 
set_undo_redo(UndoRedo * p_undo_redo)494 	void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
495 	Dictionary get_state() const;
496 	void set_state(const Dictionary &p_state);
497 
get_viewport_environment()498 	Ref<Environment> get_viewport_environment() { return viewport_environment; }
499 
get_undo_redo()500 	UndoRedo *get_undo_redo() { return undo_redo; }
501 
502 	void add_control_to_menu_panel(Control *p_control);
503 
504 	VSplitContainer *get_shader_split();
505 	HSplitContainer *get_palette_split();
506 
get_selected()507 	Spatial *get_selected() { return selected; }
508 
get_over_gizmo_handle()509 	int get_over_gizmo_handle() const { return over_gizmo_handle; }
set_over_gizmo_handle(int idx)510 	void set_over_gizmo_handle(int idx) { over_gizmo_handle = idx; }
511 
512 	void set_can_preview(Camera *p_preview);
513 
get_editor_viewport(int p_idx)514 	SpatialEditorViewport *get_editor_viewport(int p_idx) {
515 		ERR_FAIL_INDEX_V(p_idx, 4, NULL);
516 		return viewports[p_idx];
517 	}
518 
get_camera()519 	Camera *get_camera() { return NULL; }
520 	void edit(Spatial *p_spatial);
521 	void clear();
522 	SpatialEditor(EditorNode *p_editor);
523 	~SpatialEditor();
524 };
525 
526 class SpatialEditorPlugin : public EditorPlugin {
527 
528 	OBJ_TYPE(SpatialEditorPlugin, EditorPlugin);
529 
530 	SpatialEditor *spatial_editor;
531 	EditorNode *editor;
532 
533 protected:
534 	static void _bind_methods();
535 
536 public:
537 	void snap_cursor_to_plane(const Plane &p_plane);
538 
get_spatial_editor()539 	SpatialEditor *get_spatial_editor() { return spatial_editor; }
get_name()540 	virtual String get_name() const { return "3D"; }
has_main_screen()541 	bool has_main_screen() const { return true; }
542 	virtual void make_visible(bool p_visible);
543 	virtual void edit(Object *p_object);
544 	virtual bool handles(Object *p_object) const;
545 
546 	virtual Dictionary get_state() const;
547 	virtual void set_state(const Dictionary &p_state);
clear()548 	virtual void clear() { spatial_editor->clear(); }
549 
550 	SpatialEditorPlugin(EditorNode *p_node);
551 	~SpatialEditorPlugin();
552 };
553 
554 #endif
555