/**************************************************************************/ /* editor_node.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /**************************************************************************/ /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ #ifndef EDITOR_NODE_H #define EDITOR_NODE_H #include "core/object/script_language.h" #include "core/templates/safe_refcount.h" #include "editor/editor_data.h" #include "editor/editor_folding.h" #include "editor/plugins/editor_plugin.h" typedef void (*EditorNodeInitCallback)(); typedef void (*EditorPluginInitializeCallback)(); typedef bool (*EditorBuildCallback)(); class AcceptDialog; class ColorPicker; class ConfirmationDialog; class Control; class FileDialog; class MenuBar; class MenuButton; class OptionButton; class Panel; class PanelContainer; class RichTextLabel; class SubViewport; class TextureProgressBar; class Tree; class VBoxContainer; class VSplitContainer; class Window; class AudioStreamImportSettingsDialog; class AudioStreamPreviewGenerator; class BackgroundProgress; class DependencyEditor; class DependencyErrorDialog; class DockSplitContainer; class DynamicFontImportSettingsDialog; class EditorAbout; class EditorBuildProfileManager; class EditorBottomPanel; class EditorCommandPalette; class EditorDockManager; class EditorExport; class EditorExportPreset; class EditorFeatureProfileManager; class EditorFileDialog; class EditorFolding; class EditorLayoutsDialog; class EditorLog; class EditorMainScreen; class EditorNativeShaderSourceVisualizer; class EditorPluginList; class EditorQuickOpen; class EditorResourcePreview; class EditorResourceConversionPlugin; class EditorRunBar; class EditorSceneTabs; class EditorSelectionHistory; class EditorSettingsDialog; class EditorTitleBar; class ExportTemplateManager; class FBXImporterManager; class FileSystemDock; class HistoryDock; class OrphanResourcesDialog; class ProgressDialog; class ProjectExportDialog; class ProjectSettingsEditor; class SceneImportSettingsDialog; class SurfaceUpgradeTool; class SurfaceUpgradeDialog; struct EditorProgress { String task; bool force_background = false; bool step(const String &p_state, int p_step = -1, bool p_force_refresh = true); EditorProgress(const String &p_task, const String &p_label, int p_amount, bool p_can_cancel = false, bool p_force_background = false); ~EditorProgress(); }; class EditorNode : public Node { GDCLASS(EditorNode, Node); public: enum SceneNameCasing { SCENE_NAME_CASING_AUTO, SCENE_NAME_CASING_PASCAL_CASE, SCENE_NAME_CASING_SNAKE_CASE, SCENE_NAME_CASING_KEBAB_CASE, }; enum ActionOnPlay { ACTION_ON_PLAY_DO_NOTHING, ACTION_ON_PLAY_OPEN_OUTPUT, ACTION_ON_PLAY_OPEN_DEBUGGER, }; enum ActionOnStop { ACTION_ON_STOP_DO_NOTHING, ACTION_ON_STOP_CLOSE_BUTTOM_PANEL, }; struct ExecuteThreadArgs { String path; List args; String output; Thread execute_output_thread; Mutex execute_output_mutex; int exitcode = 0; SafeFlag done; }; private: friend class EditorSceneTabs; friend class SurfaceUpgradeTool; enum MenuOptions { FILE_NEW_SCENE, FILE_NEW_INHERITED_SCENE, FILE_OPEN_SCENE, FILE_SAVE_SCENE, FILE_SAVE_SCENE_SILENTLY, FILE_SAVE_AS_SCENE, FILE_SAVE_ALL_SCENES, FILE_SAVE_AND_RUN, FILE_SAVE_AND_RUN_MAIN_SCENE, FILE_RUN_SCENE, FILE_SHOW_IN_FILESYSTEM, FILE_EXPORT_PROJECT, FILE_EXPORT_MESH_LIBRARY, FILE_INSTALL_ANDROID_SOURCE, FILE_EXPLORE_ANDROID_BUILD_TEMPLATES, FILE_SAVE_OPTIMIZED, FILE_OPEN_RECENT, FILE_OPEN_OLD_SCENE, FILE_QUICK_OPEN, FILE_QUICK_OPEN_SCENE, FILE_QUICK_OPEN_SCRIPT, FILE_OPEN_PREV, FILE_CLOSE, FILE_CLOSE_OTHERS, FILE_CLOSE_RIGHT, FILE_CLOSE_ALL, FILE_QUIT, FILE_EXTERNAL_OPEN_SCENE, EDIT_UNDO, EDIT_REDO, EDIT_RELOAD_SAVED_SCENE, TOOLS_ORPHAN_RESOURCES, TOOLS_BUILD_PROFILE_MANAGER, TOOLS_SURFACE_UPGRADE, TOOLS_CUSTOM, RESOURCE_SAVE, RESOURCE_SAVE_AS, RUN_SETTINGS, RUN_USER_DATA_FOLDER, RELOAD_CURRENT_PROJECT, RUN_PROJECT_MANAGER, VCS_MENU, RUN_VCS_METADATA, RUN_VCS_SETTINGS, SETTINGS_UPDATE_CONTINUOUSLY, SETTINGS_UPDATE_WHEN_CHANGED, SETTINGS_UPDATE_ALWAYS, SETTINGS_UPDATE_CHANGES, SETTINGS_UPDATE_SPINNER_HIDE, SETTINGS_PREFERENCES, SETTINGS_LAYOUT_SAVE, SETTINGS_LAYOUT_DELETE, SETTINGS_LAYOUT_DEFAULT, SETTINGS_EDITOR_DATA_FOLDER, SETTINGS_EDITOR_CONFIG_FOLDER, SETTINGS_MANAGE_EXPORT_TEMPLATES, SETTINGS_MANAGE_FBX_IMPORTER, SETTINGS_MANAGE_FEATURE_PROFILES, SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE, SETTINGS_PICK_MAIN_SCENE, SETTINGS_TOGGLE_FULLSCREEN, SETTINGS_HELP, SCENE_TAB_CLOSE, EDITOR_SCREENSHOT, EDITOR_OPEN_SCREENSHOT, HELP_SEARCH, HELP_COMMAND_PALETTE, HELP_DOCS, HELP_FORUM, HELP_REPORT_A_BUG, HELP_COPY_SYSTEM_INFO, HELP_SUGGEST_A_FEATURE, HELP_SEND_DOCS_FEEDBACK, HELP_COMMUNITY, HELP_ABOUT, HELP_SUPPORT_GODOT_DEVELOPMENT, SET_RENDERER_NAME_SAVE_AND_RESTART, IMPORT_PLUGIN_BASE = 100, TOOL_MENU_BASE = 1000 }; enum { MAX_INIT_CALLBACKS = 128, MAX_BUILD_CALLBACKS = 128 }; struct ExportDefer { String preset; String path; bool debug = false; bool pack_only = false; bool android_build_template = false; } export_defer; static EditorNode *singleton; EditorData editor_data; EditorFolding editor_folding; EditorSelectionHistory editor_history; EditorCommandPalette *command_palette = nullptr; EditorExport *editor_export = nullptr; EditorLog *log = nullptr; EditorNativeShaderSourceVisualizer *native_shader_source_visualizer = nullptr; EditorPluginList *editor_plugins_force_input_forwarding = nullptr; EditorPluginList *editor_plugins_force_over = nullptr; EditorPluginList *editor_plugins_over = nullptr; EditorQuickOpen *quick_open = nullptr; EditorResourcePreview *resource_preview = nullptr; EditorSelection *editor_selection = nullptr; EditorSettingsDialog *editor_settings_dialog = nullptr; HistoryDock *history_dock = nullptr; ProjectExportDialog *project_export = nullptr; ProjectSettingsEditor *project_settings_editor = nullptr; FBXImporterManager *fbx_importer_manager = nullptr; Vector editor_plugins; bool _initializing_plugins = false; HashMap addon_name_to_plugin; LocalVector pending_addons; HashMap> active_plugins; bool is_main_screen_editing = false; Control *gui_base = nullptr; VBoxContainer *main_vbox = nullptr; OptionButton *renderer = nullptr; ConfirmationDialog *video_restart_dialog = nullptr; int renderer_current = 0; String renderer_request; // Split containers. DockSplitContainer *left_l_hsplit = nullptr; DockSplitContainer *left_l_vsplit = nullptr; DockSplitContainer *left_r_hsplit = nullptr; DockSplitContainer *left_r_vsplit = nullptr; DockSplitContainer *main_hsplit = nullptr; DockSplitContainer *right_hsplit = nullptr; DockSplitContainer *right_l_vsplit = nullptr; DockSplitContainer *right_r_vsplit = nullptr; DockSplitContainer *center_split = nullptr; // Main tabs. EditorSceneTabs *scene_tabs = nullptr; int tab_closing_idx = 0; List tabs_to_close; int tab_closing_menu_option = -1; bool exiting = false; bool dimmed = false; DisplayServer::WindowMode prev_mode = DisplayServer::WINDOW_MODE_MAXIMIZED; int old_split_ofs = 0; VSplitContainer *top_split = nullptr; Control *vp_base = nullptr; Label *project_title = nullptr; Control *left_menu_spacer = nullptr; Control *right_menu_spacer = nullptr; EditorTitleBar *title_bar = nullptr; EditorRunBar *project_run_bar = nullptr; MenuBar *main_menu = nullptr; PopupMenu *apple_menu = nullptr; PopupMenu *file_menu = nullptr; PopupMenu *project_menu = nullptr; PopupMenu *debug_menu = nullptr; PopupMenu *settings_menu = nullptr; PopupMenu *help_menu = nullptr; PopupMenu *tool_menu = nullptr; PopupMenu *export_as_menu = nullptr; Button *export_button = nullptr; Button *search_button = nullptr; TextureProgressBar *audio_vu = nullptr; Timer *screenshot_timer = nullptr; uint64_t started_timestamp = 0; RichTextLabel *load_errors = nullptr; AcceptDialog *load_error_dialog = nullptr; RichTextLabel *execute_outputs = nullptr; AcceptDialog *execute_output_dialog = nullptr; Ref theme; Timer *system_theme_timer = nullptr; bool follow_system_theme = false; bool use_system_accent_color = false; bool last_dark_mode_state = false; Color last_system_base_color = Color(0, 0, 0, 0); Color last_system_accent_color = Color(0, 0, 0, 0); PopupMenu *recent_scenes = nullptr; String _recent_scene; List previous_scenes; String defer_load_scene; Node *_last_instantiated_scene = nullptr; ConfirmationDialog *confirmation = nullptr; ConfirmationDialog *save_confirmation = nullptr; ConfirmationDialog *import_confirmation = nullptr; ConfirmationDialog *pick_main_scene = nullptr; Button *select_current_scene_button = nullptr; AcceptDialog *accept = nullptr; AcceptDialog *save_accept = nullptr; EditorAbout *about = nullptr; AcceptDialog *warning = nullptr; EditorPlugin *plugin_to_save = nullptr; int overridden_default_layout = -1; Ref default_layout; PopupMenu *editor_layouts = nullptr; EditorLayoutsDialog *layout_dialog = nullptr; ConfirmationDialog *gradle_build_manage_templates = nullptr; ConfirmationDialog *install_android_build_template = nullptr; ConfirmationDialog *remove_android_build_template = nullptr; Label *install_android_build_template_message = nullptr; OptionButton *choose_android_export_profile = nullptr; Ref android_export_preset; PopupMenu *vcs_actions_menu = nullptr; EditorFileDialog *file = nullptr; ExportTemplateManager *export_template_manager = nullptr; EditorFeatureProfileManager *feature_profile_manager = nullptr; EditorBuildProfileManager *build_profile_manager = nullptr; EditorFileDialog *file_templates = nullptr; EditorFileDialog *file_export_lib = nullptr; EditorFileDialog *file_script = nullptr; EditorFileDialog *file_android_build_source = nullptr; String current_path; MenuButton *update_spinner = nullptr; EditorMainScreen *editor_main_screen = nullptr; AudioStreamPreviewGenerator *audio_preview_gen = nullptr; ProgressDialog *progress_dialog = nullptr; BackgroundProgress *progress_hb = nullptr; DependencyErrorDialog *dependency_error = nullptr; HashMap> dependency_errors; DependencyEditor *dependency_fixer = nullptr; OrphanResourcesDialog *orphan_resources = nullptr; ConfirmationDialog *open_imported = nullptr; Button *new_inherited_button = nullptr; String open_import_request; EditorDockManager *editor_dock_manager = nullptr; Timer *editor_layout_save_delay_timer = nullptr; Timer *scan_changes_timer = nullptr; Button *distraction_free = nullptr; EditorBottomPanel *bottom_panel = nullptr; Tree *disk_changed_list = nullptr; ConfirmationDialog *disk_changed = nullptr; bool scene_distraction_free = false; bool script_distraction_free = false; bool changing_scene = false; bool cmdline_export_mode = false; bool convert_old = false; bool immediate_dialog_confirmed = false; bool opening_prev = false; bool restoring_scenes = false; bool unsaved_cache = true; bool requested_first_scan = false; bool waiting_for_first_scan = true; bool load_editor_layout_done = false; int current_menu_option = 0; SubViewport *scene_root = nullptr; // Root of the scene being edited. Object *current = nullptr; Ref saving_resource; HashSet> saving_resources_in_path; uint64_t update_spinner_step_msec = 0; uint64_t update_spinner_step_frame = 0; int update_spinner_step = 0; String _tmp_import_path; String external_file; String open_navigate; String saving_scene; EditorProgress *save_scene_progress = nullptr; DynamicFontImportSettingsDialog *fontdata_import_settings = nullptr; SceneImportSettingsDialog *scene_import_settings = nullptr; AudioStreamImportSettingsDialog *audio_stream_import_settings = nullptr; String import_reload_fn; HashSet textfile_extensions; HashSet other_file_extensions; HashSet file_dialogs; HashSet editor_file_dialogs; Vector> resource_conversion_plugins; PrintHandlerList print_handler; HashMap> icon_type_cache; SurfaceUpgradeTool *surface_upgrade_tool = nullptr; SurfaceUpgradeDialog *surface_upgrade_dialog = nullptr; bool run_surface_upgrade_tool = false; bool was_window_windowed_last = false; static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS]; static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS]; static int build_callback_count; static int plugin_init_callback_count; static Vector _init_callbacks; String _get_system_info() const; bool _should_display_update_spinner() const; static void _dependency_error_report(const String &p_path, const String &p_dep, const String &p_type) { DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id()); if (!singleton->dependency_errors.has(p_path)) { singleton->dependency_errors[p_path] = HashSet(); } singleton->dependency_errors[p_path].insert(p_dep + "::" + p_type); } static Ref _file_dialog_get_icon(const String &p_path); static void _file_dialog_register(FileDialog *p_dialog); static void _file_dialog_unregister(FileDialog *p_dialog); static void _editor_file_dialog_register(EditorFileDialog *p_dialog); static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog); static void _file_access_close_error_notify(const String &p_str); static void _file_access_close_error_notify_impl(const String &p_str); static void _print_handler(void *p_this, const String &p_string, bool p_error, bool p_rich); static void _print_handler_impl(const String &p_string, bool p_error, bool p_rich); static void _resource_saved(Ref p_resource, const String &p_path); static void _resource_loaded(Ref p_resource, const String &p_path); void _update_theme(bool p_skip_creation = false); void _build_icon_type_cache(); void _enable_pending_addons(); void _dialog_action(String p_file); void _add_to_history(const Object *p_object, const String &p_property, bool p_inspector_only); void _edit_current(bool p_skip_foreign = false, bool p_skip_inspector_update = false); void _dialog_display_save_error(String p_file, Error p_error); void _dialog_display_load_error(String p_file, Error p_error); void _menu_option(int p_option); void _menu_confirm_current(); void _menu_option_confirm(int p_option, bool p_confirmed); void _android_build_source_selected(const String &p_file); void _android_export_preset_selected(int p_index); void _request_screenshot(); void _screenshot(bool p_use_utc = false); void _save_screenshot(NodePath p_path); void _check_system_theme_changed(); void _tool_menu_option(int p_idx); void _export_as_menu_option(int p_idx); void _update_file_menu_opened(); void _update_file_menu_closed(); void _remove_plugin_from_enabled(const String &p_name); void _plugin_over_edit(EditorPlugin *p_plugin, Object *p_object); void _plugin_over_self_own(EditorPlugin *p_plugin); void _fs_changed(); void _resources_reimporting(const Vector &p_resources); void _resources_reimported(const Vector &p_resources); void _sources_changed(bool p_exist); void _node_renamed(); void _save_editor_states(const String &p_file, int p_idx = -1); void _load_editor_plugin_states_from_config(const Ref &p_config_file); void _update_title(); void _version_control_menu_option(int p_idx); void _close_messages(); void _show_messages(); void _vp_resized(); void _titlebar_resized(); void _viewport_resized(); void _update_undo_redo_allowed(); int _save_external_resources(bool p_also_save_external_data = false); void _set_current_scene(int p_idx); void _set_current_scene_nocheck(int p_idx); bool _validate_scene_recursive(const String &p_filename, Node *p_node); void _save_scene(String p_file, int idx = -1); void _save_all_scenes(); int _next_unsaved_scene(bool p_valid_filename, int p_start = 0); void _discard_changes(const String &p_str = String()); void _scene_tab_closed(int p_tab); void _cancel_close_scene_tab(); void _inherit_request(String p_file); void _instantiate_request(const Vector &p_files); void _quick_opened(); void _open_command_palette(); void _project_run_started(); void _project_run_stopped(); void _add_to_recent_scenes(const String &p_scene); void _update_recent_scenes(); void _open_recent_scene(int p_idx); void _dropped_files(const Vector &p_files); void _add_dropped_files_recursive(const Vector &p_files, String to_path); void _update_vsync_mode(); void _update_from_settings(); void _gdextensions_reloaded(); void _renderer_selected(int); void _update_renderer_color(); void _add_renderer_entry(const String &p_renderer_name, bool p_mark_overridden); void _exit_editor(int p_exit_code); virtual void shortcut_input(const Ref &p_event) override; bool has_main_screen() const { return true; } void _remove_edited_scene(bool p_change_tab = true); void _remove_scene(int index, bool p_change_tab = true); bool _find_and_save_resource(Ref p_res, HashMap, bool> &processed, int32_t flags); bool _find_and_save_edited_subresources(Object *obj, HashMap, bool> &processed, int32_t flags); void _save_edited_subresources(Node *scene, HashMap, bool> &processed, int32_t flags); void _mark_unsaved_scenes(); void _find_node_types(Node *p_node, int &count_2d, int &count_3d); void _save_scene_with_preview(String p_file, int p_idx = -1); void _close_save_scene_progress(); bool _find_scene_in_use(Node *p_node, const String &p_path) const; void _proceed_closing_scene_tabs(); bool _is_closing_editor() const; Dictionary _get_main_scene_state(); void _set_main_scene_state(Dictionary p_state, Node *p_for_scene); void _save_editor_layout(); void _load_editor_layout(); void _save_central_editor_layout_to_config(Ref p_config_file); void _load_central_editor_layout_from_config(Ref p_config_file); void _save_window_settings_to_config(Ref p_layout, const String &p_section); void _save_open_scenes_to_config(Ref p_layout); void _load_open_scenes_from_config(Ref p_layout); void _update_layouts_menu(); void _layout_menu_option(int p_id); void _update_addon_config(); void _toggle_distraction_free_mode(); void _inherit_imported(const String &p_action); void _open_imported(); void _update_update_spinner(); void _resources_changed(const Vector &p_resources); void _scan_external_changes(); void _reload_modified_scenes(); void _reload_project_settings(); void _resave_scenes(String p_str); void _feature_profile_changed(); bool _is_class_editor_disabled_by_feature_profile(const StringName &p_class); Ref _get_class_or_script_icon(const String &p_class, const Ref