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