diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/debugger/editor_profiler.cpp | 22 | ||||
-rw-r--r-- | editor/debugger/editor_profiler.h | 3 | ||||
-rw-r--r-- | editor/debugger/script_editor_debugger.cpp | 9 | ||||
-rw-r--r-- | editor/editor_fonts.cpp | 10 | ||||
-rw-r--r-- | editor/editor_node.cpp | 17 | ||||
-rw-r--r-- | editor/editor_node.h | 2 | ||||
-rw-r--r-- | editor/editor_resource_picker.cpp | 2 | ||||
-rw-r--r-- | editor/editor_undo_redo_manager.cpp | 7 | ||||
-rw-r--r-- | editor/export/editor_export_platform.cpp | 13 | ||||
-rw-r--r-- | editor/export/project_export.cpp | 15 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 36 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.h | 2 | ||||
-rw-r--r-- | editor/plugins/sprite_frames_editor_plugin.cpp | 31 | ||||
-rw-r--r-- | editor/plugins/sprite_frames_editor_plugin.h | 2 |
14 files changed, 147 insertions, 24 deletions
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index cf48366bd3..a882275375 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -104,6 +104,10 @@ void EditorProfiler::clear() { updating_frame = false; hover_metric = -1; seeking = false; + + // Ensure button text (start, stop) is correct + _set_button_text(); + emit_signal(SNAME("enable_profiling"), activate->is_pressed()); } static String _get_percent_txt(float p_value, float p_total) { @@ -374,15 +378,23 @@ void EditorProfiler::_update_frame() { updating_frame = false; } -void EditorProfiler::_activate_pressed() { +void EditorProfiler::_set_button_text() { if (activate->is_pressed()) { activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); activate->set_text(TTR("Stop")); - _clear_pressed(); } else { activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); activate->set_text(TTR("Start")); } +} + +void EditorProfiler::_activate_pressed() { + _set_button_text(); + + if (activate->is_pressed()) { + _clear_pressed(); + } + emit_signal(SNAME("enable_profiling"), activate->is_pressed()); } @@ -499,8 +511,12 @@ void EditorProfiler::_bind_methods() { ADD_SIGNAL(MethodInfo("break_request")); } -void EditorProfiler::set_enabled(bool p_enable) { +void EditorProfiler::set_enabled(bool p_enable, bool p_clear) { + activate->set_pressed(false); activate->set_disabled(!p_enable); + if (p_clear) { + clear(); + } } bool EditorProfiler::is_profiling() { diff --git a/editor/debugger/editor_profiler.h b/editor/debugger/editor_profiler.h index df92125258..e9ecc285ed 100644 --- a/editor/debugger/editor_profiler.h +++ b/editor/debugger/editor_profiler.h @@ -122,6 +122,7 @@ private: Timer *frame_delay = nullptr; Timer *plot_delay = nullptr; + void _set_button_text(); void _update_frame(); void _activate_pressed(); @@ -153,7 +154,7 @@ protected: public: void add_frame_metric(const Metric &p_metric, bool p_final = false); - void set_enabled(bool p_enable); + void set_enabled(bool p_enable, bool p_clear = true); bool is_profiling(); bool is_seeking() { return seeking; } void disable_seeking(); diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 5baa9970af..6bc1536cb9 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -52,7 +52,6 @@ #include "editor/plugins/node_3d_editor_plugin.h" #include "main/performance.h" #include "scene/3d/camera_3d.h" -#include "scene/debugger/scene_debugger.h" #include "scene/gui/dialogs.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" @@ -317,7 +316,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da if (!error.is_empty()) { tabs->set_current_tab(0); } - profiler->set_enabled(false); + profiler->set_enabled(false, false); inspector->clear_cache(); // Take a chance to force remote objects update. } else if (p_msg == "debug_exit") { @@ -327,7 +326,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da _update_buttons_state(); _set_reason_text(TTR("Execution resumed."), MESSAGE_SUCCESS); emit_signal(SNAME("breaked"), false, false, "", false); - profiler->set_enabled(true); + profiler->set_enabled(true, false); profiler->disable_seeking(); } else if (p_msg == "set_pid") { ERR_FAIL_COND(p_data.size() < 1); @@ -916,6 +915,8 @@ void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) { _clear_errors_list(); stop(); + profiler->set_enabled(true, true); + peer = p_peer; ERR_FAIL_COND(p_peer.is_null()); @@ -971,6 +972,8 @@ void ScriptEditorDebugger::stop() { res_path_cache.clear(); profiler_signature.clear(); + profiler->set_enabled(true, false); + inspector->edit(nullptr); _update_buttons_state(); } diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index fffe77f1c4..c31d13d122 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -96,6 +96,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EditorSettings::get_singleton()->get("interface/editor/font_subpixel_positioning"); TextServer::Hinting font_hinting; + TextServer::Hinting font_mono_hinting; switch (font_hinting_setting) { case 0: // The "Auto" setting uses the setting that best matches the OS' font rendering: @@ -104,18 +105,23 @@ void editor_register_fonts(Ref<Theme> p_theme) { // - Linux has configurable font hinting, but most distributions including Ubuntu default to "Light". #ifdef MACOS_ENABLED font_hinting = TextServer::HINTING_NONE; + font_mono_hinting = TextServer::HINTING_NONE; #else font_hinting = TextServer::HINTING_LIGHT; + font_mono_hinting = TextServer::HINTING_LIGHT; #endif break; case 1: font_hinting = TextServer::HINTING_NONE; + font_mono_hinting = TextServer::HINTING_NONE; break; case 2: font_hinting = TextServer::HINTING_LIGHT; + font_mono_hinting = TextServer::HINTING_LIGHT; break; default: font_hinting = TextServer::HINTING_NORMAL; + font_mono_hinting = TextServer::HINTING_LIGHT; break; } @@ -163,7 +169,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { default_font_bold->set_fallbacks(fallbacks_bold); default_font_bold_msdf->set_fallbacks(fallbacks_bold); - Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning); + Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_mono_hinting, font_antialiasing, true, font_subpixel_positioning); default_font_mono->set_fallbacks(fallbacks); // Init base font configs and load custom fonts. @@ -260,7 +266,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> mono_fc; mono_fc.instantiate(); if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiasing, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_mono_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_mono); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 9dc4c2c953..8eaddcb7e1 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -3932,7 +3932,7 @@ void EditorNode::edit_foreign_resource(Ref<Resource> p_resource) { InspectorDock::get_singleton()->call_deferred("edit_resource", p_resource); } -bool EditorNode::is_resource_read_only(Ref<Resource> p_resource) { +bool EditorNode::is_resource_read_only(Ref<Resource> p_resource, bool p_foreign_resources_are_writable) { ERR_FAIL_COND_V(p_resource.is_null(), false); String path = p_resource->get_path(); @@ -3944,7 +3944,11 @@ bool EditorNode::is_resource_read_only(Ref<Resource> p_resource) { // If the base resource is a packed scene, we treat it as read-only if it is not the currently edited scene. if (ResourceLoader::get_resource_type(base) == "PackedScene") { if (!get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->get_scene_file_path() != base) { - return true; + // If we have not flagged foreign resources as writable or the base scene the resource is + // part was imported, it can be considered read-only. + if (!p_foreign_resources_are_writable || FileAccess::exists(base + ".import")) { + return true; + } } } else { // If a corresponding .import file exists for the base file, we assume it to be imported and should therefore treated as read-only. @@ -6750,8 +6754,10 @@ EditorNode::EditorNode() { project_menu->add_separator(); project_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/export", TTR("Export..."), Key::NONE, TTR("Export")), FILE_EXPORT_PROJECT); +#ifndef ANDROID_ENABLED project_menu->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE); project_menu->add_item(TTR("Open User Data Folder"), RUN_USER_DATA_FOLDER); +#endif project_menu->add_separator(); project_menu->add_item(TTR("Customize Engine Build Configuration..."), TOOLS_BUILD_PROFILE_MANAGER); @@ -6814,12 +6820,14 @@ EditorNode::EditorNode() { settings_menu->set_item_tooltip(-1, TTR("Screenshots are stored in the Editor Data/Settings Folder.")); +#ifndef ANDROID_ENABLED ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KeyModifierMask::SHIFT | Key::F11); ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::F); settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/fullscreen_mode"), SETTINGS_TOGGLE_FULLSCREEN); - +#endif settings_menu->add_separator(); +#ifndef ANDROID_ENABLED if (OS::get_singleton()->get_data_path() == OS::get_singleton()->get_config_path()) { // Configuration and data folders are located in the same place (Windows/MacOS). settings_menu->add_item(TTR("Open Editor Data/Settings Folder"), SETTINGS_EDITOR_DATA_FOLDER); @@ -6829,9 +6837,12 @@ EditorNode::EditorNode() { settings_menu->add_item(TTR("Open Editor Settings Folder"), SETTINGS_EDITOR_CONFIG_FOLDER); } settings_menu->add_separator(); +#endif settings_menu->add_item(TTR("Manage Editor Features..."), SETTINGS_MANAGE_FEATURE_PROFILES); +#ifndef ANDROID_ENABLED settings_menu->add_item(TTR("Manage Export Templates..."), SETTINGS_MANAGE_EXPORT_TEMPLATES); +#endif help_menu = memnew(PopupMenu); help_menu->set_name(TTR("Help")); diff --git a/editor/editor_node.h b/editor/editor_node.h index df3d2ae0f8..200d68908c 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -784,7 +784,7 @@ public: void open_request(const String &p_path); void edit_foreign_resource(Ref<Resource> p_resource); - bool is_resource_read_only(Ref<Resource> p_resource); + bool is_resource_read_only(Ref<Resource> p_resource, bool p_foreign_resources_are_writable = false); bool is_changing_scene() const; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 5346052f4d..84cb085551 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -186,7 +186,7 @@ void EditorResourcePicker::_update_menu_items() { // Add options for changing existing value of the resource. if (edited_resource.is_valid()) { // Determine if the edited resource is part of another scene (foreign) which was imported - bool is_edited_resource_foreign_import = EditorNode::get_singleton()->is_resource_read_only(edited_resource); + bool is_edited_resource_foreign_import = EditorNode::get_singleton()->is_resource_read_only(edited_resource, true); // If the resource is determined to be foreign and imported, change the menu entry's description to 'inspect' rather than 'edit' // since will only be able to view its properties in read-only mode. diff --git a/editor/editor_undo_redo_manager.cpp b/editor/editor_undo_redo_manager.cpp index eca2b3143b..8c04a4d595 100644 --- a/editor/editor_undo_redo_manager.cpp +++ b/editor/editor_undo_redo_manager.cpp @@ -124,7 +124,7 @@ void EditorUndoRedoManager::create_action(const String &p_name, UndoRedo::MergeM create_action_for_history(p_name, INVALID_HISTORY, p_mode); if (p_custom_context) { - // This assigns context to pending action. + // This assigns history to pending action. get_history_for_object(p_custom_context); } } @@ -218,7 +218,10 @@ void EditorUndoRedoManager::add_undo_reference(Object *p_object) { } void EditorUndoRedoManager::commit_action(bool p_execute) { - ERR_FAIL_COND(pending_action.history_id == INVALID_HISTORY); + if (pending_action.history_id == INVALID_HISTORY) { + return; // Empty action, do nothing. + } + is_committing = true; History &history = get_or_create_history(pending_action.history_id); diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 2a444bb04f..bcc85570ed 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -1619,21 +1619,24 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags } bool EditorExportPlatform::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { + bool valid = true; +#ifndef ANDROID_ENABLED String templates_error; - bool valid_export_configuration = has_valid_export_configuration(p_preset, templates_error, r_missing_templates); - - String project_configuration_error; - bool valid_project_configuration = has_valid_project_configuration(p_preset, project_configuration_error); + valid = valid && has_valid_export_configuration(p_preset, templates_error, r_missing_templates); if (!templates_error.is_empty()) { r_error += templates_error; } +#endif + + String project_configuration_error; + valid = valid && has_valid_project_configuration(p_preset, project_configuration_error); if (!project_configuration_error.is_empty()) { r_error += project_configuration_error; } - return valid_export_configuration && valid_project_configuration; + return valid; } EditorExportPlatform::EditorExportPlatform() { diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 00a0e08d3a..8c67885971 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -932,8 +932,10 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) { } void ProjectExportDialog::_export_all_dialog() { +#ifndef ANDROID_ENABLED export_all_dialog->show(); export_all_dialog->popup_centered(Size2(300, 80)); +#endif } void ProjectExportDialog::_export_all_dialog_action(const String &p_str) { @@ -1194,11 +1196,16 @@ ProjectExportDialog::ProjectExportDialog() { set_cancel_button_text(TTR("Close")); set_ok_button_text(TTR("Export PCK/ZIP...")); + get_ok_button()->set_disabled(true); +#ifdef ANDROID_ENABLED + export_button = memnew(Button); + export_button->hide(); +#else export_button = add_button(TTR("Export Project..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export"); +#endif export_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_project)); // Disable initially before we select a valid preset export_button->set_disabled(true); - get_ok_button()->set_disabled(true); export_all_dialog = memnew(ConfirmationDialog); add_child(export_all_dialog); @@ -1208,8 +1215,14 @@ ProjectExportDialog::ProjectExportDialog() { export_all_dialog->add_button(TTR("Debug"), true, "debug"); export_all_dialog->add_button(TTR("Release"), true, "release"); export_all_dialog->connect("custom_action", callable_mp(this, &ProjectExportDialog::_export_all_dialog_action)); +#ifdef ANDROID_ENABLED + export_all_dialog->hide(); + export_all_button = memnew(Button); + export_all_button->hide(); +#else export_all_button = add_button(TTR("Export All..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export"); +#endif export_all_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_all_dialog)); export_all_button->set_disabled(true); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 41061c3fc3..b5798a5784 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1891,6 +1891,39 @@ void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_ } } +Array ResourceImporterScene::_get_skinned_pose_transforms(ImporterMeshInstance3D *p_src_mesh_node) { + Array skin_pose_transform_array; + + const Ref<Skin> skin = p_src_mesh_node->get_skin(); + if (skin.is_valid()) { + NodePath skeleton_path = p_src_mesh_node->get_skeleton_path(); + const Node *node = p_src_mesh_node->get_node_or_null(skeleton_path); + const Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node); + if (skeleton) { + int bind_count = skin->get_bind_count(); + + for (int i = 0; i < bind_count; i++) { + Transform3D bind_pose = skin->get_bind_pose(i); + String bind_name = skin->get_bind_name(i); + + int bone_idx = bind_name.is_empty() ? skin->get_bind_bone(i) : skeleton->find_bone(bind_name); + ERR_FAIL_COND_V(bone_idx >= skeleton->get_bone_count(), Array()); + + Transform3D bp_global_rest; + if (bone_idx >= 0) { + bp_global_rest = skeleton->get_bone_global_pose(bone_idx); + } else { + bp_global_rest = skeleton->get_bone_global_pose(i); + } + + skin_pose_transform_array.push_back(bp_global_rest * bind_pose); + } + } + } + + return skin_pose_transform_array; +} + void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<Vector<uint8_t>> &r_lightmap_caches) { ImporterMeshInstance3D *src_mesh_node = Object::cast_to<ImporterMeshInstance3D>(p_node); if (src_mesh_node) { @@ -2007,7 +2040,8 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } if (generate_lods) { - src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle); + Array skin_pose_transform_array = _get_skinned_pose_transforms(src_mesh_node); + src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle, skin_pose_transform_array); } if (create_shadow_meshes) { diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index da37893cc5..77bc06533c 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -34,6 +34,7 @@ #include "core/error/error_macros.h" #include "core/io/resource_importer.h" #include "core/variant/dictionary.h" +#include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/node_3d.h" #include "scene/resources/animation.h" #include "scene/resources/mesh.h" @@ -208,6 +209,7 @@ class ResourceImporterScene : public ResourceImporter { SHAPE_TYPE_CAPSULE, }; + Array _get_skinned_pose_transforms(ImporterMeshInstance3D *p_src_mesh_node); void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner); void _generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<Vector<uint8_t>> &r_lightmap_caches); void _add_shapes(Node *p_node, const Vector<Ref<Shape3D>> &p_shapes); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index ae21aad337..d0a1ddafa1 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -984,11 +984,17 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) { } void SpriteFramesEditor::edit(SpriteFrames *p_frames) { - if (frames == p_frames) { + bool new_read_only_state = false; + if (p_frames) { + new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_frames); + } + + if (frames == p_frames && new_read_only_state == read_only) { return; } frames = p_frames; + read_only = new_read_only_state; if (p_frames) { if (!p_frames->has_animation(edited_anim)) { @@ -1009,6 +1015,20 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) { } else { hide(); } + + new_anim->set_disabled(read_only); + remove_anim->set_disabled(read_only); + anim_speed->set_editable(!read_only); + anim_loop->set_disabled(read_only); + load->set_disabled(read_only); + load_sheet->set_disabled(read_only); + copy->set_disabled(read_only); + paste->set_disabled(read_only); + empty->set_disabled(read_only); + empty2->set_disabled(read_only); + move_up->set_disabled(read_only); + move_down->set_disabled(read_only); + _delete->set_disabled(read_only); } void SpriteFramesEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { @@ -1016,6 +1036,10 @@ void SpriteFramesEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { } Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + if (read_only) { + return false; + } + if (!frames->has_animation(edited_anim)) { return false; } @@ -1038,6 +1062,10 @@ Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f } bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + if (read_only) { + return false; + } + Dictionary d = p_data; if (!d.has("type")) { @@ -1169,6 +1197,7 @@ SpriteFramesEditor::SpriteFramesEditor() { remove_anim->set_flat(true); remove_anim->set_tooltip_text(TTR("Remove Animation")); hbc_animlist->add_child(remove_anim); + remove_anim->set_disabled(true); remove_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove)); anim_search_box = memnew(LineEdit); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index f2530b732f..092f556c63 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -57,6 +57,8 @@ class SpriteFramesEditor : public HSplitContainer { }; int dominant_param = PARAM_FRAME_COUNT; + bool read_only = false; + Button *load = nullptr; Button *load_sheet = nullptr; Button *_delete = nullptr; |