Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/scene/3d/node_3d_editor_plugin.h
21102 views
1
/**************************************************************************/
2
/* node_3d_editor_plugin.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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
31
#pragma once
32
33
#include "core/math/dynamic_bvh.h"
34
#include "editor/plugins/editor_plugin.h"
35
#include "editor/scene/3d/node_3d_editor_gizmos.h"
36
#include "editor/themes/editor_scale.h"
37
#include "scene/gui/box_container.h"
38
#include "scene/gui/button.h"
39
#include "scene/gui/spin_box.h"
40
#include "scene/resources/gradient.h"
41
#include "scene/resources/immediate_mesh.h"
42
43
class AcceptDialog;
44
class CheckBox;
45
class ColorPickerButton;
46
class ConfirmationDialog;
47
class DirectionalLight3D;
48
class EditorData;
49
class EditorSelection;
50
class EditorSpinSlider;
51
class HSplitContainer;
52
class LineEdit;
53
class MenuButton;
54
class Node3DEditor;
55
class Node3DEditorViewport;
56
class OptionButton;
57
class PanelContainer;
58
class ProceduralSkyMaterial;
59
class SubViewport;
60
class SubViewportContainer;
61
class VSeparator;
62
class VSplitContainer;
63
class ViewportNavigationControl;
64
class WorldEnvironment;
65
class MeshInstance3D;
66
67
class ViewportRotationControl : public Control {
68
GDCLASS(ViewportRotationControl, Control);
69
70
struct Axis2D {
71
Vector2 screen_point;
72
float z_axis = -99.0;
73
int axis = -1;
74
bool is_positive = true;
75
};
76
77
struct Axis2DCompare {
78
_FORCE_INLINE_ bool operator()(const Axis2D &l, const Axis2D &r) const {
79
return l.z_axis < r.z_axis;
80
}
81
};
82
83
Node3DEditorViewport *viewport = nullptr;
84
Vector<Color> axis_colors;
85
Vector<int> axis_menu_options;
86
Vector2i orbiting_mouse_start;
87
Point2 original_mouse_pos;
88
int orbiting_index = -1;
89
int focused_axis = -2;
90
bool gizmo_activated = false;
91
92
const float AXIS_CIRCLE_RADIUS = 8.0f * EDSCALE;
93
94
protected:
95
void _notification(int p_what);
96
virtual void gui_input(const Ref<InputEvent> &p_event) override;
97
void _draw();
98
void _draw_axis(const Axis2D &p_axis);
99
void _get_sorted_axis(Vector<Axis2D> &r_axis);
100
void _update_focus();
101
void _process_click(int p_index, Vector2 p_position, bool p_pressed);
102
void _process_drag(Ref<InputEventWithModifiers> p_event, int p_index, Vector2 p_position, Vector2 p_relative_position);
103
104
public:
105
void set_viewport(Node3DEditorViewport *p_viewport);
106
};
107
108
class Node3DEditorViewport : public Control {
109
GDCLASS(Node3DEditorViewport, Control);
110
friend class Node3DEditor;
111
friend class ViewportNavigationControl;
112
friend class ViewportRotationControl;
113
enum {
114
VIEW_TOP,
115
VIEW_BOTTOM,
116
VIEW_LEFT,
117
VIEW_RIGHT,
118
VIEW_FRONT,
119
VIEW_REAR,
120
VIEW_CENTER_TO_ORIGIN,
121
VIEW_CENTER_TO_SELECTION,
122
VIEW_ALIGN_TRANSFORM_WITH_VIEW,
123
VIEW_ALIGN_ROTATION_WITH_VIEW,
124
VIEW_PERSPECTIVE,
125
VIEW_ENVIRONMENT,
126
VIEW_ORTHOGONAL,
127
VIEW_SWITCH_PERSPECTIVE_ORTHOGONAL,
128
VIEW_HALF_RESOLUTION,
129
VIEW_AUDIO_LISTENER,
130
VIEW_AUDIO_DOPPLER,
131
VIEW_GIZMOS,
132
VIEW_TRANSFORM_GIZMO,
133
VIEW_GRID,
134
VIEW_INFORMATION,
135
VIEW_FRAME_TIME,
136
137
// < Keep in sync with menu.
138
VIEW_DISPLAY_NORMAL,
139
VIEW_DISPLAY_WIREFRAME,
140
VIEW_DISPLAY_OVERDRAW,
141
VIEW_DISPLAY_LIGHTING,
142
VIEW_DISPLAY_UNSHADED,
143
VIEW_DISPLAY_ADVANCED,
144
// Advanced menu:
145
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
146
VIEW_DISPLAY_NORMAL_BUFFER,
147
VIEW_DISPLAY_DEBUG_SHADOW_ATLAS,
148
VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS,
149
VIEW_DISPLAY_DEBUG_DECAL_ATLAS,
150
VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO,
151
VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING,
152
VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION,
153
VIEW_DISPLAY_DEBUG_SDFGI,
154
VIEW_DISPLAY_DEBUG_SDFGI_PROBES,
155
VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
156
VIEW_DISPLAY_DEBUG_SSAO,
157
VIEW_DISPLAY_DEBUG_SSIL,
158
VIEW_DISPLAY_DEBUG_GI_BUFFER,
159
VIEW_DISPLAY_DEBUG_DISABLE_LOD,
160
VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS,
161
VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS,
162
VIEW_DISPLAY_DEBUG_CLUSTER_DECALS,
163
VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES,
164
VIEW_DISPLAY_DEBUG_OCCLUDERS,
165
VIEW_DISPLAY_MOTION_VECTORS,
166
VIEW_DISPLAY_INTERNAL_BUFFER,
167
VIEW_DISPLAY_MAX,
168
// > Keep in sync with menu.
169
170
VIEW_LOCK_ROTATION,
171
VIEW_CINEMATIC_PREVIEW,
172
VIEW_AUTO_ORTHOGONAL,
173
VIEW_MAX
174
};
175
176
enum ViewType {
177
VIEW_TYPE_USER,
178
VIEW_TYPE_TOP,
179
VIEW_TYPE_BOTTOM,
180
VIEW_TYPE_LEFT,
181
VIEW_TYPE_RIGHT,
182
VIEW_TYPE_FRONT,
183
VIEW_TYPE_REAR,
184
};
185
186
public:
187
static constexpr int32_t GIZMO_BASE_LAYER = 27;
188
static constexpr int32_t GIZMO_EDIT_LAYER = 26;
189
static constexpr int32_t GIZMO_GRID_LAYER = 25;
190
static constexpr int32_t MISC_TOOL_LAYER = 24;
191
192
static constexpr int32_t FRAME_TIME_HISTORY = 20;
193
194
enum NavigationScheme {
195
NAVIGATION_GODOT = 0,
196
NAVIGATION_MAYA = 1,
197
NAVIGATION_MODO = 2,
198
NAVIGATION_CUSTOM = 3,
199
NAVIGATION_TABLET = 4,
200
};
201
202
enum FreelookNavigationScheme {
203
FREELOOK_DEFAULT,
204
FREELOOK_PARTIALLY_AXIS_LOCKED,
205
FREELOOK_FULLY_AXIS_LOCKED,
206
};
207
208
enum ViewportNavMouseButton {
209
NAVIGATION_LEFT_MOUSE,
210
NAVIGATION_MIDDLE_MOUSE,
211
NAVIGATION_RIGHT_MOUSE,
212
NAVIGATION_MOUSE_4,
213
NAVIGATION_MOUSE_5,
214
};
215
216
private:
217
double cpu_time_history[FRAME_TIME_HISTORY];
218
int cpu_time_history_index;
219
double gpu_time_history[FRAME_TIME_HISTORY];
220
int gpu_time_history_index;
221
222
Node *ruler = nullptr;
223
Node3D *ruler_start_point = nullptr;
224
Node3D *ruler_end_point = nullptr;
225
Ref<ImmediateMesh> geometry;
226
MeshInstance3D *ruler_line = nullptr;
227
MeshInstance3D *ruler_line_xray = nullptr;
228
Label *ruler_label = nullptr;
229
Ref<StandardMaterial3D> ruler_material;
230
Ref<StandardMaterial3D> ruler_material_xray;
231
232
int index;
233
ViewType view_type;
234
void _menu_option(int p_option);
235
void _set_auto_orthogonal();
236
Node3D *preview_node = nullptr;
237
bool update_preview_node = false;
238
Point2 preview_node_viewport_pos;
239
Vector3 preview_node_pos;
240
AABB *preview_bounds = nullptr;
241
Vector<String> selected_files;
242
AcceptDialog *accept = nullptr;
243
244
Node *target_node = nullptr;
245
Point2 drop_pos;
246
247
EditorSelection *editor_selection = nullptr;
248
249
Button *translation_preview_button = nullptr;
250
CheckBox *preview_camera = nullptr;
251
SubViewportContainer *subviewport_container = nullptr;
252
253
MenuButton *view_display_menu = nullptr;
254
PopupMenu *display_submenu = nullptr;
255
256
Control *surface = nullptr;
257
SubViewport *viewport = nullptr;
258
Camera3D *camera = nullptr;
259
bool transforming = false;
260
bool orthogonal;
261
bool auto_orthogonal;
262
bool lock_rotation;
263
bool transform_gizmo_visible = true;
264
bool collision_reposition = false;
265
real_t gizmo_scale;
266
267
bool freelook_active;
268
real_t freelook_speed;
269
Vector2 previous_mouse_position;
270
271
PanelContainer *info_panel = nullptr;
272
Label *info_label = nullptr;
273
Label *cinema_label = nullptr;
274
Label *locked_label = nullptr;
275
Label *zoom_limit_label = nullptr;
276
277
Label *preview_material_label = nullptr;
278
Label *preview_material_label_desc = nullptr;
279
280
VBoxContainer *top_right_vbox = nullptr;
281
VBoxContainer *bottom_center_vbox = nullptr;
282
ViewportNavigationControl *position_control = nullptr;
283
ViewportNavigationControl *look_control = nullptr;
284
ViewportRotationControl *rotation_control = nullptr;
285
Gradient *frame_time_gradient = nullptr;
286
PanelContainer *frame_time_panel = nullptr;
287
VBoxContainer *frame_time_vbox = nullptr;
288
Label *cpu_time_label = nullptr;
289
Label *gpu_time_label = nullptr;
290
Label *fps_label = nullptr;
291
292
struct _RayResult {
293
Node3D *item = nullptr;
294
real_t depth = 0;
295
_FORCE_INLINE_ bool operator<(const _RayResult &p_rr) const { return depth < p_rr.depth; }
296
};
297
298
void _update_name();
299
void _compute_edit(const Point2 &p_point);
300
void _clear_selected();
301
bool _is_rotation_arc_visible() const;
302
void _select_clicked(bool p_allow_locked);
303
ObjectID _select_ray(const Point2 &p_pos) const;
304
void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked);
305
306
Transform3D _get_camera_transform() const;
307
int get_selected_count() const;
308
void cancel_transform();
309
void _update_shrink();
310
311
Vector3 _get_camera_position() const;
312
Vector3 _get_camera_normal() const;
313
Vector3 _get_screen_to_space(const Vector3 &p_vector3);
314
315
void _select_region();
316
bool _transform_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only = false);
317
void _transform_gizmo_apply(Node3D *p_node, const Transform3D &p_transform, bool p_local);
318
319
void _nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
320
void _nav_zoom(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
321
void _nav_orbit(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
322
void _nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
323
324
bool _is_shortcut_empty(const String &p_name);
325
bool _is_nav_modifier_pressed(const String &p_name);
326
int _get_shortcut_input_count(const String &p_name);
327
328
float get_znear() const;
329
float get_zfar() const;
330
float get_fov() const;
331
332
ObjectID clicked;
333
ObjectID material_target;
334
Vector<Node3D *> selection_results;
335
Vector<Node3D *> selection_results_menu;
336
bool clicked_wants_append = false;
337
bool selection_in_progress = false;
338
bool movement_threshold_passed = false;
339
340
PopupMenu *selection_menu = nullptr;
341
342
enum NavigationZoomStyle {
343
NAVIGATION_ZOOM_VERTICAL,
344
NAVIGATION_ZOOM_HORIZONTAL
345
};
346
347
enum NavigationMode {
348
NAVIGATION_NONE,
349
NAVIGATION_PAN,
350
NAVIGATION_ZOOM,
351
NAVIGATION_ORBIT,
352
NAVIGATION_LOOK,
353
NAVIGATION_MOVE
354
};
355
enum TransformMode {
356
TRANSFORM_NONE,
357
TRANSFORM_ROTATE,
358
TRANSFORM_TRANSLATE,
359
TRANSFORM_SCALE
360
};
361
enum TransformPlane {
362
TRANSFORM_VIEW,
363
TRANSFORM_X_AXIS,
364
TRANSFORM_Y_AXIS,
365
TRANSFORM_Z_AXIS,
366
TRANSFORM_YZ,
367
TRANSFORM_XZ,
368
TRANSFORM_XY,
369
};
370
enum TransformType {
371
POSITION,
372
ROTATION,
373
SCALE,
374
};
375
376
struct EditData {
377
TransformMode mode;
378
TransformPlane plane;
379
Transform3D original;
380
Vector3 click_ray;
381
Vector3 click_ray_pos;
382
Vector3 center;
383
Point2 mouse_pos;
384
Point2 original_mouse_pos;
385
bool snap = false;
386
bool show_rotation_line = false;
387
bool is_trackball = false;
388
Ref<EditorNode3DGizmo> gizmo;
389
int gizmo_handle = 0;
390
bool gizmo_handle_secondary = false;
391
Variant gizmo_initial_value;
392
bool original_local;
393
bool instant;
394
395
// Numeric blender-style transforms (e.g. 'g5x').
396
// numeric_input tracks the current input value, e.g. 1.23.
397
// numeric_negate indicates whether '-' has been pressed to negate the value
398
// while numeric_next_decimal is 0, numbers are input before the decimal point
399
// after pressing '.', numeric next decimal changes to -1, and decrements after each press.
400
double numeric_input = 0.0;
401
bool numeric_negate = false;
402
int numeric_next_decimal = 0;
403
404
Vector3 rotation_axis;
405
Vector3 view_axis_local;
406
double accumulated_rotation_angle = 0.0;
407
double display_rotation_angle = 0.0;
408
Vector3 initial_click_vector;
409
Vector3 previous_rotation_vector;
410
bool gizmo_initiated = false;
411
} _edit;
412
413
struct Cursor {
414
Vector3 pos;
415
real_t x_rot, y_rot, distance, fov_scale;
416
real_t unsnapped_x_rot, unsnapped_y_rot;
417
Vector3 eye_pos; // Used in freelook mode
418
bool region_select;
419
Point2 region_begin, region_end;
420
421
Cursor() {
422
// These rotations place the camera in +X +Y +Z, aka south east, facing north west.
423
x_rot = 0.5;
424
y_rot = -0.5;
425
unsnapped_x_rot = x_rot;
426
unsnapped_y_rot = y_rot;
427
distance = 4;
428
fov_scale = 1.0;
429
region_select = false;
430
}
431
};
432
// Viewport camera supports movement smoothing,
433
// so one cursor is the real cursor, while the other can be an interpolated version.
434
Cursor cursor; // Immediate cursor
435
Cursor camera_cursor; // That one may be interpolated (don't modify this one except for smoothing purposes)
436
Cursor previous_cursor; // Storing previous cursor state for canceling purposes
437
438
void scale_fov(real_t p_fov_offset);
439
void reset_fov();
440
void scale_cursor_distance(real_t scale);
441
442
struct ShortcutCheckSet {
443
bool mod_pressed = false;
444
bool shortcut_not_empty = true;
445
int input_count = 0;
446
ViewportNavMouseButton mouse_preference = NAVIGATION_LEFT_MOUSE;
447
NavigationMode result_nav_mode = NAVIGATION_NONE;
448
449
ShortcutCheckSet() {}
450
451
ShortcutCheckSet(bool p_mod_pressed, bool p_shortcut_not_empty, int p_input_count, const ViewportNavMouseButton &p_mouse_preference, const NavigationMode &p_result_nav_mode) :
452
mod_pressed(p_mod_pressed), shortcut_not_empty(p_shortcut_not_empty), input_count(p_input_count), mouse_preference(p_mouse_preference), result_nav_mode(p_result_nav_mode) {
453
}
454
};
455
456
struct ShortcutCheckSetComparator {
457
_FORCE_INLINE_ bool operator()(const ShortcutCheckSet &A, const ShortcutCheckSet &B) const {
458
return A.input_count > B.input_count;
459
}
460
};
461
462
NavigationMode _get_nav_mode_from_shortcut_check(ViewportNavMouseButton p_mouse_button, Vector<ShortcutCheckSet> p_shortcut_check_sets, bool p_use_not_empty);
463
464
void set_freelook_active(bool active_now);
465
void scale_freelook_speed(real_t scale);
466
467
real_t zoom_indicator_delay;
468
int zoom_failed_attempts_count = 0;
469
470
RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[4], scale_gizmo_instance[3], scale_plane_gizmo_instance[3], axis_gizmo_instance[3];
471
RID trackball_sphere_instance;
472
473
String last_message;
474
String message;
475
double message_time;
476
477
void set_message(const String &p_message, float p_time = 5);
478
479
void _view_settings_confirmed(real_t p_interp_delta);
480
void _update_camera(real_t p_interp_delta);
481
void _update_navigation_controls_visibility();
482
Transform3D to_camera_transform(const Cursor &p_cursor) const;
483
void _draw();
484
485
// These allow tool scripts to set the 3D cursor location by updating the camera transform.
486
Transform3D last_camera_transform;
487
bool _camera_moved_externally();
488
void _apply_camera_transform_to_cursor();
489
490
void _surface_mouse_enter();
491
void _surface_mouse_exit();
492
void _surface_focus_enter();
493
void _surface_focus_exit();
494
495
void input(const Ref<InputEvent> &p_event) override;
496
void _sinput(const Ref<InputEvent> &p_event);
497
void _update_freelook(real_t delta);
498
Node3DEditor *spatial_editor = nullptr;
499
500
Camera3D *previewing = nullptr;
501
Camera3D *preview = nullptr;
502
503
bool previewing_camera = false;
504
bool previewing_cinema = false;
505
bool _is_node_locked(const Node *p_node) const;
506
void _preview_exited_scene();
507
void _preview_camera_property_changed();
508
void _update_centered_labels();
509
void _toggle_camera_preview(bool);
510
void _toggle_cinema_preview(bool);
511
void _init_gizmo_instance(int p_idx);
512
void _finish_gizmo_instances();
513
void _selection_result_pressed(int);
514
void _selection_menu_hide();
515
void _list_select(Ref<InputEventMouseButton> b);
516
Point2 _get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const;
517
518
Vector3 _get_instance_position(const Point2 &p_pos, Node3D *p_node) const;
519
static AABB _calculate_spatial_bounds(const Node3D *p_parent, bool p_omit_top_level = false, const Transform3D *p_bounds_orientation = nullptr);
520
521
Node *_sanitize_preview_node(Node *p_node) const;
522
523
void _create_preview_node(const Vector<String> &files) const;
524
void _remove_preview_node();
525
bool _apply_preview_material(ObjectID p_target, const Point2 &p_point) const;
526
void _reset_preview_material() const;
527
void _remove_preview_material();
528
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) const;
529
bool _create_instance(Node *p_parent, const String &p_path, const Point2 &p_point);
530
bool _create_audio_node(Node *p_parent, const String &p_path, const Point2 &p_point);
531
void _perform_drop_data();
532
533
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
534
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
535
536
void _project_settings_changed();
537
538
Transform3D _compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local, bool p_orthogonal, bool p_view_axis);
539
540
void _reset_transform(TransformType p_type);
541
542
void begin_transform(TransformMode p_mode, bool instant);
543
void commit_transform();
544
void apply_transform(Vector3 p_motion, double p_snap);
545
void update_transform(bool p_shift);
546
void update_transform_numeric();
547
void finish_transform();
548
549
void register_shortcut_action(const String &p_path, const String &p_name, Key p_keycode, bool p_physical = false);
550
void shortcut_changed_callback(const Ref<Shortcut> p_shortcut, const String &p_shortcut_path);
551
552
// Supported rendering methods for advanced debug draw mode items.
553
enum SupportedRenderingMethods {
554
ALL,
555
FORWARD_PLUS,
556
FORWARD_PLUS_MOBILE,
557
};
558
559
void _set_lock_view_rotation(bool p_lock_rotation);
560
void _add_advanced_debug_draw_mode_item(PopupMenu *p_popup, const String &p_name, int p_value, SupportedRenderingMethods p_rendering_methods = SupportedRenderingMethods::ALL, const String &p_tooltip = "");
561
562
protected:
563
void _notification(int p_what);
564
static void _bind_methods();
565
566
public:
567
void update_surface() { surface->queue_redraw(); }
568
void update_transform_gizmo_view();
569
570
void set_can_preview(Camera3D *p_preview);
571
void set_state(const Dictionary &p_state);
572
Dictionary get_state() const;
573
void reset();
574
bool is_freelook_active() const { return freelook_active; }
575
576
Vector3 get_ray_pos(const Vector2 &p_pos) const;
577
Vector3 get_ray(const Vector2 &p_pos) const;
578
Point2 point_to_screen(const Vector3 &p_point);
579
580
void focus_selection();
581
582
void assign_pending_data_pointers(
583
Node3D *p_preview_node,
584
AABB *p_preview_bounds,
585
AcceptDialog *p_accept);
586
587
SubViewport *get_viewport_node() { return viewport; }
588
Camera3D *get_camera_3d() { return camera; } // return the default camera object.
589
Control *get_surface() { return surface; }
590
591
Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p_index);
592
~Node3DEditorViewport();
593
};
594
595
class Node3DEditorSelectedItem : public Object {
596
GDCLASS(Node3DEditorSelectedItem, Object);
597
598
public:
599
AABB aabb;
600
Transform3D original; // original location when moving
601
Transform3D original_local;
602
Transform3D last_xform; // last transform
603
bool last_xform_dirty;
604
Node3D *sp = nullptr;
605
RID sbox_instance;
606
RID sbox_instance_offset;
607
RID sbox_instance_xray;
608
RID sbox_instance_xray_offset;
609
Ref<EditorNode3DGizmo> gizmo;
610
HashMap<int, Transform3D> subgizmos; // Key: Subgizmo ID, Value: Initial subgizmo transform.
611
612
Node3DEditorSelectedItem() {
613
sp = nullptr;
614
last_xform_dirty = true;
615
}
616
~Node3DEditorSelectedItem();
617
};
618
619
class Node3DEditorViewportContainer : public Container {
620
GDCLASS(Node3DEditorViewportContainer, Container);
621
622
public:
623
enum View {
624
VIEW_USE_1_VIEWPORT,
625
VIEW_USE_2_VIEWPORTS,
626
VIEW_USE_2_VIEWPORTS_ALT,
627
VIEW_USE_3_VIEWPORTS,
628
VIEW_USE_3_VIEWPORTS_ALT,
629
VIEW_USE_4_VIEWPORTS,
630
};
631
632
private:
633
View view;
634
bool mouseover;
635
real_t ratio_h;
636
real_t ratio_v;
637
638
bool hovering_v;
639
bool hovering_h;
640
641
bool dragging_v;
642
bool dragging_h;
643
Vector2 drag_begin_pos;
644
Vector2 drag_begin_ratio;
645
646
virtual void gui_input(const Ref<InputEvent> &p_event) override;
647
648
protected:
649
void _notification(int p_what);
650
651
public:
652
void set_view(View p_view);
653
View get_view();
654
655
Node3DEditorViewportContainer();
656
};
657
658
class Node3DEditor : public VBoxContainer {
659
GDCLASS(Node3DEditor, VBoxContainer);
660
661
public:
662
static const unsigned int VIEWPORTS_COUNT = 4;
663
664
enum ToolMode {
665
TOOL_MODE_TRANSFORM,
666
TOOL_MODE_MOVE,
667
TOOL_MODE_ROTATE,
668
TOOL_MODE_SCALE,
669
TOOL_MODE_SELECT,
670
TOOL_MODE_LIST_SELECT,
671
TOOL_LOCK_SELECTED,
672
TOOL_UNLOCK_SELECTED,
673
TOOL_GROUP_SELECTED,
674
TOOL_UNGROUP_SELECTED,
675
TOOL_RULER,
676
TOOL_MAX
677
};
678
679
enum ToolOptions {
680
TOOL_OPT_LOCAL_COORDS,
681
TOOL_OPT_USE_SNAP,
682
TOOL_OPT_USE_TRACKBALL,
683
TOOL_OPT_MAX
684
};
685
686
enum TransformMode {
687
TRANSFORM_MODE_GLOBAL = 1,
688
TRANSFORM_MODE_LOCAL = 2,
689
};
690
691
private:
692
EditorSelection *editor_selection = nullptr;
693
694
Node3DEditorViewportContainer *viewport_base = nullptr;
695
Node3DEditorViewport *viewports[VIEWPORTS_COUNT];
696
int last_used_viewport = 0;
697
698
VSplitContainer *shader_split = nullptr;
699
HSplitContainer *left_panel_split = nullptr;
700
HSplitContainer *right_panel_split = nullptr;
701
702
/////
703
704
ToolMode tool_mode = TOOL_MODE_TRANSFORM;
705
706
RID origin_mesh;
707
RID origin_multimesh;
708
RID origin_instance;
709
bool origin_enabled = false;
710
RID grid[3];
711
RID grid_instance[3];
712
bool grid_visible[3] = { false, false, false }; //currently visible
713
bool grid_enable[3] = { false, false, false }; //should be always visible if true
714
bool grid_enabled = false;
715
bool grid_init_draw = false;
716
Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
717
Vector3 grid_camera_last_update_position;
718
719
Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3], axis_gizmo[3];
720
Ref<ArrayMesh> trackball_sphere_gizmo;
721
Ref<StandardMaterial3D> gizmo_color[3];
722
Ref<StandardMaterial3D> plane_gizmo_color[3];
723
Ref<ShaderMaterial> rotate_gizmo_color[4];
724
Ref<StandardMaterial3D> gizmo_color_hl[3];
725
Ref<StandardMaterial3D> plane_gizmo_color_hl[3];
726
Ref<ShaderMaterial> rotate_gizmo_color_hl[4];
727
Ref<StandardMaterial3D> trackball_sphere_material;
728
Ref<StandardMaterial3D> trackball_sphere_material_hl;
729
730
Ref<Node3DGizmo> current_hover_gizmo;
731
int current_hover_gizmo_handle;
732
bool current_hover_gizmo_handle_secondary;
733
734
DynamicBVH gizmo_bvh;
735
736
real_t snap_translate_value;
737
real_t snap_rotate_value;
738
real_t snap_scale_value;
739
740
Ref<ArrayMesh> active_selection_box_xray;
741
Ref<ArrayMesh> active_selection_box;
742
Ref<ArrayMesh> selection_box_xray;
743
Ref<ArrayMesh> selection_box;
744
745
Ref<StandardMaterial3D> selection_box_mat = memnew(StandardMaterial3D);
746
Ref<StandardMaterial3D> selection_box_mat_xray = memnew(StandardMaterial3D);
747
Ref<StandardMaterial3D> active_selection_box_mat = memnew(StandardMaterial3D);
748
Ref<StandardMaterial3D> active_selection_box_mat_xray = memnew(StandardMaterial3D);
749
750
RID indicators;
751
RID indicators_instance;
752
RID cursor_mesh;
753
RID cursor_instance;
754
Ref<ShaderMaterial> origin_mat;
755
Ref<ShaderMaterial> grid_mat[3];
756
Ref<StandardMaterial3D> cursor_material;
757
758
// Scene drag and drop support
759
Node3D *preview_node = nullptr;
760
AABB preview_bounds;
761
762
Ref<Material> preview_material;
763
Ref<Material> preview_reset_material;
764
ObjectID preview_material_target;
765
int preview_material_surface = -1;
766
767
struct Gizmo {
768
bool visible = false;
769
real_t scale = 0;
770
Transform3D transform;
771
} gizmo;
772
773
enum MenuOption {
774
MENU_TOOL_TRANSFORM,
775
MENU_TOOL_MOVE,
776
MENU_TOOL_ROTATE,
777
MENU_TOOL_SCALE,
778
MENU_TOOL_SELECT,
779
MENU_TOOL_LIST_SELECT,
780
MENU_TOOL_LOCAL_COORDS,
781
MENU_TOOL_USE_SNAP,
782
MENU_TOOL_USE_TRACKBALL,
783
MENU_TRANSFORM_CONFIGURE_SNAP,
784
MENU_TRANSFORM_DIALOG,
785
MENU_VIEW_USE_1_VIEWPORT,
786
MENU_VIEW_USE_2_VIEWPORTS,
787
MENU_VIEW_USE_2_VIEWPORTS_ALT,
788
MENU_VIEW_USE_3_VIEWPORTS,
789
MENU_VIEW_USE_3_VIEWPORTS_ALT,
790
MENU_VIEW_USE_4_VIEWPORTS,
791
MENU_VIEW_ORIGIN,
792
MENU_VIEW_GRID,
793
MENU_VIEW_GIZMOS_3D_ICONS,
794
MENU_VIEW_CAMERA_SETTINGS,
795
MENU_LOCK_SELECTED,
796
MENU_UNLOCK_SELECTED,
797
MENU_GROUP_SELECTED,
798
MENU_UNGROUP_SELECTED,
799
MENU_SNAP_TO_FLOOR,
800
MENU_RULER,
801
};
802
803
Button *tool_button[TOOL_MAX];
804
Button *tool_option_button[TOOL_OPT_MAX];
805
806
MenuButton *transform_menu = nullptr;
807
PopupMenu *gizmos_menu = nullptr;
808
MenuButton *view_layout_menu = nullptr;
809
810
AcceptDialog *accept = nullptr;
811
812
ConfirmationDialog *snap_dialog = nullptr;
813
ConfirmationDialog *xform_dialog = nullptr;
814
ConfirmationDialog *settings_dialog = nullptr;
815
816
bool snap_enabled = false;
817
bool snap_key_enabled = false;
818
EditorSpinSlider *snap_translate = nullptr;
819
EditorSpinSlider *snap_rotate = nullptr;
820
EditorSpinSlider *snap_scale = nullptr;
821
822
bool trackball_enabled = false;
823
824
LineEdit *xform_translate[3];
825
LineEdit *xform_rotate[3];
826
LineEdit *xform_scale[3];
827
OptionButton *xform_type = nullptr;
828
829
VBoxContainer *settings_vbc = nullptr;
830
SpinBox *settings_fov = nullptr;
831
SpinBox *settings_znear = nullptr;
832
SpinBox *settings_zfar = nullptr;
833
834
void _snap_changed();
835
void _snap_update();
836
void _xform_dialog_action();
837
void _menu_item_pressed(int p_option);
838
void _menu_item_toggled(bool pressed, int p_option);
839
void _menu_gizmo_toggled(int p_option);
840
// Used for secondary menu items which are displayed depending on the currently selected node
841
// (such as MeshInstance's "Mesh" menu).
842
PanelContainer *context_toolbar_panel = nullptr;
843
HBoxContainer *context_toolbar_hbox = nullptr;
844
HashMap<Control *, VSeparator *> context_toolbar_separators;
845
846
void _update_context_toolbar();
847
848
void _generate_selection_boxes();
849
850
void _init_indicators();
851
void _update_gizmos_menu();
852
void _update_gizmos_menu_theme();
853
void _init_grid();
854
void _finish_indicators();
855
void _finish_grid();
856
857
void _toggle_maximize_view(Object *p_viewport);
858
void _viewport_clicked(int p_viewport_idx);
859
860
Node *custom_camera = nullptr;
861
862
Object *_get_editor_data(Object *p_what);
863
864
Ref<Environment> viewport_environment;
865
866
Node3D *selected = nullptr;
867
868
Node3DEditorViewport *freelook_viewport = nullptr;
869
870
void _request_gizmo(Object *p_obj);
871
void _request_gizmo_for_id(ObjectID p_id);
872
void _set_subgizmo_selection(Object *p_obj, Ref<Node3DGizmo> p_gizmo, int p_id, Transform3D p_transform = Transform3D());
873
void _clear_subgizmo_selection(Object *p_obj = nullptr);
874
875
bool gizmos_dirty = false;
876
877
static Node3DEditor *singleton;
878
879
void _node_added(Node *p_node);
880
void _node_removed(Node *p_node);
881
Vector<Ref<EditorNode3DGizmoPlugin>> gizmo_plugins_by_priority;
882
Vector<Ref<EditorNode3DGizmoPlugin>> gizmo_plugins_by_name;
883
884
void _register_all_gizmos();
885
886
void _selection_changed();
887
void _refresh_menu_icons();
888
889
bool do_snap_selected_nodes_to_floor = false;
890
void _snap_selected_nodes_to_floor();
891
892
// Preview Sun and Environment
893
894
class PreviewSunEnvPopup : public PopupPanel {
895
GDCLASS(PreviewSunEnvPopup, PopupPanel);
896
897
protected:
898
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
899
};
900
901
uint32_t world_env_count = 0;
902
uint32_t directional_light_count = 0;
903
904
Button *sun_button = nullptr;
905
Label *sun_state = nullptr;
906
Label *sun_title = nullptr;
907
VBoxContainer *sun_vb = nullptr;
908
Popup *sun_environ_popup = nullptr;
909
Control *sun_direction = nullptr;
910
EditorSpinSlider *sun_angle_altitude = nullptr;
911
EditorSpinSlider *sun_angle_azimuth = nullptr;
912
ColorPickerButton *sun_color = nullptr;
913
EditorSpinSlider *sun_energy = nullptr;
914
EditorSpinSlider *sun_shadow_max_distance = nullptr;
915
Button *sun_add_to_scene = nullptr;
916
917
Vector2 sun_rotation;
918
919
Ref<Shader> sun_direction_shader;
920
Ref<ShaderMaterial> sun_direction_material;
921
922
Button *environ_button = nullptr;
923
Label *environ_state = nullptr;
924
Label *environ_title = nullptr;
925
VBoxContainer *environ_vb = nullptr;
926
ColorPickerButton *environ_sky_color = nullptr;
927
ColorPickerButton *environ_ground_color = nullptr;
928
EditorSpinSlider *environ_energy = nullptr;
929
Button *environ_ao_button = nullptr;
930
Button *environ_glow_button = nullptr;
931
Button *environ_tonemap_button = nullptr;
932
Button *environ_gi_button = nullptr;
933
Button *environ_add_to_scene = nullptr;
934
935
Button *sun_environ_settings = nullptr;
936
937
DirectionalLight3D *preview_sun = nullptr;
938
bool preview_sun_dangling = false;
939
WorldEnvironment *preview_environment = nullptr;
940
bool preview_env_dangling = false;
941
Ref<Environment> environment;
942
Ref<CameraAttributesPractical> camera_attributes;
943
Ref<ProceduralSkyMaterial> sky_material;
944
945
bool sun_environ_updating = false;
946
947
void _sun_direction_draw();
948
void _sun_direction_input(const Ref<InputEvent> &p_event);
949
void _sun_direction_set_altitude(float p_altitude);
950
void _sun_direction_set_azimuth(float p_azimuth);
951
void _sun_set_color(const Color &p_color);
952
void _sun_set_energy(float p_energy);
953
void _sun_set_shadow_max_distance(float p_shadow_max_distance);
954
955
void _environ_set_sky_color(const Color &p_color);
956
void _environ_set_ground_color(const Color &p_color);
957
void _environ_set_sky_energy(float p_energy);
958
void _environ_set_ao();
959
void _environ_set_glow();
960
void _environ_set_tonemap();
961
void _environ_set_gi();
962
963
void _load_default_preview_settings();
964
void _update_preview_environment();
965
966
void _preview_settings_changed();
967
void _sun_environ_settings_pressed();
968
969
void _add_sun_to_scene(bool p_already_added_environment = false);
970
void _add_environment_to_scene(bool p_already_added_sun = false);
971
972
void _update_theme();
973
974
protected:
975
void _notification(int p_what);
976
//void _gui_input(InputEvent p_event);
977
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
978
979
static void _bind_methods();
980
981
public:
982
static Node3DEditor *get_singleton() { return singleton; }
983
984
static Size2i get_camera_viewport_size(Camera3D *p_camera);
985
986
Vector3 snap_point(Vector3 p_target, Vector3 p_start = Vector3(0, 0, 0)) const;
987
988
float get_znear() const { return settings_znear->get_value(); }
989
float get_zfar() const { return settings_zfar->get_value(); }
990
float get_fov() const { return settings_fov->get_value(); }
991
992
Transform3D get_gizmo_transform() const { return gizmo.transform; }
993
bool is_gizmo_visible() const;
994
995
ToolMode get_tool_mode() const { return tool_mode; }
996
bool are_local_coords_enabled() const { return tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); }
997
void set_local_coords_enabled(bool on) const { tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_pressed(on); }
998
bool is_snap_enabled() const { return snap_enabled ^ snap_key_enabled; }
999
real_t get_translate_snap() const;
1000
real_t get_rotate_snap() const;
1001
real_t get_scale_snap() const;
1002
1003
bool is_trackball_enabled() const { return trackball_enabled; }
1004
1005
Ref<ArrayMesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }
1006
Ref<ArrayMesh> get_axis_gizmo(int idx) const { return axis_gizmo[idx]; }
1007
Ref<ArrayMesh> get_move_plane_gizmo(int idx) const { return move_plane_gizmo[idx]; }
1008
Ref<ArrayMesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; }
1009
Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; }
1010
Ref<ArrayMesh> get_scale_plane_gizmo(int idx) const { return scale_plane_gizmo[idx]; }
1011
Ref<ArrayMesh> get_trackball_sphere_gizmo() const { return trackball_sphere_gizmo; }
1012
1013
void update_grid();
1014
void update_transform_gizmo();
1015
void update_all_gizmos(Node *p_node = nullptr);
1016
void update_gizmo_opacity();
1017
void snap_selected_nodes_to_floor();
1018
void select_gizmo_highlight_axis(int p_axis);
1019
void set_custom_camera(Node *p_camera) { custom_camera = p_camera; }
1020
1021
Dictionary get_state() const;
1022
void set_state(const Dictionary &p_state);
1023
1024
Ref<Environment> get_viewport_environment() { return viewport_environment; }
1025
1026
void add_control_to_menu_panel(Control *p_control);
1027
void remove_control_from_menu_panel(Control *p_control);
1028
1029
void add_control_to_left_panel(Control *p_control);
1030
void remove_control_from_left_panel(Control *p_control);
1031
1032
void add_control_to_right_panel(Control *p_control);
1033
void remove_control_from_right_panel(Control *p_control);
1034
1035
void move_control_to_left_panel(Control *p_control);
1036
void move_control_to_right_panel(Control *p_control);
1037
1038
VSplitContainer *get_shader_split();
1039
1040
Node3D *get_single_selected_node() { return selected; }
1041
bool is_current_selected_gizmo(const EditorNode3DGizmo *p_gizmo);
1042
bool is_subgizmo_selected(int p_id);
1043
Vector<int> get_subgizmo_selection();
1044
void clear_subgizmo_selection(Object *p_obj = nullptr);
1045
void refresh_dirty_gizmos();
1046
1047
Ref<EditorNode3DGizmo> get_current_hover_gizmo() const { return current_hover_gizmo; }
1048
void set_current_hover_gizmo(Ref<EditorNode3DGizmo> p_gizmo) { current_hover_gizmo = p_gizmo; }
1049
1050
void set_current_hover_gizmo_handle(int p_id, bool p_secondary) {
1051
current_hover_gizmo_handle = p_id;
1052
current_hover_gizmo_handle_secondary = p_secondary;
1053
}
1054
1055
int get_current_hover_gizmo_handle(bool &r_secondary) const {
1056
r_secondary = current_hover_gizmo_handle_secondary;
1057
return current_hover_gizmo_handle;
1058
}
1059
1060
void set_can_preview(Camera3D *p_preview);
1061
1062
void set_preview_material(Ref<Material> p_material) { preview_material = p_material; }
1063
Ref<Material> get_preview_material() { return preview_material; }
1064
void set_preview_reset_material(Ref<Material> p_material) { preview_reset_material = p_material; }
1065
Ref<Material> get_preview_reset_material() const { return preview_reset_material; }
1066
void set_preview_material_target(ObjectID p_object_id) { preview_material_target = p_object_id; }
1067
ObjectID get_preview_material_target() const { return preview_material_target; }
1068
void set_preview_material_surface(int p_surface) { preview_material_surface = p_surface; }
1069
int get_preview_material_surface() const { return preview_material_surface; }
1070
1071
Node3DEditorViewport *get_editor_viewport(int p_idx) {
1072
ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), nullptr);
1073
return viewports[p_idx];
1074
}
1075
Node3DEditorViewport *get_last_used_viewport();
1076
1077
void set_freelook_viewport(Node3DEditorViewport *p_viewport) { freelook_viewport = p_viewport; }
1078
Node3DEditorViewport *get_freelook_viewport() const { return freelook_viewport; }
1079
1080
void add_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin);
1081
void remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin);
1082
1083
DynamicBVH::ID insert_gizmo_bvh_node(Node3D *p_node, const AABB &p_aabb);
1084
void update_gizmo_bvh_node(DynamicBVH::ID p_id, const AABB &p_aabb);
1085
void remove_gizmo_bvh_node(DynamicBVH::ID p_id);
1086
Vector<Node3D *> gizmo_bvh_ray_query(const Vector3 &p_ray_start, const Vector3 &p_ray_end);
1087
Vector<Node3D *> gizmo_bvh_frustum_query(const Vector<Plane> &p_frustum);
1088
1089
void edit(Node3D *p_spatial);
1090
void clear();
1091
1092
Node3DEditor();
1093
~Node3DEditor();
1094
};
1095
1096
class Node3DEditorPlugin : public EditorPlugin {
1097
GDCLASS(Node3DEditorPlugin, EditorPlugin);
1098
1099
Node3DEditor *spatial_editor = nullptr;
1100
1101
public:
1102
Node3DEditor *get_spatial_editor() { return spatial_editor; }
1103
virtual String get_plugin_name() const override { return TTRC("3D"); }
1104
bool has_main_screen() const override { return true; }
1105
virtual void make_visible(bool p_visible) override;
1106
virtual void edit(Object *p_object) override;
1107
virtual bool handles(Object *p_object) const override;
1108
1109
virtual Dictionary get_state() const override;
1110
virtual void set_state(const Dictionary &p_state) override;
1111
virtual void clear() override { spatial_editor->clear(); }
1112
1113
virtual void edited_scene_changed() override;
1114
1115
Node3DEditorPlugin();
1116
};
1117
1118
class ViewportNavigationControl : public Control {
1119
GDCLASS(ViewportNavigationControl, Control);
1120
1121
Node3DEditorViewport *viewport = nullptr;
1122
Vector2i focused_mouse_start;
1123
Vector2 focused_pos;
1124
bool hovered = false;
1125
int focused_index = -1;
1126
Node3DEditorViewport::NavigationMode nav_mode = Node3DEditorViewport::NavigationMode::NAVIGATION_NONE;
1127
1128
const float AXIS_CIRCLE_RADIUS = 30.0f * EDSCALE;
1129
1130
protected:
1131
void _notification(int p_what);
1132
virtual void gui_input(const Ref<InputEvent> &p_event) override;
1133
void _draw();
1134
void _process_click(int p_index, Vector2 p_position, bool p_pressed);
1135
void _process_drag(int p_index, Vector2 p_position, Vector2 p_relative_position);
1136
void _update_navigation();
1137
1138
public:
1139
void set_navigation_mode(Node3DEditorViewport::NavigationMode p_nav_mode);
1140
void set_viewport(Node3DEditorViewport *p_viewport);
1141
};
1142
1143