Path: blob/master/editor/scene/3d/node_3d_editor_plugin.h
9902 views
/**************************************************************************/1/* node_3d_editor_plugin.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "core/math/dynamic_bvh.h"33#include "editor/plugins/editor_plugin.h"34#include "editor/scene/3d/node_3d_editor_gizmos.h"35#include "editor/themes/editor_scale.h"36#include "scene/gui/box_container.h"37#include "scene/gui/button.h"38#include "scene/gui/spin_box.h"39#include "scene/resources/immediate_mesh.h"4041class AcceptDialog;42class CheckBox;43class ColorPickerButton;44class ConfirmationDialog;45class DirectionalLight3D;46class EditorData;47class EditorSelection;48class EditorSpinSlider;49class HSplitContainer;50class LineEdit;51class MenuButton;52class Node3DEditor;53class Node3DEditorViewport;54class OptionButton;55class PanelContainer;56class ProceduralSkyMaterial;57class SubViewport;58class SubViewportContainer;59class VSeparator;60class VSplitContainer;61class ViewportNavigationControl;62class WorldEnvironment;63class MeshInstance3D;6465class ViewportRotationControl : public Control {66GDCLASS(ViewportRotationControl, Control);6768struct Axis2D {69Vector2 screen_point;70float z_axis = -99.0;71int axis = -1;72};7374struct Axis2DCompare {75_FORCE_INLINE_ bool operator()(const Axis2D &l, const Axis2D &r) const {76return l.z_axis < r.z_axis;77}78};7980Node3DEditorViewport *viewport = nullptr;81Vector<Color> axis_colors;82Vector<int> axis_menu_options;83Vector2i orbiting_mouse_start;84Point2 original_mouse_pos;85int orbiting_index = -1;86int focused_axis = -2;87bool gizmo_activated = false;8889const float AXIS_CIRCLE_RADIUS = 8.0f * EDSCALE;9091protected:92void _notification(int p_what);93virtual void gui_input(const Ref<InputEvent> &p_event) override;94void _draw();95void _draw_axis(const Axis2D &p_axis);96void _get_sorted_axis(Vector<Axis2D> &r_axis);97void _update_focus();98void _process_click(int p_index, Vector2 p_position, bool p_pressed);99void _process_drag(Ref<InputEventWithModifiers> p_event, int p_index, Vector2 p_position, Vector2 p_relative_position);100101public:102void set_viewport(Node3DEditorViewport *p_viewport);103};104105class Node3DEditorViewport : public Control {106GDCLASS(Node3DEditorViewport, Control);107friend class Node3DEditor;108friend class ViewportNavigationControl;109friend class ViewportRotationControl;110enum {111VIEW_TOP,112VIEW_BOTTOM,113VIEW_LEFT,114VIEW_RIGHT,115VIEW_FRONT,116VIEW_REAR,117VIEW_CENTER_TO_ORIGIN,118VIEW_CENTER_TO_SELECTION,119VIEW_ALIGN_TRANSFORM_WITH_VIEW,120VIEW_ALIGN_ROTATION_WITH_VIEW,121VIEW_PERSPECTIVE,122VIEW_ENVIRONMENT,123VIEW_ORTHOGONAL,124VIEW_SWITCH_PERSPECTIVE_ORTHOGONAL,125VIEW_HALF_RESOLUTION,126VIEW_AUDIO_LISTENER,127VIEW_AUDIO_DOPPLER,128VIEW_GIZMOS,129VIEW_TRANSFORM_GIZMO,130VIEW_GRID,131VIEW_INFORMATION,132VIEW_FRAME_TIME,133134// < Keep in sync with menu.135VIEW_DISPLAY_NORMAL,136VIEW_DISPLAY_WIREFRAME,137VIEW_DISPLAY_OVERDRAW,138VIEW_DISPLAY_LIGHTING,139VIEW_DISPLAY_UNSHADED,140VIEW_DISPLAY_ADVANCED,141// Advanced menu:142VIEW_DISPLAY_DEBUG_PSSM_SPLITS,143VIEW_DISPLAY_NORMAL_BUFFER,144VIEW_DISPLAY_DEBUG_SHADOW_ATLAS,145VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS,146VIEW_DISPLAY_DEBUG_DECAL_ATLAS,147VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO,148VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING,149VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION,150VIEW_DISPLAY_DEBUG_SDFGI,151VIEW_DISPLAY_DEBUG_SDFGI_PROBES,152VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,153VIEW_DISPLAY_DEBUG_SSAO,154VIEW_DISPLAY_DEBUG_SSIL,155VIEW_DISPLAY_DEBUG_GI_BUFFER,156VIEW_DISPLAY_DEBUG_DISABLE_LOD,157VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS,158VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS,159VIEW_DISPLAY_DEBUG_CLUSTER_DECALS,160VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES,161VIEW_DISPLAY_DEBUG_OCCLUDERS,162VIEW_DISPLAY_MOTION_VECTORS,163VIEW_DISPLAY_INTERNAL_BUFFER,164VIEW_DISPLAY_MAX,165// > Keep in sync with menu.166167VIEW_LOCK_ROTATION,168VIEW_CINEMATIC_PREVIEW,169VIEW_AUTO_ORTHOGONAL,170VIEW_MAX171};172173enum ViewType {174VIEW_TYPE_USER,175VIEW_TYPE_TOP,176VIEW_TYPE_BOTTOM,177VIEW_TYPE_LEFT,178VIEW_TYPE_RIGHT,179VIEW_TYPE_FRONT,180VIEW_TYPE_REAR,181};182183public:184static constexpr int32_t GIZMO_BASE_LAYER = 27;185static constexpr int32_t GIZMO_EDIT_LAYER = 26;186static constexpr int32_t GIZMO_GRID_LAYER = 25;187static constexpr int32_t MISC_TOOL_LAYER = 24;188189static constexpr int32_t FRAME_TIME_HISTORY = 20;190191enum NavigationScheme {192NAVIGATION_GODOT = 0,193NAVIGATION_MAYA = 1,194NAVIGATION_MODO = 2,195NAVIGATION_CUSTOM = 3,196NAVIGATION_TABLET = 4,197};198199enum FreelookNavigationScheme {200FREELOOK_DEFAULT,201FREELOOK_PARTIALLY_AXIS_LOCKED,202FREELOOK_FULLY_AXIS_LOCKED,203};204205enum ViewportNavMouseButton {206NAVIGATION_LEFT_MOUSE,207NAVIGATION_MIDDLE_MOUSE,208NAVIGATION_RIGHT_MOUSE,209NAVIGATION_MOUSE_4,210NAVIGATION_MOUSE_5,211};212213private:214double cpu_time_history[FRAME_TIME_HISTORY];215int cpu_time_history_index;216double gpu_time_history[FRAME_TIME_HISTORY];217int gpu_time_history_index;218219Node *ruler = nullptr;220Node3D *ruler_start_point = nullptr;221Node3D *ruler_end_point = nullptr;222Ref<ImmediateMesh> geometry;223MeshInstance3D *ruler_line = nullptr;224MeshInstance3D *ruler_line_xray = nullptr;225Label *ruler_label = nullptr;226Ref<StandardMaterial3D> ruler_material;227Ref<StandardMaterial3D> ruler_material_xray;228229int index;230ViewType view_type;231void _menu_option(int p_option);232void _set_auto_orthogonal();233Node3D *preview_node = nullptr;234bool update_preview_node = false;235Point2 preview_node_viewport_pos;236Vector3 preview_node_pos;237AABB *preview_bounds = nullptr;238Vector<String> selected_files;239AcceptDialog *accept = nullptr;240241Node *target_node = nullptr;242Point2 drop_pos;243244EditorSelection *editor_selection = nullptr;245246Button *translation_preview_button = nullptr;247CheckBox *preview_camera = nullptr;248SubViewportContainer *subviewport_container = nullptr;249250MenuButton *view_display_menu = nullptr;251PopupMenu *display_submenu = nullptr;252253Control *surface = nullptr;254SubViewport *viewport = nullptr;255Camera3D *camera = nullptr;256bool transforming = false;257bool orthogonal;258bool auto_orthogonal;259bool lock_rotation;260bool transform_gizmo_visible = true;261bool collision_reposition = false;262real_t gizmo_scale;263264bool freelook_active;265real_t freelook_speed;266Vector2 previous_mouse_position;267268PanelContainer *info_panel = nullptr;269Label *info_label = nullptr;270Label *cinema_label = nullptr;271Label *locked_label = nullptr;272Label *zoom_limit_label = nullptr;273274Label *preview_material_label = nullptr;275Label *preview_material_label_desc = nullptr;276277VBoxContainer *top_right_vbox = nullptr;278VBoxContainer *bottom_center_vbox = nullptr;279ViewportNavigationControl *position_control = nullptr;280ViewportNavigationControl *look_control = nullptr;281ViewportRotationControl *rotation_control = nullptr;282Gradient *frame_time_gradient = nullptr;283PanelContainer *frame_time_panel = nullptr;284VBoxContainer *frame_time_vbox = nullptr;285Label *cpu_time_label = nullptr;286Label *gpu_time_label = nullptr;287Label *fps_label = nullptr;288289struct _RayResult {290Node3D *item = nullptr;291real_t depth = 0;292_FORCE_INLINE_ bool operator<(const _RayResult &p_rr) const { return depth < p_rr.depth; }293};294295void _update_name();296void _compute_edit(const Point2 &p_point);297void _clear_selected();298void _select_clicked(bool p_allow_locked);299ObjectID _select_ray(const Point2 &p_pos) const;300void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked);301302Transform3D _get_camera_transform() const;303int get_selected_count() const;304void cancel_transform();305void _update_shrink();306307Vector3 _get_camera_position() const;308Vector3 _get_camera_normal() const;309Vector3 _get_screen_to_space(const Vector3 &p_vector3);310311void _select_region();312bool _transform_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only = false);313void _transform_gizmo_apply(Node3D *p_node, const Transform3D &p_transform, bool p_local);314315void _nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);316void _nav_zoom(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);317void _nav_orbit(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);318void _nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);319320bool _is_shortcut_empty(const String &p_name);321bool _is_nav_modifier_pressed(const String &p_name);322int _get_shortcut_input_count(const String &p_name);323324float get_znear() const;325float get_zfar() const;326float get_fov() const;327328ObjectID clicked;329ObjectID material_target;330Vector<Node3D *> selection_results;331Vector<Node3D *> selection_results_menu;332bool clicked_wants_append = false;333bool selection_in_progress = false;334335PopupMenu *selection_menu = nullptr;336337enum NavigationZoomStyle {338NAVIGATION_ZOOM_VERTICAL,339NAVIGATION_ZOOM_HORIZONTAL340};341342enum NavigationMode {343NAVIGATION_NONE,344NAVIGATION_PAN,345NAVIGATION_ZOOM,346NAVIGATION_ORBIT,347NAVIGATION_LOOK,348NAVIGATION_MOVE349};350enum TransformMode {351TRANSFORM_NONE,352TRANSFORM_ROTATE,353TRANSFORM_TRANSLATE,354TRANSFORM_SCALE355};356enum TransformPlane {357TRANSFORM_VIEW,358TRANSFORM_X_AXIS,359TRANSFORM_Y_AXIS,360TRANSFORM_Z_AXIS,361TRANSFORM_YZ,362TRANSFORM_XZ,363TRANSFORM_XY,364};365366struct EditData {367TransformMode mode;368TransformPlane plane;369Transform3D original;370Vector3 click_ray;371Vector3 click_ray_pos;372Vector3 center;373Point2 mouse_pos;374Point2 original_mouse_pos;375bool snap = false;376bool show_rotation_line = false;377Ref<EditorNode3DGizmo> gizmo;378int gizmo_handle = 0;379bool gizmo_handle_secondary = false;380Variant gizmo_initial_value;381bool original_local;382bool instant;383384// Numeric blender-style transforms (e.g. 'g5x').385// numeric_input tracks the current input value, e.g. 1.23.386// numeric_negate indicates whether '-' has been pressed to negate the value387// while numeric_next_decimal is 0, numbers are input before the decimal point388// after pressing '.', numeric next decimal changes to -1, and decrements after each press.389double numeric_input = 0.0;390bool numeric_negate = false;391int numeric_next_decimal = 0;392} _edit;393394struct Cursor {395Vector3 pos;396real_t x_rot, y_rot, distance, fov_scale;397Vector3 eye_pos; // Used in freelook mode398bool region_select;399Point2 region_begin, region_end;400401Cursor() {402// These rotations place the camera in +X +Y +Z, aka south east, facing north west.403x_rot = 0.5;404y_rot = -0.5;405distance = 4;406fov_scale = 1.0;407region_select = false;408}409};410// Viewport camera supports movement smoothing,411// so one cursor is the real cursor, while the other can be an interpolated version.412Cursor cursor; // Immediate cursor413Cursor camera_cursor; // That one may be interpolated (don't modify this one except for smoothing purposes)414Cursor previous_cursor; // Storing previous cursor state for canceling purposes415416void scale_fov(real_t p_fov_offset);417void reset_fov();418void scale_cursor_distance(real_t scale);419420struct ShortcutCheckSet {421bool mod_pressed = false;422bool shortcut_not_empty = true;423int input_count = 0;424ViewportNavMouseButton mouse_preference = NAVIGATION_LEFT_MOUSE;425NavigationMode result_nav_mode = NAVIGATION_NONE;426427ShortcutCheckSet() {}428429ShortcutCheckSet(bool p_mod_pressed, bool p_shortcut_not_empty, int p_input_count, const ViewportNavMouseButton &p_mouse_preference, const NavigationMode &p_result_nav_mode) :430mod_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) {431}432};433434struct ShortcutCheckSetComparator {435_FORCE_INLINE_ bool operator()(const ShortcutCheckSet &A, const ShortcutCheckSet &B) const {436return A.input_count > B.input_count;437}438};439440NavigationMode _get_nav_mode_from_shortcut_check(ViewportNavMouseButton p_mouse_button, Vector<ShortcutCheckSet> p_shortcut_check_sets, bool p_use_not_empty);441442void set_freelook_active(bool active_now);443void scale_freelook_speed(real_t scale);444445real_t zoom_indicator_delay;446int zoom_failed_attempts_count = 0;447448RID 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];449450String last_message;451String message;452double message_time;453454void set_message(const String &p_message, float p_time = 5);455456void _view_settings_confirmed(real_t p_interp_delta);457void _update_camera(real_t p_interp_delta);458void _update_navigation_controls_visibility();459Transform3D to_camera_transform(const Cursor &p_cursor) const;460void _draw();461462// These allow tool scripts to set the 3D cursor location by updating the camera transform.463Transform3D last_camera_transform;464bool _camera_moved_externally();465void _apply_camera_transform_to_cursor();466467void _surface_mouse_enter();468void _surface_mouse_exit();469void _surface_focus_enter();470void _surface_focus_exit();471472void input(const Ref<InputEvent> &p_event) override;473void _sinput(const Ref<InputEvent> &p_event);474void _update_freelook(real_t delta);475Node3DEditor *spatial_editor = nullptr;476477Camera3D *previewing = nullptr;478Camera3D *preview = nullptr;479480bool previewing_camera = false;481bool previewing_cinema = false;482bool _is_node_locked(const Node *p_node) const;483void _preview_exited_scene();484void _preview_camera_property_changed();485void _update_centered_labels();486void _toggle_camera_preview(bool);487void _toggle_cinema_preview(bool);488void _init_gizmo_instance(int p_idx);489void _finish_gizmo_instances();490void _selection_result_pressed(int);491void _selection_menu_hide();492void _list_select(Ref<InputEventMouseButton> b);493Point2 _get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const;494495Vector3 _get_instance_position(const Point2 &p_pos, Node3D *p_node) const;496static AABB _calculate_spatial_bounds(const Node3D *p_parent, bool p_omit_top_level = false, const Transform3D *p_bounds_orientation = nullptr);497498Node *_sanitize_preview_node(Node *p_node) const;499500void _create_preview_node(const Vector<String> &files) const;501void _remove_preview_node();502bool _apply_preview_material(ObjectID p_target, const Point2 &p_point) const;503void _reset_preview_material() const;504void _remove_preview_material();505bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) const;506bool _create_instance(Node *p_parent, const String &p_path, const Point2 &p_point);507bool _create_audio_node(Node *p_parent, const String &p_path, const Point2 &p_point);508void _perform_drop_data();509510bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);511void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);512513void _project_settings_changed();514515Transform3D _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);516517void begin_transform(TransformMode p_mode, bool instant);518void commit_transform();519void apply_transform(Vector3 p_motion, double p_snap);520void update_transform(bool p_shift);521void update_transform_numeric();522void finish_transform();523524void register_shortcut_action(const String &p_path, const String &p_name, Key p_keycode, bool p_physical = false);525void shortcut_changed_callback(const Ref<Shortcut> p_shortcut, const String &p_shortcut_path);526527// Supported rendering methods for advanced debug draw mode items.528enum SupportedRenderingMethods {529ALL,530FORWARD_PLUS,531FORWARD_PLUS_MOBILE,532};533534void _set_lock_view_rotation(bool p_lock_rotation);535void _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 = "");536537protected:538void _notification(int p_what);539static void _bind_methods();540541public:542void update_surface() { surface->queue_redraw(); }543void update_transform_gizmo_view();544545void set_can_preview(Camera3D *p_preview);546void set_state(const Dictionary &p_state);547Dictionary get_state() const;548void reset();549bool is_freelook_active() const { return freelook_active; }550551Vector3 get_ray_pos(const Vector2 &p_pos) const;552Vector3 get_ray(const Vector2 &p_pos) const;553Point2 point_to_screen(const Vector3 &p_point);554555void focus_selection();556557void assign_pending_data_pointers(558Node3D *p_preview_node,559AABB *p_preview_bounds,560AcceptDialog *p_accept);561562SubViewport *get_viewport_node() { return viewport; }563Camera3D *get_camera_3d() { return camera; } // return the default camera object.564Control *get_surface() { return surface; }565566Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p_index);567~Node3DEditorViewport();568};569570class Node3DEditorSelectedItem : public Object {571GDCLASS(Node3DEditorSelectedItem, Object);572573public:574AABB aabb;575Transform3D original; // original location when moving576Transform3D original_local;577Transform3D last_xform; // last transform578bool last_xform_dirty;579Node3D *sp = nullptr;580RID sbox_instance;581RID sbox_instance_offset;582RID sbox_instance_xray;583RID sbox_instance_xray_offset;584Ref<EditorNode3DGizmo> gizmo;585HashMap<int, Transform3D> subgizmos; // Key: Subgizmo ID, Value: Initial subgizmo transform.586587Node3DEditorSelectedItem() {588sp = nullptr;589last_xform_dirty = true;590}591~Node3DEditorSelectedItem();592};593594class Node3DEditorViewportContainer : public Container {595GDCLASS(Node3DEditorViewportContainer, Container);596597public:598enum View {599VIEW_USE_1_VIEWPORT,600VIEW_USE_2_VIEWPORTS,601VIEW_USE_2_VIEWPORTS_ALT,602VIEW_USE_3_VIEWPORTS,603VIEW_USE_3_VIEWPORTS_ALT,604VIEW_USE_4_VIEWPORTS,605};606607private:608View view;609bool mouseover;610real_t ratio_h;611real_t ratio_v;612613bool hovering_v;614bool hovering_h;615616bool dragging_v;617bool dragging_h;618Vector2 drag_begin_pos;619Vector2 drag_begin_ratio;620621virtual void gui_input(const Ref<InputEvent> &p_event) override;622623protected:624void _notification(int p_what);625626public:627void set_view(View p_view);628View get_view();629630Node3DEditorViewportContainer();631};632633class Node3DEditor : public VBoxContainer {634GDCLASS(Node3DEditor, VBoxContainer);635636public:637static const unsigned int VIEWPORTS_COUNT = 4;638639enum ToolMode {640TOOL_MODE_SELECT,641TOOL_MODE_MOVE,642TOOL_MODE_ROTATE,643TOOL_MODE_SCALE,644TOOL_MODE_LIST_SELECT,645TOOL_LOCK_SELECTED,646TOOL_UNLOCK_SELECTED,647TOOL_GROUP_SELECTED,648TOOL_UNGROUP_SELECTED,649TOOL_RULER,650TOOL_MAX651};652653enum ToolOptions {654TOOL_OPT_LOCAL_COORDS,655TOOL_OPT_USE_SNAP,656TOOL_OPT_MAX657658};659660private:661EditorSelection *editor_selection = nullptr;662663Node3DEditorViewportContainer *viewport_base = nullptr;664Node3DEditorViewport *viewports[VIEWPORTS_COUNT];665int last_used_viewport = 0;666667VSplitContainer *shader_split = nullptr;668HSplitContainer *left_panel_split = nullptr;669HSplitContainer *right_panel_split = nullptr;670671/////672673ToolMode tool_mode;674675RID origin_mesh;676RID origin_multimesh;677RID origin_instance;678bool origin_enabled = false;679RID grid[3];680RID grid_instance[3];681bool grid_visible[3] = { false, false, false }; //currently visible682bool grid_enable[3] = { false, false, false }; //should be always visible if true683bool grid_enabled = false;684bool grid_init_draw = false;685Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;686Vector3 grid_camera_last_update_position;687688Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3], axis_gizmo[3];689Ref<StandardMaterial3D> gizmo_color[3];690Ref<StandardMaterial3D> plane_gizmo_color[3];691Ref<ShaderMaterial> rotate_gizmo_color[3];692Ref<StandardMaterial3D> gizmo_color_hl[3];693Ref<StandardMaterial3D> plane_gizmo_color_hl[3];694Ref<ShaderMaterial> rotate_gizmo_color_hl[3];695696Ref<Node3DGizmo> current_hover_gizmo;697int current_hover_gizmo_handle;698bool current_hover_gizmo_handle_secondary;699700DynamicBVH gizmo_bvh;701702real_t snap_translate_value;703real_t snap_rotate_value;704real_t snap_scale_value;705706Ref<ArrayMesh> active_selection_box_xray;707Ref<ArrayMesh> active_selection_box;708Ref<ArrayMesh> selection_box_xray;709Ref<ArrayMesh> selection_box;710711Ref<StandardMaterial3D> selection_box_mat = memnew(StandardMaterial3D);712Ref<StandardMaterial3D> selection_box_mat_xray = memnew(StandardMaterial3D);713Ref<StandardMaterial3D> active_selection_box_mat = memnew(StandardMaterial3D);714Ref<StandardMaterial3D> active_selection_box_mat_xray = memnew(StandardMaterial3D);715716RID indicators;717RID indicators_instance;718RID cursor_mesh;719RID cursor_instance;720Ref<ShaderMaterial> origin_mat;721Ref<ShaderMaterial> grid_mat[3];722Ref<StandardMaterial3D> cursor_material;723724// Scene drag and drop support725Node3D *preview_node = nullptr;726AABB preview_bounds;727728Ref<Material> preview_material;729Ref<Material> preview_reset_material;730ObjectID preview_material_target;731int preview_material_surface = -1;732733struct Gizmo {734bool visible = false;735real_t scale = 0;736Transform3D transform;737} gizmo;738739enum MenuOption {740MENU_TOOL_SELECT,741MENU_TOOL_MOVE,742MENU_TOOL_ROTATE,743MENU_TOOL_SCALE,744MENU_TOOL_LIST_SELECT,745MENU_TOOL_LOCAL_COORDS,746MENU_TOOL_USE_SNAP,747MENU_TRANSFORM_CONFIGURE_SNAP,748MENU_TRANSFORM_DIALOG,749MENU_VIEW_USE_1_VIEWPORT,750MENU_VIEW_USE_2_VIEWPORTS,751MENU_VIEW_USE_2_VIEWPORTS_ALT,752MENU_VIEW_USE_3_VIEWPORTS,753MENU_VIEW_USE_3_VIEWPORTS_ALT,754MENU_VIEW_USE_4_VIEWPORTS,755MENU_VIEW_ORIGIN,756MENU_VIEW_GRID,757MENU_VIEW_GIZMOS_3D_ICONS,758MENU_VIEW_CAMERA_SETTINGS,759MENU_LOCK_SELECTED,760MENU_UNLOCK_SELECTED,761MENU_GROUP_SELECTED,762MENU_UNGROUP_SELECTED,763MENU_SNAP_TO_FLOOR,764MENU_RULER,765};766767Button *tool_button[TOOL_MAX];768Button *tool_option_button[TOOL_OPT_MAX];769770MenuButton *transform_menu = nullptr;771PopupMenu *gizmos_menu = nullptr;772MenuButton *view_layout_menu = nullptr;773774AcceptDialog *accept = nullptr;775776ConfirmationDialog *snap_dialog = nullptr;777ConfirmationDialog *xform_dialog = nullptr;778ConfirmationDialog *settings_dialog = nullptr;779780bool snap_enabled;781bool snap_key_enabled;782LineEdit *snap_translate = nullptr;783LineEdit *snap_rotate = nullptr;784LineEdit *snap_scale = nullptr;785786LineEdit *xform_translate[3];787LineEdit *xform_rotate[3];788LineEdit *xform_scale[3];789OptionButton *xform_type = nullptr;790791VBoxContainer *settings_vbc = nullptr;792SpinBox *settings_fov = nullptr;793SpinBox *settings_znear = nullptr;794SpinBox *settings_zfar = nullptr;795796void _snap_changed();797void _snap_update();798void _xform_dialog_action();799void _menu_item_pressed(int p_option);800void _menu_item_toggled(bool pressed, int p_option);801void _menu_gizmo_toggled(int p_option);802// Used for secondary menu items which are displayed depending on the currently selected node803// (such as MeshInstance's "Mesh" menu).804PanelContainer *context_toolbar_panel = nullptr;805HBoxContainer *context_toolbar_hbox = nullptr;806HashMap<Control *, VSeparator *> context_toolbar_separators;807808void _update_context_toolbar();809810void _generate_selection_boxes();811812void _init_indicators();813void _update_gizmos_menu();814void _update_gizmos_menu_theme();815void _init_grid();816void _finish_indicators();817void _finish_grid();818819void _toggle_maximize_view(Object *p_viewport);820void _viewport_clicked(int p_viewport_idx);821822Node *custom_camera = nullptr;823824Object *_get_editor_data(Object *p_what);825826Ref<Environment> viewport_environment;827828Node3D *selected = nullptr;829830Node3DEditorViewport *freelook_viewport = nullptr;831832void _request_gizmo(Object *p_obj);833void _request_gizmo_for_id(ObjectID p_id);834void _set_subgizmo_selection(Object *p_obj, Ref<Node3DGizmo> p_gizmo, int p_id, Transform3D p_transform = Transform3D());835void _clear_subgizmo_selection(Object *p_obj = nullptr);836837bool gizmos_dirty = false;838839static Node3DEditor *singleton;840841void _node_added(Node *p_node);842void _node_removed(Node *p_node);843Vector<Ref<EditorNode3DGizmoPlugin>> gizmo_plugins_by_priority;844Vector<Ref<EditorNode3DGizmoPlugin>> gizmo_plugins_by_name;845846void _register_all_gizmos();847848void _selection_changed();849void _refresh_menu_icons();850851bool do_snap_selected_nodes_to_floor = false;852void _snap_selected_nodes_to_floor();853854// Preview Sun and Environment855856class PreviewSunEnvPopup : public PopupPanel {857GDCLASS(PreviewSunEnvPopup, PopupPanel);858859protected:860virtual void shortcut_input(const Ref<InputEvent> &p_event) override;861};862863uint32_t world_env_count = 0;864uint32_t directional_light_count = 0;865866Button *sun_button = nullptr;867Label *sun_state = nullptr;868Label *sun_title = nullptr;869VBoxContainer *sun_vb = nullptr;870Popup *sun_environ_popup = nullptr;871Control *sun_direction = nullptr;872EditorSpinSlider *sun_angle_altitude = nullptr;873EditorSpinSlider *sun_angle_azimuth = nullptr;874ColorPickerButton *sun_color = nullptr;875EditorSpinSlider *sun_energy = nullptr;876EditorSpinSlider *sun_shadow_max_distance = nullptr;877Button *sun_add_to_scene = nullptr;878879Vector2 sun_rotation;880881Ref<Shader> sun_direction_shader;882Ref<ShaderMaterial> sun_direction_material;883884Button *environ_button = nullptr;885Label *environ_state = nullptr;886Label *environ_title = nullptr;887VBoxContainer *environ_vb = nullptr;888ColorPickerButton *environ_sky_color = nullptr;889ColorPickerButton *environ_ground_color = nullptr;890EditorSpinSlider *environ_energy = nullptr;891Button *environ_ao_button = nullptr;892Button *environ_glow_button = nullptr;893Button *environ_tonemap_button = nullptr;894Button *environ_gi_button = nullptr;895Button *environ_add_to_scene = nullptr;896897Button *sun_environ_settings = nullptr;898899DirectionalLight3D *preview_sun = nullptr;900bool preview_sun_dangling = false;901WorldEnvironment *preview_environment = nullptr;902bool preview_env_dangling = false;903Ref<Environment> environment;904Ref<CameraAttributesPractical> camera_attributes;905Ref<ProceduralSkyMaterial> sky_material;906907bool sun_environ_updating = false;908909void _sun_direction_draw();910void _sun_direction_input(const Ref<InputEvent> &p_event);911void _sun_direction_set_altitude(float p_altitude);912void _sun_direction_set_azimuth(float p_azimuth);913void _sun_set_color(const Color &p_color);914void _sun_set_energy(float p_energy);915void _sun_set_shadow_max_distance(float p_shadow_max_distance);916917void _environ_set_sky_color(const Color &p_color);918void _environ_set_ground_color(const Color &p_color);919void _environ_set_sky_energy(float p_energy);920void _environ_set_ao();921void _environ_set_glow();922void _environ_set_tonemap();923void _environ_set_gi();924925void _load_default_preview_settings();926void _update_preview_environment();927928void _preview_settings_changed();929void _sun_environ_settings_pressed();930931void _add_sun_to_scene(bool p_already_added_environment = false);932void _add_environment_to_scene(bool p_already_added_sun = false);933934void _update_theme();935936protected:937void _notification(int p_what);938//void _gui_input(InputEvent p_event);939virtual void shortcut_input(const Ref<InputEvent> &p_event) override;940941static void _bind_methods();942943public:944static Node3DEditor *get_singleton() { return singleton; }945946static Size2i get_camera_viewport_size(Camera3D *p_camera);947948Vector3 snap_point(Vector3 p_target, Vector3 p_start = Vector3(0, 0, 0)) const;949950float get_znear() const { return settings_znear->get_value(); }951float get_zfar() const { return settings_zfar->get_value(); }952float get_fov() const { return settings_fov->get_value(); }953954Transform3D get_gizmo_transform() const { return gizmo.transform; }955bool is_gizmo_visible() const;956957ToolMode get_tool_mode() const { return tool_mode; }958bool are_local_coords_enabled() const { return tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); }959void set_local_coords_enabled(bool on) const { tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_pressed(on); }960bool is_snap_enabled() const { return snap_enabled ^ snap_key_enabled; }961real_t get_translate_snap() const;962real_t get_rotate_snap() const;963real_t get_scale_snap() const;964965Ref<ArrayMesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }966Ref<ArrayMesh> get_axis_gizmo(int idx) const { return axis_gizmo[idx]; }967Ref<ArrayMesh> get_move_plane_gizmo(int idx) const { return move_plane_gizmo[idx]; }968Ref<ArrayMesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; }969Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; }970Ref<ArrayMesh> get_scale_plane_gizmo(int idx) const { return scale_plane_gizmo[idx]; }971972void update_grid();973void update_transform_gizmo();974void update_all_gizmos(Node *p_node = nullptr);975void snap_selected_nodes_to_floor();976void select_gizmo_highlight_axis(int p_axis);977void set_custom_camera(Node *p_camera) { custom_camera = p_camera; }978979Dictionary get_state() const;980void set_state(const Dictionary &p_state);981982Ref<Environment> get_viewport_environment() { return viewport_environment; }983984void add_control_to_menu_panel(Control *p_control);985void remove_control_from_menu_panel(Control *p_control);986987void add_control_to_left_panel(Control *p_control);988void remove_control_from_left_panel(Control *p_control);989990void add_control_to_right_panel(Control *p_control);991void remove_control_from_right_panel(Control *p_control);992993void move_control_to_left_panel(Control *p_control);994void move_control_to_right_panel(Control *p_control);995996VSplitContainer *get_shader_split();997998Node3D *get_single_selected_node() { return selected; }999bool is_current_selected_gizmo(const EditorNode3DGizmo *p_gizmo);1000bool is_subgizmo_selected(int p_id);1001Vector<int> get_subgizmo_selection();1002void clear_subgizmo_selection(Object *p_obj = nullptr);1003void refresh_dirty_gizmos();10041005Ref<EditorNode3DGizmo> get_current_hover_gizmo() const { return current_hover_gizmo; }1006void set_current_hover_gizmo(Ref<EditorNode3DGizmo> p_gizmo) { current_hover_gizmo = p_gizmo; }10071008void set_current_hover_gizmo_handle(int p_id, bool p_secondary) {1009current_hover_gizmo_handle = p_id;1010current_hover_gizmo_handle_secondary = p_secondary;1011}10121013int get_current_hover_gizmo_handle(bool &r_secondary) const {1014r_secondary = current_hover_gizmo_handle_secondary;1015return current_hover_gizmo_handle;1016}10171018void set_can_preview(Camera3D *p_preview);10191020void set_preview_material(Ref<Material> p_material) { preview_material = p_material; }1021Ref<Material> get_preview_material() { return preview_material; }1022void set_preview_reset_material(Ref<Material> p_material) { preview_reset_material = p_material; }1023Ref<Material> get_preview_reset_material() const { return preview_reset_material; }1024void set_preview_material_target(ObjectID p_object_id) { preview_material_target = p_object_id; }1025ObjectID get_preview_material_target() const { return preview_material_target; }1026void set_preview_material_surface(int p_surface) { preview_material_surface = p_surface; }1027int get_preview_material_surface() const { return preview_material_surface; }10281029Node3DEditorViewport *get_editor_viewport(int p_idx) {1030ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), nullptr);1031return viewports[p_idx];1032}1033Node3DEditorViewport *get_last_used_viewport();10341035void set_freelook_viewport(Node3DEditorViewport *p_viewport) { freelook_viewport = p_viewport; }1036Node3DEditorViewport *get_freelook_viewport() const { return freelook_viewport; }10371038void add_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin);1039void remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin);10401041DynamicBVH::ID insert_gizmo_bvh_node(Node3D *p_node, const AABB &p_aabb);1042void update_gizmo_bvh_node(DynamicBVH::ID p_id, const AABB &p_aabb);1043void remove_gizmo_bvh_node(DynamicBVH::ID p_id);1044Vector<Node3D *> gizmo_bvh_ray_query(const Vector3 &p_ray_start, const Vector3 &p_ray_end);1045Vector<Node3D *> gizmo_bvh_frustum_query(const Vector<Plane> &p_frustum);10461047void edit(Node3D *p_spatial);1048void clear();10491050Node3DEditor();1051~Node3DEditor();1052};10531054class Node3DEditorPlugin : public EditorPlugin {1055GDCLASS(Node3DEditorPlugin, EditorPlugin);10561057Node3DEditor *spatial_editor = nullptr;10581059public:1060Node3DEditor *get_spatial_editor() { return spatial_editor; }1061virtual String get_plugin_name() const override { return TTRC("3D"); }1062bool has_main_screen() const override { return true; }1063virtual void make_visible(bool p_visible) override;1064virtual void edit(Object *p_object) override;1065virtual bool handles(Object *p_object) const override;10661067virtual Dictionary get_state() const override;1068virtual void set_state(const Dictionary &p_state) override;1069virtual void clear() override { spatial_editor->clear(); }10701071virtual void edited_scene_changed() override;10721073Node3DEditorPlugin();1074};10751076class ViewportNavigationControl : public Control {1077GDCLASS(ViewportNavigationControl, Control);10781079Node3DEditorViewport *viewport = nullptr;1080Vector2i focused_mouse_start;1081Vector2 focused_pos;1082bool hovered = false;1083int focused_index = -1;1084Node3DEditorViewport::NavigationMode nav_mode = Node3DEditorViewport::NavigationMode::NAVIGATION_NONE;10851086const float AXIS_CIRCLE_RADIUS = 30.0f * EDSCALE;10871088protected:1089void _notification(int p_what);1090virtual void gui_input(const Ref<InputEvent> &p_event) override;1091void _draw();1092void _process_click(int p_index, Vector2 p_position, bool p_pressed);1093void _process_drag(int p_index, Vector2 p_position, Vector2 p_relative_position);1094void _update_navigation();10951096public:1097void set_navigation_mode(Node3DEditorViewport::NavigationMode p_nav_mode);1098void set_viewport(Node3DEditorViewport *p_viewport);1099};110011011102