diff options
-rw-r--r-- | core/script_language.h | 2 | ||||
-rw-r--r-- | doc/classes/AcceptDialog.xml | 5 | ||||
-rw-r--r-- | editor/create_dialog.cpp | 36 | ||||
-rw-r--r-- | editor/editor_data.cpp | 45 | ||||
-rw-r--r-- | editor/editor_data.h | 8 | ||||
-rw-r--r-- | editor/editor_file_system.cpp | 27 | ||||
-rw-r--r-- | editor/editor_file_system.h | 5 | ||||
-rw-r--r-- | editor/property_editor.cpp | 18 | ||||
-rw-r--r-- | editor/scene_tree_dock.cpp | 30 | ||||
-rw-r--r-- | modules/gdscript/gdscript.cpp | 8 | ||||
-rw-r--r-- | modules/gdscript/gdscript.h | 2 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 26 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.h | 1 | ||||
-rw-r--r-- | scene/main/node.cpp | 2 | ||||
-rw-r--r-- | scene/resources/texture.cpp | 6 |
15 files changed, 178 insertions, 43 deletions
diff --git a/core/script_language.h b/core/script_language.h index a5987e2a78..71b705e960 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -315,7 +315,7 @@ public: virtual void frame(); virtual bool handles_global_class_type(const String &p_type) const { return false; } - virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL) const { return String(); } + virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL, String *r_icon_path = NULL) const { return String(); } virtual ~ScriptLanguage() {} }; diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml index 20d8bebd6b..7e871d68cb 100644 --- a/doc/classes/AcceptDialog.xml +++ b/doc/classes/AcceptDialog.xml @@ -60,7 +60,8 @@ </methods> <members> <member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok"> - If [code]true[/code] the dialog is hidden when accepted. Default value: [code]true[/code]. + If [code]true[/code] the dialog is hidden when the OK button is pressed. You can set it to [code]false[/code] if you want to do e.g. input validation when receiving the [signal confirmed] signal, and handle hiding the dialog in your own logic. Default value: [code]true[/code]. + Note: Some nodes derived from this class can have a different default value, and potentially their own built-in logic overriding this setting. For example [FileDialog] defaults to [code]false[/code], and has its own input validation code that is called when you press OK, which eventually hides the dialog if the input is valid. As such this property can't be used in [FileDialog] to disable hiding the dialog when pressing OK. </member> <member name="dialog_text" type="String" setter="set_text" getter="get_text"> The text displayed by this dialog. @@ -69,7 +70,7 @@ <signals> <signal name="confirmed"> <description> - Emitted when the dialog is accepted. + Emitted when the dialog is accepted, i.e. the OK button is pressed. </description> </signal> <signal name="custom_action"> diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 5dd5b7fcc5..0bc4244642 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -157,6 +157,18 @@ Ref<Texture> CreateDialog::_get_editor_icon(const String &p_type) const { return get_icon(p_type, "EditorIcons"); } + if (ScriptServer::is_global_class(p_type)) { + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(p_type); + RES icon; + if (FileAccess::exists(icon_path)) { + icon = ResourceLoader::load(icon_path); + } + if (!icon.is_valid()) { + icon = get_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons"); + } + return icon; + } + const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types(); for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) { const Vector<EditorData::CustomType> &ct = E->value(); @@ -180,7 +192,7 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p return; bool cpp_type = ClassDB::class_exists(p_type); - EditorData &ed = EditorNode::get_singleton()->get_editor_data(); + EditorData &ed = EditorNode::get_editor_data(); if (p_type == base_type) return; @@ -262,13 +274,7 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p const String &description = EditorHelp::get_doc_data()->class_list[p_type].brief_description; item->set_tooltip(0, description); - if (cpp_type && has_icon(p_type, "EditorIcons")) { - - item->set_icon(0, get_icon(p_type, "EditorIcons")); - } else if (!cpp_type && has_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")) { - - item->set_icon(0, get_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")); - } + item->set_icon(0, _get_editor_icon(p_type)); p_types[p_type] = item; } @@ -287,7 +293,7 @@ void CreateDialog::_update_search() { HashMap<String, TreeItem *> types; TreeItem *root = search_options->create_item(); - EditorData &ed = EditorNode::get_singleton()->get_editor_data(); + EditorData &ed = EditorNode::get_editor_data(); root->set_text(0, base_type); if (has_icon(base_type, "EditorIcons")) { @@ -330,7 +336,7 @@ void CreateDialog::_update_search() { break; } - type = ClassDB::get_parent_class(type); + type = cpp_type ? ClassDB::get_parent_class(type) : ed.script_class_get_base(type); } if (found) @@ -490,16 +496,8 @@ Object *CreateDialog::instance_selected() { custom = md; if (custom != String()) { - if (ScriptServer::is_global_class(custom)) { - RES script = ResourceLoader::load(ScriptServer::get_global_class_path(custom)); - ERR_FAIL_COND_V(!script.is_valid(), NULL); - - Object *obj = ClassDB::instance(ScriptServer::get_global_class_base(custom)); - ERR_FAIL_COND_V(!obj, NULL); - - obj->set_script(script.get_ref_ptr()); - return obj; + return EditorNode::get_editor_data().script_class_instance(custom); } return EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom); } else { diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index f4ef11eb36..69c120bb3c 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -888,11 +888,56 @@ StringName EditorData::script_class_get_base(const String &p_class) { return script->get_language()->get_global_class_name(base_script->get_path()); } +Object *EditorData::script_class_instance(const String &p_class) { + if (ScriptServer::is_global_class(p_class)) { + Object *obj = ClassDB::instance(ScriptServer::get_global_class_base(p_class)); + if (obj) { + RES script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class)); + if (script.is_valid()) + obj->set_script(script.get_ref_ptr()); + + RES icon = ResourceLoader::load(script_class_get_icon_path(p_class)); + if (icon.is_valid()) + obj->set_meta("_editor_icon", icon); + + return obj; + } + } + return NULL; +} + +void EditorData::script_class_save_icon_paths() { + List<StringName> keys; + _script_class_icon_paths.get_key_list(&keys); + + Dictionary d; + for (List<StringName>::Element *E = keys.front(); E; E = E->next()) { + d[E->get()] = _script_class_icon_paths[E->get()]; + } + + ProjectSettings::get_singleton()->set("_global_script_class_icons", d); + ProjectSettings::get_singleton()->save(); +} + +void EditorData::script_class_load_icon_paths() { + script_class_clear_icon_paths(); + + Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons"); + List<Variant> keys; + d.get_key_list(&keys); + + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { + String key = E->get().operator String(); + _script_class_icon_paths[key] = d[key]; + } +} + EditorData::EditorData() { current_edited_scene = -1; //load_imported_scenes_from_globals(); + script_class_load_icon_paths(); } /////////// diff --git a/editor/editor_data.h b/editor/editor_data.h index fac6635cd2..285769aa78 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -146,6 +146,8 @@ private: bool _find_updated_instances(Node *p_root, Node *p_node, Set<String> &checked_paths); + HashMap<StringName, String> _script_class_icon_paths; + public: EditorPlugin *get_editor(Object *p_object); EditorPlugin *get_subeditor(Object *p_object); @@ -213,6 +215,12 @@ public: bool script_class_is_parent(const String &p_class, const String &p_inherits); StringName script_class_get_base(const String &p_class); + Object *script_class_instance(const String &p_class); + String script_class_get_icon_path(const String &p_class) const { return _script_class_icon_paths.has(p_class) ? _script_class_icon_paths[p_class] : String(); } + void script_class_set_icon_path(const String &p_class, const String &p_icon_path) { _script_class_icon_paths[p_class] = p_icon_path; } + void script_class_clear_icon_paths() { _script_class_icon_paths.clear(); } + void script_class_save_icon_paths(); + void script_class_load_icon_paths(); EditorData(); }; diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 671ac755b2..9562a8c63c 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -133,6 +133,10 @@ String EditorFileSystemDirectory::get_file_script_class_extends(int p_idx) const return files[p_idx]->script_class_extends; } +String EditorFileSystemDirectory::get_file_script_class_icon_path(int p_idx) const { + return files[p_idx]->script_class_icon_path; +} + StringName EditorFileSystemDirectory::get_file_type(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, files.size(), ""); @@ -233,6 +237,7 @@ void EditorFileSystem::_scan_filesystem() { fc.import_valid = split[4].to_int64() != 0; fc.script_class_name = split[5].get_slice("<>", 0); fc.script_class_extends = split[5].get_slice("<>", 1); + fc.script_class_icon_path = split[5].get_slice("<>", 2); String deps = split[6].strip_edges(); if (deps.length()) { @@ -721,6 +726,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess fi->import_valid = fc->import_valid; fi->script_class_name = fc->script_class_name; fi->script_class_extends = fc->script_class_extends; + fi->script_class_icon_path = fc->script_class_icon_path; if (fc->type == String()) { fi->type = ResourceLoader::get_resource_type(path); @@ -731,7 +737,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess } else { fi->type = ResourceFormatImporter::get_singleton()->get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->modified_time = 0; fi->import_modified_time = 0; fi->import_valid = ResourceLoader::is_import_valid(path); @@ -753,10 +759,11 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess fi->import_valid = true; fi->script_class_name = fc->script_class_name; fi->script_class_extends = fc->script_class_extends; + fi->script_class_icon_path = fc->script_class_icon_path; } else { //new or modified time fi->type = ResourceLoader::get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->deps = _get_dependencies(path); fi->modified_time = mt; fi->import_modified_time = 0; @@ -855,7 +862,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const fi->modified_time = FileAccess::get_modified_time(path); fi->import_modified_time = 0; fi->type = ResourceLoader::get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->import_valid = ResourceLoader::is_import_valid(path); { @@ -1110,7 +1117,7 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, for (int i = 0; i < p_dir->files.size(); i++) { - String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends; + String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path; s += "::"; for (int j = 0; j < p_dir->files[i]->deps.size(); j++) { @@ -1316,19 +1323,22 @@ Vector<String> EditorFileSystem::_get_dependencies(const String &p_path) { return ret; } -String EditorFileSystem::_get_global_script_class(const String &p_type, const String &p_path, String *r_extends) const { +String EditorFileSystem::_get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const { for (int i = 0; i < ScriptServer::get_language_count(); i++) { if (ScriptServer::get_language(i)->handles_global_class_type(p_type)) { String global_name; String extends; + String icon_path; - global_name = ScriptServer::get_language(i)->get_global_class_name(p_path, &extends); + global_name = ScriptServer::get_language(i)->get_global_class_name(p_path, &extends, &icon_path); *r_extends = extends; + *r_icon_path = icon_path; return global_name; } } *r_extends = String(); + *r_icon_path = String(); return String(); } @@ -1346,8 +1356,8 @@ void EditorFileSystem::_scan_script_classes(EditorFileSystemDirectory *p_dir) { lang = ScriptServer::get_language(j)->get_name(); } } - ScriptServer::add_global_class(files[i]->script_class_name, files[i]->script_class_extends, lang, p_dir->get_file_path(i)); + EditorNode::get_editor_data().script_class_set_icon_path(files[i]->script_class_name, files[i]->script_class_icon_path); } for (int i = 0; i < p_dir->get_subdir_count(); i++) { _scan_script_classes(p_dir->get_subdir(i)); @@ -1366,6 +1376,7 @@ void EditorFileSystem::update_script_classes() { } ScriptServer::save_global_classes(); + EditorNode::get_editor_data().script_class_save_icon_paths(); emit_signal("script_classes_updated"); } @@ -1438,7 +1449,7 @@ void EditorFileSystem::update_file(const String &p_file) { } fs->files[cpos]->type = type; - fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends); + fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path); fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); fs->files[cpos]->deps = _get_dependencies(p_file); fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file); diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 1aa35f4782..75ca79932f 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -60,6 +60,7 @@ class EditorFileSystemDirectory : public Object { bool verified; //used for checking changes String script_class_name; String script_class_extends; + String script_class_icon_path; }; struct FileInfoSort { @@ -90,6 +91,7 @@ public: bool get_file_import_is_valid(int p_idx) const; String get_file_script_class_name(int p_idx) const; //used for scripts String get_file_script_class_extends(int p_idx) const; //used for scripts + String get_file_script_class_icon_path(int p_idx) const; //used for scripts EditorFileSystemDirectory *get_parent(); @@ -163,6 +165,7 @@ class EditorFileSystem : public Node { bool import_valid; String script_class_name; String script_class_extends; + String script_class_icon_path; }; HashMap<String, FileCache> file_cache; @@ -225,7 +228,7 @@ class EditorFileSystem : public Node { volatile bool update_script_classes_queued; void _queue_update_script_classes(); - String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends) const; + String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const; protected: void _notification(int p_what); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index b370a711e3..408e67149a 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -287,7 +287,11 @@ void CustomPropertyEditor::_menu_option(int p_which) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_BREAK(!obj); @@ -1132,7 +1136,11 @@ void CustomPropertyEditor::_type_create_selected(int p_idx) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_FAIL_COND(!obj); @@ -1334,7 +1342,11 @@ void CustomPropertyEditor::_action_pressed(int p_which) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_BREAK(!obj); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index d17bcef92b..607d974025 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -365,10 +365,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptLanguage *l = ScriptServer::get_language(i); if (l->get_type() == existing->get_class()) { - if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { - String name = l->get_global_class_name(existing->get_path(), NULL); - inherits = editor->get_editor_data().script_class_get_base(name); - } else if (l->can_inherit_from_file()) { + String name = l->get_global_class_name(existing->get_path()); + if (ScriptServer::is_global_class(name)) { + if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { + inherits = editor->get_editor_data().script_class_get_base(name); + } else if (l->can_inherit_from_file()) { + inherits = "\"" + existing->get_path() + "\""; + } + } else { inherits = "\"" + existing->get_path() + "\""; } } @@ -395,6 +399,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { const RefPtr empty; editor_data->get_undo_redo().add_do_method(E->get(), "set_script", empty); editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + + editor_data->get_undo_redo().add_do_method(E->get(), "set_meta", "_editor_icon", get_icon(E->get()->get_class(), "EditorIcons")); + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", E->get()->get_meta("_editor_icon")); } } @@ -402,7 +409,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); editor_data->get_undo_redo().commit_action(); - } break; case TOOL_MOVE_UP: case TOOL_MOVE_DOWN: { @@ -1490,9 +1496,23 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { Ref<Script> existing = E->get()->get_script(); editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script.get_ref_ptr()); editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + + String icon_path; + String name = p_script->get_language()->get_global_class_name(p_script->get_path(), NULL, &icon_path); + if (ScriptServer::is_global_class(name)) { + RES icon = ResourceLoader::load(icon_path); + editor_data->get_undo_redo().add_do_method(E->get(), "set_meta", "_editor_icon", icon); + String existing_name = existing.is_valid() ? existing->get_language()->get_global_class_name(existing->get_path()) : String(); + if (existing.is_null() || !ScriptServer::is_global_class(existing_name)) { + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", get_icon(E->get()->get_class(), "EditorIcons")); + } else { + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", editor_data->script_class_get_icon_path(existing_name)); + } + } } editor_data->get_undo_redo().commit_action(); + print_line("test: " + String(Variant(selected.front()->get()->get_meta("_editor_icon")))); editor->push_item(p_script.operator->()); } diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 42ec05e6ce..b987d2897f 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1811,7 +1811,7 @@ bool GDScriptLanguage::handles_global_class_type(const String &p_type) const { return p_type == "GDScript"; } -String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type) const { +String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const { PoolVector<uint8_t> sourcef; Error err; @@ -1876,6 +1876,12 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b } } } + if (r_icon_path) { + if (c->icon_path.empty() || c->icon_path.is_abs_path()) + *r_icon_path = c->icon_path; + else if (c->icon_path.is_rel_path()) + *r_icon_path = p_path.get_base_dir().plus_file(c->icon_path).simplify_path(); + } return c->name; } diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 68e89887b0..d400230f43 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -492,7 +492,7 @@ public: /* GLOBAL CLASSES */ virtual bool handles_global_class_type(const String &p_type) const; - virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL) const; + virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL, String *r_icon_path = NULL) const; GDScriptLanguage(); ~GDScriptLanguage(); diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index e0ed2b332b..bec314866d 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -3429,6 +3429,32 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(2); + if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { + tokenizer->advance(); + + if ((tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING)) { + Variant constant = tokenizer->get_token_constant(); + String icon_path = constant.operator String(); + + String abs_icon_path = icon_path.is_rel_path() ? self_path.get_base_dir().plus_file(icon_path).simplify_path() : icon_path; + if (!FileAccess::exists(abs_icon_path)) { + _set_error("No class icon found at: " + abs_icon_path); + return; + } + + p_class->icon_path = icon_path; + + tokenizer->advance(); + } else { + _set_error("Optional parameter after 'class_name' must be a string constant file path to an icon."); + return; + } + + } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT) { + _set_error("Class icon must be separated by a comma."); + return; + } + } break; case GDScriptTokenizer::TK_PR_TOOL: { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index d8ee4e8159..dbe523a0b9 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -149,6 +149,7 @@ public: StringName extends_file; Vector<StringName> extends_class; DataType base_type; + String icon_path; struct Member { PropertyInfo _export; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 372ad7367e..d6a80bfb1a 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2555,7 +2555,7 @@ void Node::clear_internal_tree_resource_paths() { String Node::get_configuration_warning() const { - if (get_script_instance()) { + if (get_script_instance() && get_script_instance()->has_method("_get_configuration_warning")) { return get_script_instance()->call("_get_configuration_warning"); } return String(); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 2f663431de..96edb17eea 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -621,7 +621,11 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla memdelete(f); - if (bytes != total_size - ofs) { + int expected = total_size - ofs; + if (bytes < expected) { + //this is a compatibility workaround for older format, which saved less mipmaps. It is still recommended the image is reimported. + zeromem(w.ptr() + bytes, (expected - bytes)); + } else if (bytes != expected) { ERR_FAIL_V(ERR_FILE_CORRUPT); } } |