diff options
Diffstat (limited to 'editor/import')
42 files changed, 1413 insertions, 3256 deletions
diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp index b6d0927ce6..2cc534d96d 100644 --- a/editor/import/collada.cpp +++ b/editor/import/collada.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -541,7 +541,10 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & COLLADA_PRINT("node name: " + parser.get_node_name()); - if (!parser.is_empty() && (parser.get_node_name() == "profile_COMMON" || parser.get_node_name() == "technique" || parser.get_node_name() == "extra")) { + if (!parser.is_empty() && + (parser.get_node_name() == "profile_COMMON" || + parser.get_node_name() == "technique" || + parser.get_node_name() == "extra")) { _parse_effect_material(parser, effect, id); // try again } else if (parser.get_node_name() == "newparam") { @@ -551,9 +554,9 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & COLLADA_PRINT("param: " + name + " value:" + String(value)); } else if (parser.get_node_name() == "constant" || - parser.get_node_name() == "lambert" || - parser.get_node_name() == "phong" || - parser.get_node_name() == "blinn") { + parser.get_node_name() == "lambert" || + parser.get_node_name() == "phong" || + parser.get_node_name() == "blinn") { COLLADA_PRINT("shade model: " + parser.get_node_name()); while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { @@ -627,10 +630,11 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & } else if (what == "shininess") { effect.shininess = _parse_param(parser); } - } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && (parser.get_node_name() == "constant" || - parser.get_node_name() == "lambert" || - parser.get_node_name() == "phong" || - parser.get_node_name() == "blinn")) { + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && + (parser.get_node_name() == "constant" || + parser.get_node_name() == "lambert" || + parser.get_node_name() == "phong" || + parser.get_node_name() == "blinn")) { break; } } @@ -681,10 +685,10 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & parser.skip_section(); } } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && - (parser.get_node_name() == "effect" || - parser.get_node_name() == "profile_COMMON" || - parser.get_node_name() == "technique" || - parser.get_node_name() == "extra")) { + (parser.get_node_name() == "effect" || + parser.get_node_name() == "profile_COMMON" || + parser.get_node_name() == "technique" || + parser.get_node_name() == "extra")) { break; } } @@ -1358,7 +1362,7 @@ Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) { } else if (parser.get_node_name() == "skeleton") { parser.read(); String uri = _uri_to_id(parser.get_node_data()); - if (uri != "") { + if (!uri.is_empty()) { geom->skeletons.push_back(uri); } } @@ -1460,7 +1464,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { bool found_name = false; - if (id == "") { + if (id.is_empty()) { id = "%NODEID%" + itos(Math::rand()); } else { @@ -1475,7 +1479,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { Node *node = nullptr; name = parser.has_attribute("name") ? parser.get_attribute_value_safe("name") : parser.get_attribute_value_safe("id"); - if (name == "") { + if (name.is_empty()) { name = id; } else { found_name = true; @@ -1495,7 +1499,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { joint->sid = parser.get_attribute_value_safe("name"); } - if (joint->sid != "") { + if (!joint->sid.is_empty()) { state.sid_to_node_map[joint->sid] = id; } @@ -1692,16 +1696,16 @@ void Collada::_parse_animation(XMLParser &parser) { source_param_types[current_source] = Vector<String>(); } else if (name == "float_array") { - if (current_source != "") { + if (!current_source.is_empty()) { float_sources[current_source] = _read_float_array(parser); } } else if (name == "Name_array") { - if (current_source != "") { + if (!current_source.is_empty()) { string_sources[current_source] = _read_string_array(parser); } } else if (name == "accessor") { - if (current_source != "" && parser.has_attribute("stride")) { + if (!current_source.is_empty() && parser.has_attribute("stride")) { source_strides[current_source] = parser.get_attribute_value("stride").to_int(); } } else if (name == "sampler") { @@ -1721,7 +1725,7 @@ void Collada::_parse_animation(XMLParser &parser) { } } else if (name == "input") { - if (current_sampler != "") { + if (!current_sampler.is_empty()) { samplers[current_sampler][parser.get_attribute_value("semantic")] = parser.get_attribute_value("source"); } @@ -1834,7 +1838,7 @@ void Collada::_parse_animation(XMLParser &parser) { track.component = track.param.get_slice(".", 1).to_upper(); } track.param = track.param.get_slice(".", 0); - if (names.size() > 1 && track.component == "") { + if (names.size() > 1 && track.component.is_empty()) { //this is a guess because the collada spec is ambiguous here... //i suppose if you have many names (outputs) you can't use a component and i should abide to that. track.component = name; @@ -1851,7 +1855,7 @@ void Collada::_parse_animation(XMLParser &parser) { state.referenced_tracks[target].push_back(state.animation_tracks.size() - 1); - if (id != "") { + if (!id.is_empty()) { if (!state.by_id_tracks.has(id)) { state.by_id_tracks[id] = Vector<int>(); } @@ -1949,10 +1953,10 @@ void Collada::_parse_library(XMLParser &parser) { while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "mesh") { - state.mesh_name_map[id] = (name2 != "") ? name2 : id; + state.mesh_name_map[id] = (!name2.is_empty()) ? name2 : id; _parse_mesh_geometry(parser, id, name2); } else if (parser.get_node_name() == "spline") { - state.mesh_name_map[id] = (name2 != "") ? name2 : id; + state.mesh_name_map[id] = (!name2.is_empty()) ? name2 : id; _parse_curve_geometry(parser, id, name2); } else if (!parser.is_empty()) { parser.skip_section(); @@ -2020,7 +2024,7 @@ void Collada::_create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton bool Collada::_remove_node(Node *p_parent, Node *p_node) { for (int i = 0; i < p_parent->children.size(); i++) { if (p_parent->children[i] == p_node) { - p_parent->children.remove(i); + p_parent->children.remove_at(i); return true; } if (_remove_node(p_parent->children[i], p_node)) { @@ -2034,7 +2038,7 @@ bool Collada::_remove_node(Node *p_parent, Node *p_node) { void Collada::_remove_node(VisualScene *p_vscene, Node *p_node) { for (int i = 0; i < p_vscene->root_nodes.size(); i++) { if (p_vscene->root_nodes[i] == p_node) { - p_vscene->root_nodes.remove(i); + p_vscene->root_nodes.remove_at(i); return; } if (_remove_node(p_vscene->root_nodes[i], p_node)) { @@ -2095,19 +2099,19 @@ void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) { } void Collada::_merge_skeletons2(VisualScene *p_vscene) { - for (Map<String, SkinControllerData>::Element *E = state.skin_controller_data_map.front(); E; E = E->next()) { - SkinControllerData &cd = E->get(); + for (KeyValue<String, SkinControllerData> &E : state.skin_controller_data_map) { + SkinControllerData &cd = E.value; NodeSkeleton *skeleton = nullptr; - for (Map<String, Transform3D>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) { + for (const KeyValue<String, Transform3D> &F : cd.bone_rest_map) { String name; - if (!state.sid_to_node_map.has(F->key())) { + if (!state.sid_to_node_map.has(F.key)) { continue; } - name = state.sid_to_node_map[F->key()]; + name = state.sid_to_node_map[F.key]; ERR_CONTINUE(!state.scene_map.has(name)); @@ -2248,9 +2252,9 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it //make rests relative to the skeleton (they seem to be always relative to world) - for (Map<String, Transform3D>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) { - E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton - state.bone_rest_map[E->key()] = E->get(); // make it remember where the bone is globally, now that it's relative + for (KeyValue<String, Transform3D> &E : skin.bone_rest_map) { + E.value = skel_inv * E.value; //make the bone rest local to the skeleton + state.bone_rest_map[E.key] = E.value; // make it remember where the bone is globally, now that it's relative } //but most exporters seem to work only if i do this.. @@ -2267,7 +2271,7 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L for (int i = 0; i < p_node->children.size(); i++) { if (_move_geometry_to_skeletons(p_vscene, p_node->children[i], p_mgeom)) { - p_node->children.remove(i); + p_node->children.remove_at(i); i--; } } @@ -2282,7 +2286,7 @@ void Collada::_find_morph_nodes(VisualScene *p_vscene, Node *p_node) { if (nj->controller) { String base = nj->source; - while (base != "" && !state.mesh_data_map.has(base)) { + while (!base.is_empty() && !state.mesh_data_map.has(base)) { if (state.skin_controller_data_map.has(base)) { SkinControllerData &sk = state.skin_controller_data_map[base]; base = sk.base; @@ -2302,8 +2306,8 @@ void Collada::_find_morph_nodes(VisualScene *p_vscene, Node *p_node) { } void Collada::_optimize() { - for (Map<String, VisualScene>::Element *E = state.visual_scene_map.front(); E; E = E->next()) { - VisualScene &vs = E->get(); + for (KeyValue<String, VisualScene> &E : state.visual_scene_map) { + VisualScene &vs = E.value; for (int i = 0; i < vs.root_nodes.size(); i++) { _create_skeletons(&vs.root_nodes.write[i]); } @@ -2321,7 +2325,7 @@ void Collada::_optimize() { for (int i = 0; i < vs.root_nodes.size(); i++) { List<Node *> mgeom; if (_move_geometry_to_skeletons(&vs, vs.root_nodes[i], &mgeom)) { - vs.root_nodes.remove(i); + vs.root_nodes.remove_at(i); i--; } diff --git a/editor/import/collada.h b/editor/import/collada.h index 5e38637504..b5e4cd9983 100644 --- a/editor/import/collada.h +++ b/editor/import/collada.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/editor/import/dynamicfont_import_settings.cpp b/editor/import/dynamicfont_import_settings.cpp index 37ca40287f..f4b1468314 100644 --- a/editor/import/dynamicfont_import_settings.cpp +++ b/editor/import/dynamicfont_import_settings.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -92,6 +92,8 @@ struct UniRange { String name; }; +// Unicode Character Blocks +// Source: https://www.unicode.org/Public/14.0.0/ucd/Blocks.txt static UniRange unicode_ranges[] = { { 0x0000, 0x007F, U"Basic Latin" }, { 0x0080, 0x00FF, U"Latin-1 Supplement" }, @@ -109,10 +111,11 @@ static UniRange unicode_ranges[] = { { 0x0700, 0x074F, U"Syriac" }, { 0x0750, 0x077F, U"Arabic Supplement" }, { 0x0780, 0x07BF, U"Thaana" }, - { 0x07C0, 0x07FF, U"N'Ko" }, + { 0x07C0, 0x07FF, U"NKo" }, { 0x0800, 0x083F, U"Samaritan" }, { 0x0840, 0x085F, U"Mandaic" }, { 0x0860, 0x086F, U"Syriac Supplement" }, + { 0x0870, 0x089F, U"Arabic Extended-B" }, { 0x08A0, 0x08FF, U"Arabic Extended-A" }, { 0x0900, 0x097F, U"Devanagari" }, { 0x0980, 0x09FF, U"Bengali" }, @@ -239,9 +242,12 @@ static UniRange unicode_ranges[] = { { 0xAB30, 0xAB6F, U"Latin Extended-E" }, { 0xAB70, 0xABBF, U"Cherokee Supplement" }, { 0xABC0, 0xABFF, U"Meetei Mayek" }, + { 0xAC00, 0xD7AF, U"Hangul Syllables" }, { 0xD7B0, 0xD7FF, U"Hangul Jamo Extended-B" }, - //{ 0xF800, 0xDFFF, U"Surrogates" }, - { 0xE000, 0xE2FE, U"Private Use Area" }, + //{ 0xD800, 0xDB7F, U"High Surrogates" }, + //{ 0xDB80, 0xDBFF, U"High Private Use Surrogates" }, + //{ 0xDC00, 0xDFFF, U"Low Surrogates" }, + { 0xE000, 0xF8FF, U"Private Use Area" }, { 0xF900, 0xFAFF, U"CJK Compatibility Ideographs" }, { 0xFB00, 0xFB4F, U"Alphabetic Presentation Forms" }, { 0xFB50, 0xFDFF, U"Arabic Presentation Forms-A" }, @@ -273,7 +279,9 @@ static UniRange unicode_ranges[] = { { 0x104B0, 0x104FF, U"Osage" }, { 0x10500, 0x1052F, U"Elbasan" }, { 0x10530, 0x1056F, U"Caucasian Albanian" }, + { 0x10570, 0x105BF, U"Vithkuqi" }, { 0x10600, 0x1077F, U"Linear A" }, + { 0x10780, 0x107BF, U"Latin Extended-F" }, { 0x10800, 0x1083F, U"Cypriot Syllabary" }, { 0x10840, 0x1085F, U"Imperial Aramaic" }, { 0x10860, 0x1087F, U"Palmyrene" }, @@ -298,6 +306,7 @@ static UniRange unicode_ranges[] = { { 0x10E80, 0x10EBF, U"Yezidi" }, { 0x10F00, 0x10F2F, U"Old Sogdian" }, { 0x10F30, 0x10F6F, U"Sogdian" }, + { 0x10F70, 0x10FAF, U"Old Uyghur" }, { 0x10FB0, 0x10FDF, U"Chorasmian" }, { 0x10FE0, 0x10FFF, U"Elymaic" }, { 0x11000, 0x1107F, U"Brahmi" }, @@ -317,13 +326,14 @@ static UniRange unicode_ranges[] = { { 0x11600, 0x1165F, U"Modi" }, { 0x11660, 0x1167F, U"Mongolian Supplement" }, { 0x11680, 0x116CF, U"Takri" }, - { 0x11700, 0x1173F, U"Ahom" }, + { 0x11700, 0x1174F, U"Ahom" }, { 0x11800, 0x1184F, U"Dogra" }, { 0x118A0, 0x118FF, U"Warang Citi" }, { 0x11900, 0x1195F, U"Dives Akuru" }, { 0x119A0, 0x119FF, U"Nandinagari" }, { 0x11A00, 0x11A4F, U"Zanabazar Square" }, { 0x11A50, 0x11AAF, U"Soyombo" }, + { 0x11AB0, 0x11ABF, U"Unified Canadian Aboriginal Syllabics Extended-A" }, { 0x11AC0, 0x11AFF, U"Pau Cin Hau" }, { 0x11C00, 0x11C6F, U"Bhaiksuki" }, { 0x11C70, 0x11CBF, U"Marchen" }, @@ -335,11 +345,13 @@ static UniRange unicode_ranges[] = { { 0x12000, 0x123FF, U"Cuneiform" }, { 0x12400, 0x1247F, U"Cuneiform Numbers and Punctuation" }, { 0x12480, 0x1254F, U"Early Dynastic Cuneiform" }, + { 0x12F90, 0x12FFF, U"Cypro-Minoan" }, { 0x13000, 0x1342F, U"Egyptian Hieroglyphs" }, { 0x13430, 0x1343F, U"Egyptian Hieroglyph Format Controls" }, { 0x14400, 0x1467F, U"Anatolian Hieroglyphs" }, { 0x16800, 0x16A3F, U"Bamum Supplement" }, { 0x16A40, 0x16A6F, U"Mro" }, + { 0x16A70, 0x16ACF, U"Tangsa" }, { 0x16AD0, 0x16AFF, U"Bassa Vah" }, { 0x16B00, 0x16B8F, U"Pahawh Hmong" }, { 0x16E40, 0x16E9F, U"Medefaidrin" }, @@ -348,13 +360,15 @@ static UniRange unicode_ranges[] = { { 0x17000, 0x187FF, U"Tangut" }, { 0x18800, 0x18AFF, U"Tangut Components" }, { 0x18B00, 0x18CFF, U"Khitan Small Script" }, - { 0x18D00, 0x18D8F, U"Tangut Supplement" }, + { 0x18D00, 0x18D7F, U"Tangut Supplement" }, + { 0x1AFF0, 0x1AFFF, U"Kana Extended-B" }, { 0x1B000, 0x1B0FF, U"Kana Supplement" }, { 0x1B100, 0x1B12F, U"Kana Extended-A" }, { 0x1B130, 0x1B16F, U"Small Kana Extension" }, { 0x1B170, 0x1B2FF, U"Nushu" }, { 0x1BC00, 0x1BC9F, U"Duployan" }, { 0x1BCA0, 0x1BCAF, U"Shorthand Format Controls" }, + { 0x1CF00, 0x1CFCF, U"Znamenny Musical Notation" }, { 0x1D000, 0x1D0FF, U"Byzantine Musical Symbols" }, { 0x1D100, 0x1D1FF, U"Musical Symbols" }, { 0x1D200, 0x1D24F, U"Ancient Greek Musical Notation" }, @@ -363,9 +377,12 @@ static UniRange unicode_ranges[] = { { 0x1D360, 0x1D37F, U"Counting Rod Numerals" }, { 0x1D400, 0x1D7FF, U"Mathematical Alphanumeric Symbols" }, { 0x1D800, 0x1DAAF, U"Sutton SignWriting" }, + { 0x1DF00, 0x1DFFF, U"Latin Extended-G" }, { 0x1E000, 0x1E02F, U"Glagolitic Supplement" }, { 0x1E100, 0x1E14F, U"Nyiakeng Puachue Hmong" }, + { 0x1E290, 0x1E2BF, U"Toto" }, { 0x1E2C0, 0x1E2FF, U"Wancho" }, + { 0x1E7E0, 0x1E7FF, U"Ethiopic Extended-B" }, { 0x1E800, 0x1E8DF, U"Mende Kikakui" }, { 0x1E900, 0x1E95F, U"Adlam" }, { 0x1EC70, 0x1ECBF, U"Indic Siyaq Numbers" }, @@ -396,8 +413,8 @@ static UniRange unicode_ranges[] = { { 0x30000, 0x3134F, U"CJK Unified Ideographs Extension G" }, //{ 0xE0000, 0xE007F, U"Tags" }, //{ 0xE0100, 0xE01EF, U"Variation Selectors Supplement" }, - { 0xF0000, 0xFFFFD, U"Supplementary Private Use Area-A" }, - { 0x100000, 0x10FFFD, U"Supplementary Private Use Area-B" }, + { 0xF0000, 0xFFFFF, U"Supplementary Private Use Area-A" }, + { 0x100000, 0x10FFFF, U"Supplementary Private Use Area-B" }, { 0x10FFFF, 0x10FFFF, String() } }; @@ -425,398 +442,6 @@ void DynamicFontImportSettings::_add_glyph_range_item(int32_t p_start, int32_t p } /*************************************************************************/ -/* Languages and scripts */ -/*************************************************************************/ - -struct CodeInfo { - String name; - String code; -}; - -static CodeInfo langs[] = { - { U"Custom", U"xx" }, - { U"-", U"-" }, - { U"Abkhazian", U"ab" }, - { U"Afar", U"aa" }, - { U"Afrikaans", U"af" }, - { U"Akan", U"ak" }, - { U"Albanian", U"sq" }, - { U"Amharic", U"am" }, - { U"Arabic", U"ar" }, - { U"Aragonese", U"an" }, - { U"Armenian", U"hy" }, - { U"Assamese", U"as" }, - { U"Avaric", U"av" }, - { U"Avestan", U"ae" }, - { U"Aymara", U"ay" }, - { U"Azerbaijani", U"az" }, - { U"Bambara", U"bm" }, - { U"Bashkir", U"ba" }, - { U"Basque", U"eu" }, - { U"Belarusian", U"be" }, - { U"Bengali", U"bn" }, - { U"Bihari", U"bh" }, - { U"Bislama", U"bi" }, - { U"Bosnian", U"bs" }, - { U"Breton", U"br" }, - { U"Bulgarian", U"bg" }, - { U"Burmese", U"my" }, - { U"Catalan", U"ca" }, - { U"Chamorro", U"ch" }, - { U"Chechen", U"ce" }, - { U"Chichewa", U"ny" }, - { U"Chinese", U"zh" }, - { U"Chuvash", U"cv" }, - { U"Cornish", U"kw" }, - { U"Corsican", U"co" }, - { U"Cree", U"cr" }, - { U"Croatian", U"hr" }, - { U"Czech", U"cs" }, - { U"Danish", U"da" }, - { U"Divehi", U"dv" }, - { U"Dutch", U"nl" }, - { U"Dzongkha", U"dz" }, - { U"English", U"en" }, - { U"Esperanto", U"eo" }, - { U"Estonian", U"et" }, - { U"Ewe", U"ee" }, - { U"Faroese", U"fo" }, - { U"Fijian", U"fj" }, - { U"Finnish", U"fi" }, - { U"French", U"fr" }, - { U"Fulah", U"ff" }, - { U"Galician", U"gl" }, - { U"Georgian", U"ka" }, - { U"German", U"de" }, - { U"Greek", U"el" }, - { U"Guarani", U"gn" }, - { U"Gujarati", U"gu" }, - { U"Haitian", U"ht" }, - { U"Hausa", U"ha" }, - { U"Hebrew", U"he" }, - { U"Herero", U"hz" }, - { U"Hindi", U"hi" }, - { U"Hiri Motu", U"ho" }, - { U"Hungarian", U"hu" }, - { U"Interlingua", U"ia" }, - { U"Indonesian", U"id" }, - { U"Interlingue", U"ie" }, - { U"Irish", U"ga" }, - { U"Igbo", U"ig" }, - { U"Inupiaq", U"ik" }, - { U"Ido", U"io" }, - { U"Icelandic", U"is" }, - { U"Italian", U"it" }, - { U"Inuktitut", U"iu" }, - { U"Japanese", U"ja" }, - { U"Javanese", U"jv" }, - { U"Kalaallisut", U"kl" }, - { U"Kannada", U"kn" }, - { U"Kanuri", U"kr" }, - { U"Kashmiri", U"ks" }, - { U"Kazakh", U"kk" }, - { U"Central Khmer", U"km" }, - { U"Kikuyu", U"ki" }, - { U"Kinyarwanda", U"rw" }, - { U"Kirghiz", U"ky" }, - { U"Komi", U"kv" }, - { U"Kongo", U"kg" }, - { U"Korean", U"ko" }, - { U"Kurdish", U"ku" }, - { U"Kuanyama", U"kj" }, - { U"Latin", U"la" }, - { U"Luxembourgish", U"lb" }, - { U"Ganda", U"lg" }, - { U"Limburgan", U"li" }, - { U"Lingala", U"ln" }, - { U"Lao", U"lo" }, - { U"Lithuanian", U"lt" }, - { U"Luba-Katanga", U"lu" }, - { U"Latvian", U"lv" }, - { U"Man", U"gv" }, - { U"Macedonian", U"mk" }, - { U"Malagasy", U"mg" }, - { U"Malay", U"ms" }, - { U"Malayalam", U"ml" }, - { U"Maltese", U"mt" }, - { U"Maori", U"mi" }, - { U"Marathi", U"mr" }, - { U"Marshallese", U"mh" }, - { U"Mongolian", U"mn" }, - { U"Nauru", U"na" }, - { U"Navajo", U"nv" }, - { U"North Ndebele", U"nd" }, - { U"Nepali", U"ne" }, - { U"Ndonga", U"ng" }, - { U"Norwegian Bokmål", U"nb" }, - { U"Norwegian Nynorsk", U"nn" }, - { U"Norwegian", U"no" }, - { U"Sichuan Yi, Nuosu", U"ii" }, - { U"South Ndebele", U"nr" }, - { U"Occitan", U"oc" }, - { U"Ojibwa", U"oj" }, - { U"Church Slavic", U"cu" }, - { U"Oromo", U"om" }, - { U"Oriya", U"or" }, - { U"Ossetian", U"os" }, - { U"Punjabi", U"pa" }, - { U"Pali", U"pi" }, - { U"Persian", U"fa" }, - { U"Polish", U"pl" }, - { U"Pashto", U"ps" }, - { U"Portuguese", U"pt" }, - { U"Quechua", U"qu" }, - { U"Romansh", U"rm" }, - { U"Rundi", U"rn" }, - { U"Romanian", U"ro" }, - { U"Russian", U"ru" }, - { U"Sanskrit", U"sa" }, - { U"Sardinian", U"sc" }, - { U"Sindhi", U"sd" }, - { U"Northern Sami", U"se" }, - { U"Samoan", U"sm" }, - { U"Sango", U"sg" }, - { U"Serbian", U"sr" }, - { U"Gaelic", U"gd" }, - { U"Shona", U"sn" }, - { U"Sinhala", U"si" }, - { U"Slovak", U"sk" }, - { U"Slovenian", U"sl" }, - { U"Somali", U"so" }, - { U"Southern Sotho", U"st" }, - { U"Spanish", U"es" }, - { U"Sundanese", U"su" }, - { U"Swahili", U"sw" }, - { U"Swati", U"ss" }, - { U"Swedish", U"sv" }, - { U"Tamil", U"ta" }, - { U"Telugu", U"te" }, - { U"Tajik", U"tg" }, - { U"Thai", U"th" }, - { U"Tigrinya", U"ti" }, - { U"Tibetan", U"bo" }, - { U"Turkmen", U"tk" }, - { U"Tagalog", U"tl" }, - { U"Tswana", U"tn" }, - { U"Tonga", U"to" }, - { U"Turkish", U"tr" }, - { U"Tsonga", U"ts" }, - { U"Tatar", U"tt" }, - { U"Twi", U"tw" }, - { U"Tahitian", U"ty" }, - { U"Uighur", U"ug" }, - { U"Ukrainian", U"uk" }, - { U"Urdu", U"ur" }, - { U"Uzbek", U"uz" }, - { U"Venda", U"ve" }, - { U"Vietnamese", U"vi" }, - { U"Volapük", U"vo" }, - { U"Walloon", U"wa" }, - { U"Welsh", U"cy" }, - { U"Wolof", U"wo" }, - { U"Western Frisian", U"fy" }, - { U"Xhosa", U"xh" }, - { U"Yiddish", U"yi" }, - { U"Yoruba", U"yo" }, - { U"Zhuang", U"za" }, - { U"Zulu", U"zu" }, - { String(), String() } -}; - -static CodeInfo scripts[] = { - { U"Custom", U"Qaaa" }, - { U"-", U"-" }, - { U"Adlam", U"Adlm" }, - { U"Afaka", U"Afak" }, - { U"Caucasian Albanian", U"Aghb" }, - { U"Ahom", U"Ahom" }, - { U"Arabic", U"Arab" }, - { U"Imperial Aramaic", U"Armi" }, - { U"Armenian", U"Armn" }, - { U"Avestan", U"Avst" }, - { U"Balinese", U"Bali" }, - { U"Bamum", U"Bamu" }, - { U"Bassa Vah", U"Bass" }, - { U"Batak", U"Batk" }, - { U"Bengali", U"Beng" }, - { U"Bhaiksuki", U"Bhks" }, - { U"Blissymbols", U"Blis" }, - { U"Bopomofo", U"Bopo" }, - { U"Brahmi", U"Brah" }, - { U"Braille", U"Brai" }, - { U"Buginese", U"Bugi" }, - { U"Buhid", U"Buhd" }, - { U"Chakma", U"Cakm" }, - { U"Unified Canadian Aboriginal", U"Cans" }, - { U"Carian", U"Cari" }, - { U"Cham", U"Cham" }, - { U"Cherokee", U"Cher" }, - { U"Chorasmian", U"Chrs" }, - { U"Cirth", U"Cirt" }, - { U"Coptic", U"Copt" }, - { U"Cypro-Minoan", U"Cpmn" }, - { U"Cypriot", U"Cprt" }, - { U"Cyrillic", U"Cyrl" }, - { U"Devanagari", U"Deva" }, - { U"Dives Akuru", U"Diak" }, - { U"Dogra", U"Dogr" }, - { U"Deseret", U"Dsrt" }, - { U"Duployan", U"Dupl" }, - { U"Egyptian demotic", U"Egyd" }, - { U"Egyptian hieratic", U"Egyh" }, - { U"Egyptian hieroglyphs", U"Egyp" }, - { U"Elbasan", U"Elba" }, - { U"Elymaic", U"Elym" }, - { U"Ethiopic", U"Ethi" }, - { U"Khutsuri", U"Geok" }, - { U"Georgian", U"Geor" }, - { U"Glagolitic", U"Glag" }, - { U"Gunjala Gondi", U"Gong" }, - { U"Masaram Gondi", U"Gonm" }, - { U"Gothic", U"Goth" }, - { U"Grantha", U"Gran" }, - { U"Greek", U"Grek" }, - { U"Gujarati", U"Gujr" }, - { U"Gurmukhi", U"Guru" }, - { U"Hangul", U"Hang" }, - { U"Han", U"Hani" }, - { U"Hanunoo", U"Hano" }, - { U"Hatran", U"Hatr" }, - { U"Hebrew", U"Hebr" }, - { U"Hiragana", U"Hira" }, - { U"Anatolian Hieroglyphs", U"Hluw" }, - { U"Pahawh Hmong", U"Hmng" }, - { U"Nyiakeng Puachue Hmong", U"Hmnp" }, - { U"Old Hungarian", U"Hung" }, - { U"Indus", U"Inds" }, - { U"Old Italic", U"Ital" }, - { U"Javanese", U"Java" }, - { U"Jurchen", U"Jurc" }, - { U"Kayah Li", U"Kali" }, - { U"Katakana", U"Kana" }, - { U"Kharoshthi", U"Khar" }, - { U"Khmer", U"Khmr" }, - { U"Khojki", U"Khoj" }, - { U"Khitan large script", U"Kitl" }, - { U"Khitan small script", U"Kits" }, - { U"Kannada", U"Knda" }, - { U"Kpelle", U"Kpel" }, - { U"Kaithi", U"Kthi" }, - { U"Tai Tham", U"Lana" }, - { U"Lao", U"Laoo" }, - { U"Latin", U"Latn" }, - { U"Leke", U"Leke" }, - { U"Lepcha", U"Lepc" }, - { U"Limbu", U"Limb" }, - { U"Linear A", U"Lina" }, - { U"Linear B", U"Linb" }, - { U"Lisu", U"Lisu" }, - { U"Loma", U"Loma" }, - { U"Lycian", U"Lyci" }, - { U"Lydian", U"Lydi" }, - { U"Mahajani", U"Mahj" }, - { U"Makasar", U"Maka" }, - { U"Mandaic", U"Mand" }, - { U"Manichaean", U"Mani" }, - { U"Marchen", U"Marc" }, - { U"Mayan Hieroglyphs", U"Maya" }, - { U"Medefaidrin", U"Medf" }, - { U"Mende Kikakui", U"Mend" }, - { U"Meroitic Cursive", U"Merc" }, - { U"Meroitic Hieroglyphs", U"Mero" }, - { U"Malayalam", U"Mlym" }, - { U"Modi", U"Modi" }, - { U"Mongolian", U"Mong" }, - { U"Moon", U"Moon" }, - { U"Mro", U"Mroo" }, - { U"Meitei Mayek", U"Mtei" }, - { U"Multani", U"Mult" }, - { U"Myanmar (Burmese)", U"Mymr" }, - { U"Nandinagari", U"Nand" }, - { U"Old North Arabian", U"Narb" }, - { U"Nabataean", U"Nbat" }, - { U"Newa", U"Newa" }, - { U"Naxi Dongba", U"Nkdb" }, - { U"Nakhi Geba", U"Nkgb" }, - { U"N’Ko", U"Nkoo" }, - { U"Nüshu", U"Nshu" }, - { U"Ogham", U"Ogam" }, - { U"Ol Chiki", U"Olck" }, - { U"Old Turkic", U"Orkh" }, - { U"Oriya", U"Orya" }, - { U"Osage", U"Osge" }, - { U"Osmanya", U"Osma" }, - { U"Old Uyghur", U"Ougr" }, - { U"Palmyrene", U"Palm" }, - { U"Pau Cin Hau", U"Pauc" }, - { U"Proto-Cuneiform", U"Pcun" }, - { U"Proto-Elamite", U"Pelm" }, - { U"Old Permic", U"Perm" }, - { U"Phags-pa", U"Phag" }, - { U"Inscriptional Pahlavi", U"Phli" }, - { U"Psalter Pahlavi", U"Phlp" }, - { U"Book Pahlavi", U"Phlv" }, - { U"Phoenician", U"Phnx" }, - { U"Klingon", U"Piqd" }, - { U"Miao", U"Plrd" }, - { U"Inscriptional Parthian", U"Prti" }, - { U"Proto-Sinaitic", U"Psin" }, - { U"Ranjana", U"Ranj" }, - { U"Rejang", U"Rjng" }, - { U"Hanifi Rohingya", U"Rohg" }, - { U"Rongorongo", U"Roro" }, - { U"Runic", U"Runr" }, - { U"Samaritan", U"Samr" }, - { U"Sarati", U"Sara" }, - { U"Old South Arabian", U"Sarb" }, - { U"Saurashtra", U"Saur" }, - { U"SignWriting", U"Sgnw" }, - { U"Shavian", U"Shaw" }, - { U"Sharada", U"Shrd" }, - { U"Shuishu", U"Shui" }, - { U"Siddham", U"Sidd" }, - { U"Khudawadi", U"Sind" }, - { U"Sinhala", U"Sinh" }, - { U"Sogdian", U"Sogd" }, - { U"Old Sogdian", U"Sogo" }, - { U"Sora Sompeng", U"Sora" }, - { U"Soyombo", U"Soyo" }, - { U"Sundanese", U"Sund" }, - { U"Syloti Nagri", U"Sylo" }, - { U"Syriac", U"Syrc" }, - { U"Tagbanwa", U"Tagb" }, - { U"Takri", U"Takr" }, - { U"Tai Le", U"Tale" }, - { U"New Tai Lue", U"Talu" }, - { U"Tamil", U"Taml" }, - { U"Tangut", U"Tang" }, - { U"Tai Viet", U"Tavt" }, - { U"Telugu", U"Telu" }, - { U"Tengwar", U"Teng" }, - { U"Tifinagh", U"Tfng" }, - { U"Tagalog", U"Tglg" }, - { U"Thaana", U"Thaa" }, - { U"Thai", U"Thai" }, - { U"Tibetan", U"Tibt" }, - { U"Tirhuta", U"Tirh" }, - { U"Tangsa", U"Tnsa" }, - { U"Toto", U"Toto" }, - { U"Ugaritic", U"Ugar" }, - { U"Vai", U"Vaii" }, - { U"Visible Speech", U"Visp" }, - { U"Vithkuqi", U"Vith" }, - { U"Warang Citi", U"Wara" }, - { U"Wancho", U"Wcho" }, - { U"Woleai", U"Wole" }, - { U"Old Persian", U"Xpeo" }, - { U"Cuneiform", U"Xsux" }, - { U"Yezidi", U"Yezi" }, - { U"Yi", U"Yiii" }, - { U"Zanabazar Square", U"Zanb" }, - { String(), String() } -}; - -/*************************************************************************/ /* Page 1 callbacks: Rendering Options */ /*************************************************************************/ @@ -994,9 +619,10 @@ void DynamicFontImportSettings::_glyph_text_selected() { if (text_rid.is_valid()) { TS->shaped_text_add_string(text_rid, text_edit->get_text(), font_main->get_rids(), 16, ftrs, text_edit->get_language()); TS->shaped_text_shape(text_rid); - const Vector<TextServer::Glyph> &gl = TS->shaped_text_get_glyphs(text_rid); + const Glyph *gl = TS->shaped_text_get_glyphs(text_rid); + const int gl_size = TS->shaped_text_get_glyph_count(text_rid); - for (int i = 0; i < gl.size(); i++) { + for (int i = 0; i < gl_size; i++) { if (gl[i].font_rid.is_valid() && gl[i].index != 0) { selected_glyphs.insert(gl[i].index); } @@ -1065,7 +691,7 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) { item = glyph_table->create_item(root); ERR_FAIL_NULL(item); item->set_text(0, _pad_zeros(String::num_int64(c, 16))); - item->set_text_align(0, TreeItem::ALIGN_LEFT); + item->set_text_alignment(0, HORIZONTAL_ALIGNMENT_LEFT); item->set_selectable(0, false); item->set_custom_bg_color(0, glyph_table->get_theme_color("dark_color_3", "Editor")); } @@ -1083,7 +709,7 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) { item->set_custom_bg_color(col + 1, glyph_table->get_theme_color("dark_color_2", "Editor")); } item->set_metadata(col + 1, c); - item->set_text_align(col + 1, TreeItem::ALIGN_CENTER); + item->set_text_alignment(col + 1, HORIZONTAL_ALIGNMENT_CENTER); item->set_selectable(col + 1, true); item->set_custom_font(col + 1, font_main); item->set_custom_font_size(col + 1, get_theme_font_size("font_size") * 2); @@ -1141,19 +767,17 @@ void DynamicFontImportSettings::_range_update(int32_t p_start, int32_t p_end) { /*************************************************************************/ void DynamicFontImportSettings::_lang_add() { - menu_langs->set_position(lang_list->get_screen_transform().xform(lang_list->get_local_mouse_position())); - menu_langs->set_size(Vector2(1, 1)); - menu_langs->popup(); + locale_select->popup_locale_dialog(); } -void DynamicFontImportSettings::_lang_add_item(int p_option) { +void DynamicFontImportSettings::_lang_add_item(const String &p_locale) { TreeItem *lang_item = lang_list->create_item(lang_list_root); ERR_FAIL_NULL(lang_item); lang_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); lang_item->set_editable(0, true); lang_item->set_checked(0, false); - lang_item->set_text(1, langs[p_option].code); + lang_item->set_text(1, p_locale); lang_item->set_editable(1, true); lang_item->add_button(2, lang_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); lang_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); @@ -1167,9 +791,41 @@ void DynamicFontImportSettings::_lang_remove(Object *p_item, int p_column, int p memdelete(lang_item); } +void DynamicFontImportSettings::_ot_add() { + menu_ot->set_position(ot_list->get_screen_transform().xform(ot_list->get_local_mouse_position())); + menu_ot->set_size(Vector2(1, 1)); + menu_ot->popup(); +} + +void DynamicFontImportSettings::_ot_add_item(int p_option) { + String name = TS->tag_to_name(p_option); + for (TreeItem *ot_item = ot_list_root->get_first_child(); ot_item; ot_item = ot_item->get_next()) { + if (ot_item->get_text(0) == name) { + return; + } + } + TreeItem *ot_item = ot_list->create_item(ot_list_root); + ERR_FAIL_NULL(ot_item); + + ot_item->set_text(0, name); + ot_item->set_editable(0, false); + ot_item->set_text(1, "1"); + ot_item->set_editable(1, true); + ot_item->add_button(2, ot_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); + ot_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); +} + +void DynamicFontImportSettings::_ot_remove(Object *p_item, int p_column, int p_id) { + TreeItem *ot_item = (TreeItem *)p_item; + ERR_FAIL_NULL(ot_item); + + ot_list_root->remove_child(ot_item); + memdelete(ot_item); +} + void DynamicFontImportSettings::_script_add() { - menu_scripts->set_position(script_list->get_screen_transform().xform(script_list->get_local_mouse_position())); - menu_scripts->set_size(Vector2(1, 1)); + menu_scripts->set_position(script_list->get_screen_position() + script_list->get_local_mouse_position()); + menu_scripts->reset_size(); menu_scripts->popup(); } @@ -1180,7 +836,7 @@ void DynamicFontImportSettings::_script_add_item(int p_option) { script_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); script_item->set_editable(0, true); script_item->set_checked(0, false); - script_item->set_text(1, scripts[p_option].code); + script_item->set_text(1, script_codes[p_option]); script_item->set_editable(1, true); script_item->add_button(2, lang_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); script_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); @@ -1212,6 +868,7 @@ void DynamicFontImportSettings::_notification(int p_what) { add_lang->set_icon(add_var->get_theme_icon("Add", "EditorIcons")); add_script->set_icon(add_var->get_theme_icon("Add", "EditorIcons")); add_var->set_icon(add_var->get_theme_icon("Add", "EditorIcons")); + add_ot->set_icon(add_var->get_theme_icon("Add", "EditorIcons")); } } @@ -1299,6 +956,14 @@ void DynamicFontImportSettings::_re_import() { main_settings["preload/glyph_ranges"] = ranges; } + Dictionary ot_ov; + for (TreeItem *ot_item = ot_list_root->get_first_child(); ot_item; ot_item = ot_item->get_next()) { + String tag = ot_item->get_text(0); + int32_t value = ot_item->get_text(1).to_int(); + ot_ov[tag] = value; + } + main_settings["opentype_feature_overrides"] = ot_ov; + if (OS::get_singleton()->is_stdout_verbose()) { print_line("Import settings:"); for (Map<StringName, Variant>::Element *E = main_settings.front(); E; E = E->next()) { @@ -1355,6 +1020,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { vars_list->clear(); lang_list->clear(); script_list->clear(); + ot_list->clear(); selected_chars.clear(); selected_glyphs.clear(); @@ -1363,6 +1029,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { vars_list_root = vars_list->create_item(); lang_list_root = lang_list->create_item(); script_list_root = script_list->create_item(); + ot_list_root = ot_list->create_item(); options_variations.clear(); Dictionary var_list = dfont_main->get_supported_variation_list(); @@ -1528,6 +1195,23 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { script_item->set_editable(1, true); script_item->add_button(2, lang_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); } + } else if (key == "opentype_feature_overrides") { + Dictionary features = config->get_value("params", key); + for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) { + TreeItem *ot_item = ot_list->create_item(ot_list_root); + ERR_FAIL_NULL(ot_item); + int32_t value = features[*ftr]; + if (ftr->get_type() == Variant::STRING) { + ot_item->set_text(0, *ftr); + } else { + ot_item->set_text(0, TS->tag_to_name(*ftr)); + } + ot_item->set_editable(0, false); + ot_item->set_text(1, itos(value)); + ot_item->set_editable(1, true); + ot_item->add_button(2, ot_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); + ot_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); + } } else { Variant value = config->get_value("params", key); import_settings_data->defaults[key] = value; @@ -1552,6 +1236,39 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { font_preview_label->add_theme_font_override("font", font_preview); font_preview_label->update(); + menu_ot->clear(); + menu_ot_ss->clear(); + menu_ot_cv->clear(); + menu_ot_cu->clear(); + bool have_ss = false; + bool have_cv = false; + bool have_cu = false; + Dictionary features = font_preview->get_feature_list(); + for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) { + String ftr_name = TS->tag_to_name(*ftr); + if (ftr_name.begins_with("stylistic_set_")) { + menu_ot_ss->add_item(ftr_name.capitalize(), (int32_t)*ftr); + have_ss = true; + } else if (ftr_name.begins_with("character_variant_")) { + menu_ot_cv->add_item(ftr_name.capitalize(), (int32_t)*ftr); + have_cv = true; + } else if (ftr_name.begins_with("custom_")) { + menu_ot_cu->add_item(ftr_name.replace("custom_", ""), (int32_t)*ftr); + have_cu = true; + } else { + menu_ot->add_item(ftr_name.capitalize(), (int32_t)*ftr); + } + } + if (have_ss) { + menu_ot->add_submenu_item(RTR("Stylistic Sets"), "SSMenu"); + } + if (have_cv) { + menu_ot->add_submenu_item(RTR("Character Variants"), "CVMenu"); + } + if (have_cu) { + menu_ot->add_submenu_item(RTR("Custom"), "CUMenu"); + } + _variations_validate(); popup_centered_ratio(); @@ -1577,30 +1294,38 @@ DynamicFontImportSettings::DynamicFontImportSettings() { // Popup menus - menu_langs = memnew(PopupMenu); - menu_langs->set_name("Language"); - for (int i = 0; langs[i].name != String(); i++) { - if (langs[i].name == "-") { - menu_langs->add_separator(); - } else { - menu_langs->add_item(langs[i].name + " (" + langs[i].code + ")", i); - } - } - add_child(menu_langs); - menu_langs->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_lang_add_item)); + locale_select = memnew(EditorLocaleDialog); + locale_select->connect("locale_selected", callable_mp(this, &DynamicFontImportSettings::_lang_add_item)); + add_child(locale_select); menu_scripts = memnew(PopupMenu); menu_scripts->set_name("Script"); - for (int i = 0; scripts[i].name != String(); i++) { - if (scripts[i].name == "-") { - menu_scripts->add_separator(); - } else { - menu_scripts->add_item(scripts[i].name + " (" + scripts[i].code + ")", i); - } + script_codes = TranslationServer::get_singleton()->get_all_scripts(); + for (int i = 0; i < script_codes.size(); i++) { + menu_scripts->add_item(TranslationServer::get_singleton()->get_script_name(script_codes[i]) + " (" + script_codes[i] + ")", i); } add_child(menu_scripts); menu_scripts->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_script_add_item)); + menu_ot = memnew(PopupMenu); + add_child(menu_ot); + menu_ot->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add_item)); + + menu_ot_cv = memnew(PopupMenu); + menu_ot_cv->set_name("CVMenu"); + menu_ot->add_child(menu_ot_cv); + menu_ot_cv->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add_item)); + + menu_ot_ss = memnew(PopupMenu); + menu_ot_ss->set_name("SSMenu"); + menu_ot->add_child(menu_ot_ss); + menu_ot_ss->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add_item)); + + menu_ot_cu = memnew(PopupMenu); + menu_ot_cu->set_name("CUMenu"); + menu_ot->add_child(menu_ot_cu); + menu_ot_cu->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add_item)); + Color warn_color = (EditorNode::get_singleton()) ? EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor") : Color(1, 1, 0); // Root layout @@ -1614,7 +1339,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { root_vb->add_child(main_pages); label_warn = memnew(Label); - label_warn->set_align(Label::ALIGN_CENTER); + label_warn->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); label_warn->set_text(""); root_vb->add_child(label_warn); label_warn->add_theme_color_override("font_color", warn_color); @@ -1638,8 +1363,8 @@ DynamicFontImportSettings::DynamicFontImportSettings() { font_preview_label = memnew(Label); font_preview_label->add_theme_font_size_override("font_size", 200 * EDSCALE); - font_preview_label->set_align(Label::ALIGN_CENTER); - font_preview_label->set_valign(Label::VALIGN_CENTER); + font_preview_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); + font_preview_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); font_preview_label->set_autowrap_mode(Label::AUTOWRAP_ARBITRARY); font_preview_label->set_clip_text(true); font_preview_label->set_v_size_flags(Control::SIZE_EXPAND_FILL); @@ -1676,7 +1401,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { label_vars = memnew(Label); page2_hb_vars->add_child(label_vars); - label_vars->set_align(Label::ALIGN_CENTER); + label_vars->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); label_vars->set_h_size_flags(Control::SIZE_EXPAND_FILL); label_vars->set_text(TTR("Configuration:")); @@ -1799,7 +1524,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { glyph_tree = memnew(Tree); glyphs_split->add_child(glyph_tree); glyph_tree->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); - glyph_tree->set_columns(3); + glyph_tree->set_columns(2); glyph_tree->set_hide_root(true); glyph_tree->set_column_expand(0, false); glyph_tree->set_column_expand(1, true); @@ -1808,7 +1533,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { glyph_tree->connect("item_selected", callable_mp(this, &DynamicFontImportSettings::_range_selected)); glyph_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); glyph_root = glyph_tree->create_item(); - for (int i = 0; unicode_ranges[i].name != String(); i++) { + for (int i = 0; !unicode_ranges[i].name.is_empty(); i++) { _add_glyph_range_item(unicode_ranges[i].start, unicode_ranges[i].end, unicode_ranges[i].name); } @@ -1827,7 +1552,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { page5_vb->add_child(hb_lang); label_langs = memnew(Label); - label_langs->set_align(Label::ALIGN_CENTER); + label_langs->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); label_langs->set_h_size_flags(Control::SIZE_EXPAND_FILL); label_langs->set_text(TTR("Language support overrides")); hb_lang->add_child(label_langs); @@ -1855,7 +1580,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { page5_vb->add_child(hb_script); label_script = memnew(Label); - label_script->set_align(Label::ALIGN_CENTER); + label_script->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); label_script->set_h_size_flags(Control::SIZE_EXPAND_FILL); label_script->set_text(TTR("Script support overrides")); hb_script->add_child(label_script); @@ -1879,6 +1604,34 @@ DynamicFontImportSettings::DynamicFontImportSettings() { script_list->connect("button_pressed", callable_mp(this, &DynamicFontImportSettings::_script_remove)); script_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + HBoxContainer *hb_ot = memnew(HBoxContainer); + page5_vb->add_child(hb_ot); + + label_ot = memnew(Label); + label_ot->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); + label_ot->set_h_size_flags(Control::SIZE_EXPAND_FILL); + label_ot->set_text(TTR("OpenType feature overrides")); + hb_ot->add_child(label_ot); + + add_ot = memnew(Button); + hb_ot->add_child(add_ot); + add_ot->set_tooltip(TTR("Add feature override")); + add_ot->set_icon(add_var->get_theme_icon("Add", "EditorIcons")); + add_ot->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add)); + + ot_list = memnew(Tree); + page5_vb->add_child(ot_list); + ot_list->set_hide_root(true); + ot_list->set_columns(3); + ot_list->set_column_expand(0, true); + ot_list->set_column_custom_minimum_width(0, 80 * EDSCALE); + ot_list->set_column_expand(1, true); + ot_list->set_column_custom_minimum_width(1, 80 * EDSCALE); + ot_list->set_column_expand(2, false); + ot_list->set_column_custom_minimum_width(2, 50 * EDSCALE); + ot_list->connect("button_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_remove)); + ot_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + // Common import_settings_data.instantiate(); diff --git a/editor/import/dynamicfont_import_settings.h b/editor/import/dynamicfont_import_settings.h index 05f5e8e00b..5d37f58b9b 100644 --- a/editor/import/dynamicfont_import_settings.h +++ b/editor/import/dynamicfont_import_settings.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,6 +33,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_inspector.h" +#include "editor/editor_locale_dialog.h" #include "editor/import/resource_importer_dynamicfont.h" @@ -67,6 +68,9 @@ class DynamicFontImportSettings : public ConfirmationDialog { List<ResourceImporter::ImportOption> options_variations; List<ResourceImporter::ImportOption> options_general; + EditorLocaleDialog *locale_select; + Vector<String> script_codes; + // Root layout Label *label_warn = nullptr; TabContainer *main_pages = nullptr; @@ -120,26 +124,38 @@ class DynamicFontImportSettings : public ConfirmationDialog { Label *page5_description = nullptr; Button *add_lang = nullptr; Button *add_script = nullptr; + Button *add_ot = nullptr; - PopupMenu *menu_langs = nullptr; PopupMenu *menu_scripts = nullptr; + PopupMenu *menu_ot = nullptr; + PopupMenu *menu_ot_ss = nullptr; + PopupMenu *menu_ot_cv = nullptr; + PopupMenu *menu_ot_cu = nullptr; Tree *lang_list = nullptr; TreeItem *lang_list_root = nullptr; + Label *label_langs = nullptr; Tree *script_list = nullptr; TreeItem *script_list_root = nullptr; - Label *label_langs = nullptr; Label *label_script = nullptr; + Tree *ot_list = nullptr; + TreeItem *ot_list_root = nullptr; + Label *label_ot = nullptr; + void _lang_add(); - void _lang_add_item(int p_option); + void _lang_add_item(const String &p_locale); void _lang_remove(Object *p_item, int p_column, int p_id); void _script_add(); void _script_add_item(int p_option); void _script_remove(Object *p_item, int p_column, int p_id); + void _ot_add(); + void _ot_add_item(int p_option); + void _ot_remove(Object *p_item, int p_column, int p_id); + // Common void _add_glyph_range_item(int32_t p_start, int32_t p_end, const String &p_name); diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 7ab80ac3b4..c1ae5be0bb 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,8 +33,8 @@ #include "core/os/os.h" #include "editor/editor_node.h" #include "editor/import/collada.h" -#include "editor/import/scene_importer_mesh_node_3d.h" #include "scene/3d/camera_3d.h" +#include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/node_3d.h" @@ -42,6 +42,7 @@ #include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" +#include "scene/resources/importer_mesh.h" #include "scene/resources/packed_scene.h" #include "scene/resources/surface_tool.h" @@ -68,7 +69,7 @@ struct ColladaImport { Map<String, NodeMap> node_map; //map from collada node to engine node Map<String, String> node_name_map; //map from collada node to engine node - Map<String, Ref<EditorSceneImporterMesh>> mesh_cache; + Map<String, Ref<ImporterMesh>> mesh_cache; Map<String, Ref<Curve3D>> curve_cache; Map<String, Ref<Material>> material_cache; Map<Collada::Node *, Skeleton3D *> skeleton_map; @@ -87,11 +88,11 @@ struct ColladaImport { Error _create_scene(Collada::Node *p_node, Node3D *p_parent); Error _create_resources(Collada::Node *p_node, bool p_use_compression); Error _create_material(const String &p_target); - Error _create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes = Vector<Ref<EditorSceneImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false); + Error _create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ImporterMesh>> p_morph_meshes = Vector<Ref<ImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false); Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false, bool p_use_compression = false); void _fix_param_animation_tracks(); - void create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks); - void create_animations(bool p_make_tracks_in_all_bones, bool p_import_value_tracks); + void create_animation(int p_clip, bool p_import_value_tracks); + void create_animations(bool p_import_value_tracks); Set<String> tracks_in_clips; Vector<String> missing_textures; @@ -119,6 +120,15 @@ Error ColladaImport::_populate_skeleton(Skeleton3D *p_skeleton, Collada::Node *p skeleton_bone_map[p_skeleton][joint->sid] = r_bone; + { + Transform3D xform = joint->compute_transform(collada); + xform = collada.fix_transform(xform) * joint->post_transform; + + p_skeleton->set_bone_pose_position(r_bone, xform.origin); + p_skeleton->set_bone_pose_rotation(r_bone, xform.basis.get_rotation_quaternion()); + p_skeleton->set_bone_pose_scale(r_bone, xform.basis.get_scale()); + } + if (collada.state.bone_rest_map.has(joint->sid)) { p_skeleton->set_bone_rest(r_bone, collada.fix_transform(collada.state.bone_rest_map[joint->sid])); //should map this bone to something for animation? @@ -282,8 +292,8 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) { node = memnew(Path3D); } else { //mesh since nothing else - node = memnew(EditorSceneImporterMeshNode3D); - //Object::cast_to<EditorSceneImporterMeshNode3D>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true); + node = memnew(ImporterMeshInstance3D); + //Object::cast_to<ImporterMeshInstance3D>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true); } } break; case Collada::Node::TYPE_SKELETON: { @@ -293,7 +303,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) { } break; } - if (p_node->name != "") { + if (!p_node->name.is_empty()) { node->set_name(p_node->name); } NodeMap nm; @@ -304,10 +314,10 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) { xf = collada.fix_transform(xf) * p_node->post_transform; node->set_transform(xf); - p_parent->add_child(node); + p_parent->add_child(node, true); node->set_owner(scene); - if (p_node->empty_draw_type != "") { + if (!p_node->empty_draw_type.is_empty()) { node->set_meta("empty_draw_type", Variant(p_node->empty_draw_type)); } @@ -330,9 +340,9 @@ Error ColladaImport::_create_material(const String &p_target) { Ref<StandardMaterial3D> material = memnew(StandardMaterial3D); String base_name; - if (src_mat.name != "") { + if (!src_mat.name.is_empty()) { base_name = src_mat.name; - } else if (effect.name != "") { + } else if (!effect.name.is_empty()) { base_name = effect.name; } else { base_name = "Material"; @@ -350,9 +360,9 @@ Error ColladaImport::_create_material(const String &p_target) { // DIFFUSE - if (effect.diffuse.texture != "") { + if (!effect.diffuse.texture.is_empty()) { String texfile = effect.get_texture_path(effect.diffuse.texture, collada); - if (texfile != "") { + if (!texfile.is_empty()) { if (texfile.begins_with("/")) { texfile = texfile.replace_first("/", "res://"); } @@ -371,9 +381,9 @@ Error ColladaImport::_create_material(const String &p_target) { // SPECULAR - if (effect.specular.texture != "") { + if (!effect.specular.texture.is_empty()) { String texfile = effect.get_texture_path(effect.specular.texture, collada); - if (texfile != "") { + if (!texfile.is_empty()) { if (texfile.begins_with("/")) { texfile = texfile.replace_first("/", "res://"); } @@ -396,9 +406,9 @@ Error ColladaImport::_create_material(const String &p_target) { // EMISSION - if (effect.emission.texture != "") { + if (!effect.emission.texture.is_empty()) { String texfile = effect.get_texture_path(effect.emission.texture, collada); - if (texfile != "") { + if (!texfile.is_empty()) { if (texfile.begins_with("/")) { texfile = texfile.replace_first("/", "res://"); } @@ -423,9 +433,9 @@ Error ColladaImport::_create_material(const String &p_target) { // NORMAL - if (effect.bump.texture != "") { + if (!effect.bump.texture.is_empty()) { String texfile = effect.get_texture_path(effect.bump.texture, collada); - if (texfile != "") { + if (!texfile.is_empty()) { if (texfile.begins_with("/")) { texfile = texfile.replace_first("/", "res://"); } @@ -457,11 +467,11 @@ Error ColladaImport::_create_material(const String &p_target) { return OK; } -Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) { +Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) { bool local_xform_mirror = p_local_xform.basis.determinant() < 0; if (p_morph_data) { - //add morphie target + //add morph target ERR_FAIL_COND_V(!p_morph_data->targets.has("MORPH_TARGET"), ERR_INVALID_DATA); String mt = p_morph_data->targets["MORPH_TARGET"]; ERR_FAIL_COND_V(!p_morph_data->sources.has(mt), ERR_INVALID_DATA); @@ -515,7 +525,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor normal_ofs = vertex_ofs; } - if (normal_source_id != "") { + if (!normal_source_id.is_empty()) { ERR_FAIL_COND_V(!meshdata.sources.has(normal_source_id), ERR_INVALID_DATA); normal_src = &meshdata.sources[normal_source_id]; } @@ -535,7 +545,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor binormal_ofs = vertex_ofs; } - if (binormal_source_id != "") { + if (!binormal_source_id.is_empty()) { ERR_FAIL_COND_V(!meshdata.sources.has(binormal_source_id), ERR_INVALID_DATA); binormal_src = &meshdata.sources[binormal_source_id]; } @@ -555,7 +565,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor tangent_ofs = vertex_ofs; } - if (tangent_source_id != "") { + if (!tangent_source_id.is_empty()) { ERR_FAIL_COND_V(!meshdata.sources.has(tangent_source_id), ERR_INVALID_DATA); tangent_src = &meshdata.sources[tangent_source_id]; } @@ -575,7 +585,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor uv_ofs = vertex_ofs; } - if (uv_source_id != "") { + if (!uv_source_id.is_empty()) { ERR_FAIL_COND_V(!meshdata.sources.has(uv_source_id), ERR_INVALID_DATA); uv_src = &meshdata.sources[uv_source_id]; } @@ -595,7 +605,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor uv2_ofs = vertex_ofs; } - if (uv2_source_id != "") { + if (!uv2_source_id.is_empty()) { ERR_FAIL_COND_V(!meshdata.sources.has(uv2_source_id), ERR_INVALID_DATA); uv2_src = &meshdata.sources[uv2_source_id]; } @@ -615,7 +625,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor color_ofs = vertex_ofs; } - if (color_source_id != "") { + if (!color_source_id.is_empty()) { ERR_FAIL_COND_V(!meshdata.sources.has(color_source_id), ERR_INVALID_DATA); color_src = &meshdata.sources[color_source_id]; } @@ -904,7 +914,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor material = material_cache[target]; } - } else if (p.material != "") { + } else if (!p.material.is_empty()) { WARN_PRINT("Collada: Unreferenced material in geometry instance: " + p.material); } } @@ -1087,10 +1097,10 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres } } - if (Object::cast_to<EditorSceneImporterMeshNode3D>(node)) { + if (Object::cast_to<ImporterMeshInstance3D>(node)) { Collada::NodeGeometry *ng2 = static_cast<Collada::NodeGeometry *>(p_node); - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(node); + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(node); ERR_FAIL_COND_V(!mi, ERR_BUG); @@ -1099,7 +1109,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres String meshid; Transform3D apply_xform; Vector<int> bone_remap; - Vector<Ref<EditorSceneImporterMesh>> morphs; + Vector<Ref<ImporterMesh>> morphs; if (ng2->controller) { String ngsource = ng2->source; @@ -1168,10 +1178,10 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres for (int i = 0; i < names.size(); i++) { String meshid2 = names[i]; if (collada.state.mesh_data_map.has(meshid2)) { - Ref<EditorSceneImporterMesh> mesh = Ref<EditorSceneImporterMesh>(memnew(EditorSceneImporterMesh)); + Ref<ImporterMesh> mesh = Ref<ImporterMesh>(memnew(ImporterMesh)); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid2]; mesh->set_name(meshdata.name); - Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, nullptr, Vector<Ref<EditorSceneImporterMesh>>(), false); + Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, nullptr, Vector<Ref<ImporterMesh>>(), false); ERR_FAIL_COND_V(err, err); morphs.push_back(mesh); @@ -1188,13 +1198,13 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres } } - ERR_FAIL_COND_V_MSG(ngsource != "", ERR_INVALID_DATA, "Controller instance source '" + ngsource + "' is neither skin or morph!"); + ERR_FAIL_COND_V_MSG(!ngsource.is_empty(), ERR_INVALID_DATA, "Controller instance source '" + ngsource + "' is neither skin or morph!"); } else { meshid = ng2->source; } - Ref<EditorSceneImporterMesh> mesh; + Ref<ImporterMesh> mesh; if (mesh_cache.has(meshid)) { mesh = mesh_cache[meshid]; } else { @@ -1202,16 +1212,16 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres //bleh, must ignore invalid ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid), ERR_INVALID_DATA); - mesh = Ref<EditorSceneImporterMesh>(memnew(EditorSceneImporterMesh)); + mesh = Ref<ImporterMesh>(memnew(ImporterMesh)); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; String name = meshdata.name; - if (name == "") { + if (name.is_empty()) { name = "Mesh"; } int counter = 2; while (mesh_unique_names.has(name)) { name = meshdata.name; - if (name == "") { + if (name.is_empty()) { name = "Mesh"; } name += itos(counter++); @@ -1251,7 +1261,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres } mi->set_surface_material(i, material); - } else if (matname != "") { + } else if (!matname.is_empty()) { WARN_PRINT("Collada: Unreferenced material in geometry instance: " + matname); } } @@ -1314,8 +1324,8 @@ Error ColladaImport::load(const String &p_path, int p_flags, bool p_force_make_t } void ColladaImport::_fix_param_animation_tracks() { - for (Map<String, Collada::Node *>::Element *E = collada.state.scene_map.front(); E; E = E->next()) { - Collada::Node *n = E->get(); + for (KeyValue<String, Collada::Node *> &E : collada.state.scene_map) { + Collada::Node *n = E.value; switch (n->type) { case Collada::Node::TYPE_NODE: { // ? do nothing @@ -1333,7 +1343,7 @@ void ColladaImport::_fix_param_animation_tracks() { // test source(s) String source = ng->source; - while (source != "") { + while (!source.is_empty()) { if (collada.state.skin_controller_data_map.has(source)) { const Collada::SkinControllerData &skin = collada.state.skin_controller_data_map[source]; @@ -1363,7 +1373,7 @@ void ColladaImport::_fix_param_animation_tracks() { for (int rti = 0; rti < rt.size(); rti++) { Collada::AnimationTrack *at = &collada.state.animation_tracks.write[rt[rti]]; - at->target = E->key(); + at->target = E.key; at->param = "morph/" + collada.state.mesh_name_map[mesh_name]; at->property = true; //at->param @@ -1383,7 +1393,7 @@ void ColladaImport::_fix_param_animation_tracks() { } } -void ColladaImport::create_animations(bool p_make_tracks_in_all_bones, bool p_import_value_tracks) { +void ColladaImport::create_animations(bool p_import_value_tracks) { _fix_param_animation_tracks(); for (int i = 0; i < collada.state.animation_clips.size(); i++) { for (int j = 0; j < collada.state.animation_clips[i].tracks.size(); j++) { @@ -1416,13 +1426,13 @@ void ColladaImport::create_animations(bool p_make_tracks_in_all_bones, bool p_im } } - create_animation(-1, p_make_tracks_in_all_bones, p_import_value_tracks); + create_animation(-1, p_import_value_tracks); for (int i = 0; i < collada.state.animation_clips.size(); i++) { - create_animation(i, p_make_tracks_in_all_bones, p_import_value_tracks); + create_animation(i, p_import_value_tracks); } } -void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks) { +void ColladaImport::create_animation(int p_clip, bool p_import_value_tracks) { Ref<Animation> animation = Ref<Animation>(memnew(Animation)); if (p_clip == -1) { @@ -1431,11 +1441,11 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones animation->set_name(collada.state.animation_clips[p_clip].name); } - for (Map<String, NodeMap>::Element *E = node_map.front(); E; E = E->next()) { - if (E->get().bone < 0) { + for (const KeyValue<String, NodeMap> &E : node_map) { + if (E.value.bone < 0) { continue; } - bones_with_animation[E->key()] = false; + bones_with_animation[E.key] = false; } //store and validate tracks @@ -1521,10 +1531,55 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones continue; } - animation->add_track(Animation::TYPE_TRANSFORM3D); - int track = animation->get_track_count() - 1; - animation->track_set_path(track, path); - animation->track_set_imported(track, true); //helps merging later + bool has_position = false; + bool has_rotation = false; + bool has_scale = false; + + for (int i = 0; cn->xform_list.size(); i++) { + switch (cn->xform_list[i].op) { + case Collada::Node::XForm::OP_ROTATE: { + has_rotation = true; + } break; + case Collada::Node::XForm::OP_SCALE: { + has_scale = true; + } break; + case Collada::Node::XForm::OP_TRANSLATE: { + has_position = true; + } break; + case Collada::Node::XForm::OP_MATRIX: { + has_position = true; + has_rotation = true; + has_scale = true; + } break; + case Collada::Node::XForm::OP_VISIBILITY: { + } break; + } + } + + int base_track = animation->get_track_count(); + int position_idx = -1; + if (has_position) { + position_idx = animation->get_track_count(); + animation->add_track(Animation::TYPE_POSITION_3D); + animation->track_set_path(position_idx, path); + animation->track_set_imported(position_idx, true); //helps merging later + } + + int rotation_idx = -1; + if (has_rotation) { + rotation_idx = animation->get_track_count(); + animation->add_track(Animation::TYPE_ROTATION_3D); + animation->track_set_path(rotation_idx, path); + animation->track_set_imported(rotation_idx, true); //helps merging later + } + + int scale_idx = -1; + if (has_scale) { + scale_idx = animation->get_track_count(); + animation->add_track(Animation::TYPE_SCALE_3D); + animation->track_set_path(scale_idx, path); + animation->track_set_imported(scale_idx, true); //helps merging later + } Vector<real_t> snapshots = base_snapshots; @@ -1593,22 +1648,20 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones Transform3D xform = cn->compute_transform(collada); xform = collada.fix_transform(xform) * cn->post_transform; - if (nm.bone >= 0) { - //make bone transform relative to rest (in case of skeleton) - Skeleton3D *sk = Object::cast_to<Skeleton3D>(nm.node); - if (sk) { - xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform; - } else { - ERR_PRINT("Collada: Invalid skeleton"); - } - } - Vector3 s = xform.basis.get_scale(); bool singular_matrix = Math::is_zero_approx(s.x) || Math::is_zero_approx(s.y) || Math::is_zero_approx(s.z); Quaternion q = singular_matrix ? Quaternion() : xform.basis.get_rotation_quaternion(); Vector3 l = xform.origin; - animation->transform_track_insert_key(track, snapshots[i], l, q, s); + if (position_idx >= 0) { + animation->position_track_insert_key(position_idx, snapshots[i], l); + } + if (rotation_idx >= 0) { + animation->rotation_track_insert_key(rotation_idx, snapshots[i], q); + } + if (scale_idx >= 0) { + animation->scale_track_insert_key(scale_idx, snapshots[i], s); + } } if (nm.bone >= 0) { @@ -1620,48 +1673,15 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones if (found_anim) { tracks_found = true; } else { - animation->remove_track(track); - } - } - - if (p_make_tracks_in_all_bones) { - //some bones may lack animation, but since we don't store pose as a property, we must add keyframes! - for (Map<String, bool>::Element *E = bones_with_animation.front(); E; E = E->next()) { - if (E->get()) { - continue; + if (position_idx >= 0) { + animation->remove_track(base_track); } - - NodeMap &nm = node_map[E->key()]; - String path = scene->get_path_to(nm.node); - ERR_CONTINUE(nm.bone < 0); - Skeleton3D *sk = static_cast<Skeleton3D *>(nm.node); - String name = sk->get_bone_name(nm.bone); - path = path + ":" + name; - - Collada::Node *cn = collada.state.scene_map[E->key()]; - if (cn->ignore_anim) { - WARN_PRINT("Collada: Ignoring animation on node: " + path); - continue; + if (rotation_idx >= 0) { + animation->remove_track(base_track); + } + if (scale_idx >= 0) { + animation->remove_track(base_track); } - - animation->add_track(Animation::TYPE_TRANSFORM3D); - int track = animation->get_track_count() - 1; - animation->track_set_path(track, path); - animation->track_set_imported(track, true); //helps merging later - - Transform3D xform = cn->compute_transform(collada); - xform = collada.fix_transform(xform) * cn->post_transform; - - xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform; - - Vector3 s = xform.basis.get_scale(); - bool singular_matrix = Math::is_zero_approx(s.x) || Math::is_zero_approx(s.y) || Math::is_zero_approx(s.z); - Quaternion q = singular_matrix ? Quaternion() : xform.basis.get_rotation_quaternion(); - Vector3 l = xform.origin; - - animation->transform_track_insert_key(track, 0, l, q, s); - - tracks_found = true; } } @@ -1689,7 +1709,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones NodeMap &nm = node_map[at.target]; String path = scene->get_path_to(nm.node); - animation->add_track(Animation::TYPE_VALUE); + animation->add_track(Animation::TYPE_BLEND_SHAPE); int track = animation->get_track_count() - 1; path = path + ":" + at.param; @@ -1711,7 +1731,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones WARN_PRINT("Collada: Unexpected amount of value keys: " + itos(data.size())); } - animation->track_insert_key(track, time, value); + animation->blend_shape_track_insert_key(track, time, value); } tracks_found = true; @@ -1727,15 +1747,15 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones /*************************************** SCENE ***********************************/ /*********************************************************************************/ -uint32_t EditorSceneImporterCollada::get_import_flags() const { +uint32_t EditorSceneFormatImporterCollada::get_import_flags() const { return IMPORT_SCENE | IMPORT_ANIMATION; } -void EditorSceneImporterCollada::get_extensions(List<String> *r_extensions) const { +void EditorSceneFormatImporterCollada::get_extensions(List<String> *r_extensions) const { r_extensions->push_back("dae"); } -Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { if (r_err) { *r_err = OK; } @@ -1748,7 +1768,7 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ state.use_mesh_builtin_materials = true; state.bake_fps = p_bake_fps; - Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, false); + Error err = state.load(p_path, flags, p_flags & EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, false); if (r_err) { *r_err = err; @@ -1772,11 +1792,11 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ } if (p_flags & IMPORT_ANIMATION) { - state.create_animations(true, true); + state.create_animations(true); AnimationPlayer *ap = memnew(AnimationPlayer); for (int i = 0; i < state.animations.size(); i++) { String name; - if (state.animations[i]->get_name() == "") { + if (state.animations[i]->get_name().is_empty()) { name = "default"; } else { name = state.animations[i]->get_name(); @@ -1784,22 +1804,22 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ ap->add_animation(name, state.animations[i]); } - state.scene->add_child(ap); + state.scene->add_child(ap, true); ap->set_owner(state.scene); } return state.scene; } -Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref<Animation> EditorSceneFormatImporterCollada::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { ColladaImport state; state.use_mesh_builtin_materials = false; - Error err = state.load(p_path, Collada::IMPORT_FLAG_ANIMATION, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS); + Error err = state.load(p_path, Collada::IMPORT_FLAG_ANIMATION, p_flags & EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS); ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot load animation from file '" + p_path + "'."); - state.create_animations(true, true); + state.create_animations(true); if (state.scene) { memdelete(state.scene); } @@ -1812,5 +1832,5 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String &p_path return anim; } -EditorSceneImporterCollada::EditorSceneImporterCollada() { +EditorSceneFormatImporterCollada::EditorSceneFormatImporterCollada() { } diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h index bf45322765..c32d785d1c 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/editor_import_collada.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,16 +33,16 @@ #include "editor/import/resource_importer_scene.h" -class EditorSceneImporterCollada : public EditorSceneImporter { - GDCLASS(EditorSceneImporterCollada, EditorSceneImporter); +class EditorSceneFormatImporterCollada : public EditorSceneFormatImporter { + GDCLASS(EditorSceneFormatImporterCollada, EditorSceneFormatImporter); public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override; + virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override; - EditorSceneImporterCollada(); + EditorSceneFormatImporterCollada(); }; #endif diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp index d219f6e325..cf3464b168 100644 --- a/editor/import/editor_import_plugin.cpp +++ b/editor/import/editor_import_plugin.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,6 +57,7 @@ void EditorImportPlugin::get_recognized_extensions(List<String> *p_extensions) c for (int i = 0; i < extensions.size(); i++) { p_extensions->push_back(extensions[i]); } + return; } ERR_FAIL_MSG("Unimplemented _get_recognized_extensions in add-on."); } @@ -109,12 +110,12 @@ int EditorImportPlugin::get_import_order() const { ERR_FAIL_V_MSG(-1, "Unimplemented _get_import_order in add-on."); } -void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption> *r_options, int p_preset) const { +void EditorImportPlugin::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options, int p_preset) const { Array needed; needed.push_back("name"); needed.push_back("default_value"); Array options; - if (GDVIRTUAL_CALL(_get_import_options, p_preset, options)) { + if (GDVIRTUAL_CALL(_get_import_options, p_path, p_preset, options)) { for (int i = 0; i < options.size(); i++) { Dictionary d = options[i]; ERR_FAIL_COND(!d.has_all(needed)); @@ -139,12 +140,13 @@ void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption> ImportOption option(PropertyInfo(default_value.get_type(), name, hint, hint_string, usage), default_value); r_options->push_back(option); } + return; } ERR_FAIL_MSG("Unimplemented _get_import_options in add-on."); } -bool EditorImportPlugin::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool EditorImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { Dictionary d; Map<StringName, Variant>::Element *E = p_options.front(); while (E) { @@ -152,7 +154,7 @@ bool EditorImportPlugin::get_option_visibility(const String &p_option, const Map E = E->next(); } bool visible; - if (GDVIRTUAL_CALL(_get_option_visibility, p_option, d, visible)) { + if (GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, d, visible)) { return visible; } @@ -190,11 +192,11 @@ void EditorImportPlugin::_bind_methods() { GDVIRTUAL_BIND(_get_preset_count) GDVIRTUAL_BIND(_get_preset_name, "preset_index") GDVIRTUAL_BIND(_get_recognized_extensions) - GDVIRTUAL_BIND(_get_import_options, "preset_index") + GDVIRTUAL_BIND(_get_import_options, "path", "preset_index") GDVIRTUAL_BIND(_get_save_extension) GDVIRTUAL_BIND(_get_resource_type) GDVIRTUAL_BIND(_get_priority) GDVIRTUAL_BIND(_get_import_order) - GDVIRTUAL_BIND(_get_option_visibility, "option_name", "options") + GDVIRTUAL_BIND(_get_option_visibility, "path", "option_name", "options") GDVIRTUAL_BIND(_import, "source_file", "save_path", "options", "platform_variants", "gen_files"); } diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index 49c959ab44..6cff8fb917 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -44,12 +44,12 @@ protected: GDVIRTUAL0RC(int, _get_preset_count) GDVIRTUAL1RC(String, _get_preset_name, int) GDVIRTUAL0RC(Vector<String>, _get_recognized_extensions) - GDVIRTUAL1RC(Array, _get_import_options, int) + GDVIRTUAL2RC(Array, _get_import_options, String, int) GDVIRTUAL0RC(String, _get_save_extension) GDVIRTUAL0RC(String, _get_resource_type) GDVIRTUAL0RC(float, _get_priority) GDVIRTUAL0RC(int, _get_import_order) - GDVIRTUAL2RC(bool, _get_option_visibility, StringName, Dictionary) + GDVIRTUAL3RC(bool, _get_option_visibility, String, StringName, Dictionary) GDVIRTUAL5RC(int, _import, String, String, Dictionary, Array, Array) public: @@ -63,8 +63,8 @@ public: virtual String get_resource_type() const override; virtual float get_priority() const override; virtual int get_import_order() const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata = nullptr) override; }; diff --git a/editor/import/editor_importer_bake_reset.cpp b/editor/import/editor_importer_bake_reset.cpp deleted file mode 100644 index 00dce6850e..0000000000 --- a/editor/import/editor_importer_bake_reset.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/*************************************************************************/ -/* editor_importer_bake_reset.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "editor/import/editor_importer_bake_reset.h" - -#include "core/error/error_list.h" -#include "core/error/error_macros.h" -#include "core/math/transform_3d.h" -#include "editor/import/scene_importer_mesh_node_3d.h" -#include "resource_importer_scene.h" -#include "scene/3d/mesh_instance_3d.h" -#include "scene/3d/node_3d.h" -#include "scene/3d/skeleton_3d.h" -#include "scene/animation/animation_player.h" - -// Given that an engineering team has made a reference character, one wants ten animators to create animations. -// Currently, a tech artist needs to combine the ten files into one exported gltf2 to import into Godot Engine. -// We bake the RESET animation and then set it to identity, -// so that rigs with corresponding RESET animation can have their animations transferred with ease. -// -// The original algorithm for the code was used to change skeleton bone rolls to be parent to child. -// -// Reference https://github.com/godotengine/godot-proposals/issues/2961 -void BakeReset::_bake_animation_pose(Node *scene, const String &p_bake_anim) { - Map<StringName, BakeResetRestBone> r_rest_bones; - Vector<Node3D *> r_meshes; - List<Node *> queue; - queue.push_back(scene); - while (!queue.is_empty()) { - List<Node *>::Element *E = queue.front(); - Node *node = E->get(); - AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(node); - // Step 1: import scene with animations into the rest bones data structure. - _fetch_reset_animation(ap, r_rest_bones, p_bake_anim); - - int child_count = node->get_child_count(); - for (int i = 0; i < child_count; i++) { - queue.push_back(node->get_child(i)); - } - queue.pop_front(); - } - - queue.push_back(scene); - while (!queue.is_empty()) { - List<Node *>::Element *E = queue.front(); - Node *node = E->get(); - EditorSceneImporterMeshNode3D *editor_mesh_3d = scene->cast_to<EditorSceneImporterMeshNode3D>(node); - MeshInstance3D *mesh_3d = scene->cast_to<MeshInstance3D>(node); - if (scene->cast_to<Skeleton3D>(node)) { - Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node); - - // Step 2: Bake the RESET animation from the RestBone to the skeleton. - _fix_skeleton(skeleton, r_rest_bones); - } - if (editor_mesh_3d) { - NodePath path = editor_mesh_3d->get_skeleton_path(); - if (!path.is_empty() && editor_mesh_3d->get_node_or_null(path) && Object::cast_to<Skeleton3D>(editor_mesh_3d->get_node_or_null(path))) { - r_meshes.push_back(editor_mesh_3d); - } - } else if (mesh_3d) { - NodePath path = mesh_3d->get_skeleton_path(); - if (!path.is_empty() && mesh_3d->get_node_or_null(path) && Object::cast_to<Skeleton3D>(mesh_3d->get_node_or_null(path))) { - r_meshes.push_back(mesh_3d); - } - } - int child_count = node->get_child_count(); - for (int i = 0; i < child_count; i++) { - queue.push_back(node->get_child(i)); - } - queue.pop_front(); - } - - queue.push_back(scene); - while (!queue.is_empty()) { - List<Node *>::Element *E = queue.front(); - Node *node = E->get(); - AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(node); - if (ap) { - // Step 3: Key all RESET animation frames to identity. - _align_animations(ap, r_rest_bones); - } - - int child_count = node->get_child_count(); - for (int i = 0; i < child_count; i++) { - queue.push_back(node->get_child(i)); - } - queue.pop_front(); - } -} - -void BakeReset::_align_animations(AnimationPlayer *p_ap, const Map<StringName, BakeResetRestBone> &r_rest_bones) { - ERR_FAIL_NULL(p_ap); - List<StringName> anim_names; - p_ap->get_animation_list(&anim_names); - for (List<StringName>::Element *anim_i = anim_names.front(); anim_i; anim_i = anim_i->next()) { - Ref<Animation> a = p_ap->get_animation(anim_i->get()); - ERR_CONTINUE(a.is_null()); - for (Map<StringName, BakeResetRestBone>::Element *rest_bone_i = r_rest_bones.front(); rest_bone_i; rest_bone_i = rest_bone_i->next()) { - int track = a->find_track(NodePath(rest_bone_i->key())); - if (track == -1) { - continue; - } - int new_track = a->add_track(Animation::TYPE_TRANSFORM3D); - NodePath new_path = NodePath(rest_bone_i->key()); - BakeResetRestBone rest_bone = rest_bone_i->get(); - a->track_set_path(new_track, new_path); - for (int key_i = 0; key_i < a->track_get_key_count(track); key_i++) { - Vector3 loc; - Quaternion rot; - Vector3 scale; - Error err = a->transform_track_get_key(track, key_i, &loc, &rot, &scale); - ERR_CONTINUE(err); - real_t time = a->track_get_key_time(track, key_i); - rot.normalize(); - loc = loc - rest_bone.loc; - rot = rest_bone.rest_delta.get_rotation_quaternion().inverse() * rot; - rot.normalize(); - scale = Vector3(1, 1, 1) - (rest_bone.rest_delta.get_scale() - scale); - // Apply the reverse of the rest changes to make the key be close to identity transform. - a->transform_track_insert_key(new_track, time, loc, rot, scale); - } - a->remove_track(track); - } - } -} - -void BakeReset::_fetch_reset_animation(AnimationPlayer *p_ap, Map<StringName, BakeResetRestBone> &r_rest_bones, const String &p_bake_anim) { - if (!p_ap) { - return; - } - List<StringName> anim_names; - p_ap->get_animation_list(&anim_names); - Node *root = p_ap->get_owner(); - ERR_FAIL_NULL(root); - if (!p_ap->has_animation(p_bake_anim)) { - return; - } - Ref<Animation> a = p_ap->get_animation(p_bake_anim); - if (a.is_null()) { - return; - } - for (int32_t track = 0; track < a->get_track_count(); track++) { - NodePath path = a->track_get_path(track); - String string_path = path; - Skeleton3D *skeleton = root->cast_to<Skeleton3D>(root->get_node(string_path.get_slice(":", 0))); - if (!skeleton) { - continue; - } - String bone_name = string_path.get_slice(":", 1); - for (int key_i = 0; key_i < a->track_get_key_count(track); key_i++) { - Vector3 loc; - Quaternion rot; - Vector3 scale; - Error err = a->transform_track_get_key(track, key_i, &loc, &rot, &scale); - if (err != OK) { - ERR_PRINT_ONCE("Reset animation baker can't get key."); - continue; - } - rot.normalize(); - Basis rot_basis = Basis(rot, scale); - BakeResetRestBone rest_bone; - rest_bone.rest_delta = rot_basis; - rest_bone.loc = loc; - // Store the animation into the RestBone. - r_rest_bones[StringName(String(skeleton->get_owner()->get_path_to(skeleton)) + ":" + bone_name)] = rest_bone; - break; - } - } -} - -void BakeReset::_fix_skeleton(Skeleton3D *p_skeleton, Map<StringName, BakeReset::BakeResetRestBone> &r_rest_bones) { - int bone_count = p_skeleton->get_bone_count(); - - // First iterate through all the bones and update the RestBone. - for (int j = 0; j < bone_count; j++) { - StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(j); - BakeResetRestBone &rest_bone = r_rest_bones[final_path]; - rest_bone.rest_local = p_skeleton->get_bone_rest(j); - } - for (int i = 0; i < bone_count; i++) { - int parent_bone = p_skeleton->get_bone_parent(i); - String path = p_skeleton->get_owner()->get_path_to(p_skeleton); - StringName final_path = String(path) + String(":") + p_skeleton->get_bone_name(parent_bone); - if (parent_bone >= 0) { - r_rest_bones[path].children.push_back(i); - } - } - - // When we apply transform to a bone, we also have to move all of its children in the opposite direction. - for (int i = 0; i < bone_count; i++) { - StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(i); - r_rest_bones[final_path].rest_local = r_rest_bones[final_path].rest_local * Transform3D(r_rest_bones[final_path].rest_delta, r_rest_bones[final_path].loc); - // Iterate through the children and move in the opposite direction. - for (int j = 0; j < r_rest_bones[final_path].children.size(); j++) { - int child_index = r_rest_bones[final_path].children[j]; - StringName children_path = String(p_skeleton->get_name()) + String(":") + p_skeleton->get_bone_name(child_index); - r_rest_bones[children_path].rest_local = Transform3D(r_rest_bones[final_path].rest_delta, r_rest_bones[final_path].loc).affine_inverse() * r_rest_bones[children_path].rest_local; - } - } - - for (int i = 0; i < bone_count; i++) { - StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(i); - ERR_CONTINUE(!r_rest_bones.has(final_path)); - Transform3D rest_transform = r_rest_bones[final_path].rest_local; - p_skeleton->set_bone_rest(i, rest_transform); - } -} diff --git a/editor/import/editor_importer_bake_reset.h b/editor/import/editor_importer_bake_reset.h deleted file mode 100644 index e36ae86181..0000000000 --- a/editor/import/editor_importer_bake_reset.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************/ -/* editor_importer_bake_reset.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 RESOURCE_IMPORTER_BAKE_RESET_H -#define RESOURCE_IMPORTER_BAKE_RESET_H - -#include "scene/main/node.h" - -class Skeleton3D; -class AnimationPlayer; -class BakeReset { - struct BakeResetRestBone { - Transform3D rest_local; - Basis rest_delta; - Vector3 loc; - Vector<int> children; - }; - -public: - void _bake_animation_pose(Node *scene, const String &p_bake_anim); - -private: - void _fix_skeleton(Skeleton3D *p_skeleton, Map<StringName, BakeReset::BakeResetRestBone> &r_rest_bones); - void _align_animations(AnimationPlayer *p_ap, const Map<StringName, BakeResetRestBone> &r_rest_bones); - void _fetch_reset_animation(AnimationPlayer *p_ap, Map<StringName, BakeResetRestBone> &r_rest_bones, const String &p_bake_anim); -}; -#endif diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp index 7fd9230284..16b68bcc22 100644 --- a/editor/import/resource_importer_bitmask.cpp +++ b/editor/import/resource_importer_bitmask.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,7 +57,7 @@ String ResourceImporterBitMap::get_resource_type() const { return "BitMap"; } -bool ResourceImporterBitMap::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterBitMap::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -69,7 +69,7 @@ String ResourceImporterBitMap::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterBitMap::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterBitMap::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "create_from", PROPERTY_HINT_ENUM, "Black & White,Alpha"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.5)); } diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h index d68693c54a..e5cf1facff 100644 --- a/editor/import/resource_importer_bitmask.h +++ b/editor/import/resource_importer_bitmask.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -49,8 +49,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterBitMap(); diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp index 2e7ef1402b..8a655fbc0c 100644 --- a/editor/import/resource_importer_bmfont.cpp +++ b/editor/import/resource_importer_bmfont.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,6 @@ #include "resource_importer_bmfont.h" -#include "core/io/image_loader.h" #include "core/io/resource_saver.h" String ResourceImporterBMFont::get_importer_name() const { @@ -56,730 +55,22 @@ String ResourceImporterBMFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterBMFont::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterBMFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } -void ResourceImporterBMFont::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterBMFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true)); } -void _convert_packed_8bit(Ref<FontData> &r_font, Ref<Image> &p_source, int p_page, int p_sz) { - int w = p_source->get_width(); - int h = p_source->get_height(); - - PackedByteArray imgdata = p_source->get_data(); - const uint8_t *r = imgdata.ptr(); - - PackedByteArray imgdata_r; - imgdata_r.resize(w * h * 2); - uint8_t *wr = imgdata_r.ptrw(); - - PackedByteArray imgdata_g; - imgdata_g.resize(w * h * 2); - uint8_t *wg = imgdata_g.ptrw(); - - PackedByteArray imgdata_b; - imgdata_b.resize(w * h * 2); - uint8_t *wb = imgdata_b.ptrw(); - - PackedByteArray imgdata_a; - imgdata_a.resize(w * h * 2); - uint8_t *wa = imgdata_a.ptrw(); - - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - int ofs_src = (i * w + j) * 4; - int ofs_dst = (i * w + j) * 2; - wr[ofs_dst + 0] = 255; - wr[ofs_dst + 1] = r[ofs_src + 0]; - wg[ofs_dst + 0] = 255; - wg[ofs_dst + 1] = r[ofs_src + 1]; - wb[ofs_dst + 0] = 255; - wb[ofs_dst + 1] = r[ofs_src + 2]; - wa[ofs_dst + 0] = 255; - wa[ofs_dst + 1] = r[ofs_src + 3]; - } - } - Ref<Image> img_r = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_r)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 0, img_r); - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 1, img_g); - Ref<Image> img_b = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_b)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 2, img_b); - Ref<Image> img_a = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_a)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a); -} - -void _convert_packed_4bit(Ref<FontData> &r_font, Ref<Image> &p_source, int p_page, int p_sz) { - int w = p_source->get_width(); - int h = p_source->get_height(); - - PackedByteArray imgdata = p_source->get_data(); - const uint8_t *r = imgdata.ptr(); - - PackedByteArray imgdata_r; - imgdata_r.resize(w * h * 2); - uint8_t *wr = imgdata_r.ptrw(); - - PackedByteArray imgdata_g; - imgdata_g.resize(w * h * 2); - uint8_t *wg = imgdata_g.ptrw(); - - PackedByteArray imgdata_b; - imgdata_b.resize(w * h * 2); - uint8_t *wb = imgdata_b.ptrw(); - - PackedByteArray imgdata_a; - imgdata_a.resize(w * h * 2); - uint8_t *wa = imgdata_a.ptrw(); - - PackedByteArray imgdata_ro; - imgdata_ro.resize(w * h * 2); - uint8_t *wro = imgdata_ro.ptrw(); - - PackedByteArray imgdata_go; - imgdata_go.resize(w * h * 2); - uint8_t *wgo = imgdata_go.ptrw(); - - PackedByteArray imgdata_bo; - imgdata_bo.resize(w * h * 2); - uint8_t *wbo = imgdata_bo.ptrw(); - - PackedByteArray imgdata_ao; - imgdata_ao.resize(w * h * 2); - uint8_t *wao = imgdata_ao.ptrw(); - - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - int ofs_src = (i * w + j) * 4; - int ofs_dst = (i * w + j) * 2; - wr[ofs_dst + 0] = 255; - wro[ofs_dst + 0] = 255; - if (r[ofs_src + 0] > 0x0F) { - wr[ofs_dst + 1] = (r[ofs_src + 0] - 0x0F) * 2; - wro[ofs_dst + 1] = 0; - } else { - wr[ofs_dst + 1] = 0; - wro[ofs_dst + 1] = r[ofs_src + 0] * 2; - } - wg[ofs_dst + 0] = 255; - wgo[ofs_dst + 0] = 255; - if (r[ofs_src + 1] > 0x0F) { - wg[ofs_dst + 1] = (r[ofs_src + 1] - 0x0F) * 2; - wgo[ofs_dst + 1] = 0; - } else { - wg[ofs_dst + 1] = 0; - wgo[ofs_dst + 1] = r[ofs_src + 1] * 2; - } - wb[ofs_dst + 0] = 255; - wbo[ofs_dst + 0] = 255; - if (r[ofs_src + 2] > 0x0F) { - wb[ofs_dst + 1] = (r[ofs_src + 2] - 0x0F) * 2; - wbo[ofs_dst + 1] = 0; - } else { - wb[ofs_dst + 1] = 0; - wbo[ofs_dst + 1] = r[ofs_src + 2] * 2; - } - wa[ofs_dst + 0] = 255; - wao[ofs_dst + 0] = 255; - if (r[ofs_src + 3] > 0x0F) { - wa[ofs_dst + 1] = (r[ofs_src + 3] - 0x0F) * 2; - wao[ofs_dst + 1] = 0; - } else { - wa[ofs_dst + 1] = 0; - wao[ofs_dst + 1] = r[ofs_src + 3] * 2; - } - } - } - Ref<Image> img_r = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_r)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 0, img_r); - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 1, img_g); - Ref<Image> img_b = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_b)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 2, img_b); - Ref<Image> img_a = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_a)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a); - - Ref<Image> img_ro = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_ro)); - r_font->set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 0, img_ro); - Ref<Image> img_go = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_go)); - r_font->set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 1, img_go); - Ref<Image> img_bo = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_bo)); - r_font->set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 2, img_bo); - Ref<Image> img_ao = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_ao)); - r_font->set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 3, img_ao); -} - -void _convert_rgba_4bit(Ref<FontData> &r_font, Ref<Image> &p_source, int p_page, int p_sz) { - int w = p_source->get_width(); - int h = p_source->get_height(); - - PackedByteArray imgdata = p_source->get_data(); - const uint8_t *r = imgdata.ptr(); - - PackedByteArray imgdata_g; - imgdata_g.resize(w * h * 4); - uint8_t *wg = imgdata_g.ptrw(); - - PackedByteArray imgdata_o; - imgdata_o.resize(w * h * 4); - uint8_t *wo = imgdata_o.ptrw(); - - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - int ofs = (i * w + j) * 4; - - if (r[ofs + 0] > 0x7F) { - wg[ofs + 0] = r[ofs + 0]; - wo[ofs + 0] = 0; - } else { - wg[ofs + 0] = 0; - wo[ofs + 0] = r[ofs + 0] * 2; - } - if (r[ofs + 1] > 0x7F) { - wg[ofs + 1] = r[ofs + 1]; - wo[ofs + 1] = 0; - } else { - wg[ofs + 1] = 0; - wo[ofs + 1] = r[ofs + 1] * 2; - } - if (r[ofs + 2] > 0x7F) { - wg[ofs + 2] = r[ofs + 2]; - wo[ofs + 2] = 0; - } else { - wg[ofs + 2] = 0; - wo[ofs + 2] = r[ofs + 2] * 2; - } - if (r[ofs + 3] > 0x7F) { - wg[ofs + 3] = r[ofs + 3]; - wo[ofs + 3] = 0; - } else { - wg[ofs + 3] = 0; - wo[ofs + 3] = r[ofs + 3] * 2; - } - } - } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_RGBA8, imgdata_g)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page, img_g); - - Ref<Image> img_o = memnew(Image(w, h, 0, Image::FORMAT_RGBA8, imgdata_o)); - r_font->set_texture_image(0, Vector2i(p_sz, 1), p_page, img_o); -} - -void _convert_mono_8bit(Ref<FontData> &r_font, Ref<Image> &p_source, int p_page, int p_ch, int p_sz, int p_ol) { - int w = p_source->get_width(); - int h = p_source->get_height(); - - PackedByteArray imgdata = p_source->get_data(); - const uint8_t *r = imgdata.ptr(); - - int size = 4; - if (p_source->get_format() == Image::FORMAT_L8) { - size = 1; - p_ch = 0; - } - - PackedByteArray imgdata_g; - imgdata_g.resize(w * h * 2); - uint8_t *wg = imgdata_g.ptrw(); - - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - int ofs_src = (i * w + j) * size; - int ofs_dst = (i * w + j) * 2; - wg[ofs_dst + 0] = 255; - wg[ofs_dst + 1] = r[ofs_src + p_ch]; - } - } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); - r_font->set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_g); -} - -void _convert_mono_4bit(Ref<FontData> &r_font, Ref<Image> &p_source, int p_page, int p_ch, int p_sz, int p_ol) { - int w = p_source->get_width(); - int h = p_source->get_height(); - - PackedByteArray imgdata = p_source->get_data(); - const uint8_t *r = imgdata.ptr(); - - int size = 4; - if (p_source->get_format() == Image::FORMAT_L8) { - size = 1; - p_ch = 0; - } - - PackedByteArray imgdata_g; - imgdata_g.resize(w * h * 2); - uint8_t *wg = imgdata_g.ptrw(); - - PackedByteArray imgdata_o; - imgdata_o.resize(w * h * 2); - uint8_t *wo = imgdata_o.ptrw(); - - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - int ofs_src = (i * w + j) * size; - int ofs_dst = (i * w + j) * 2; - wg[ofs_dst + 0] = 255; - wo[ofs_dst + 0] = 255; - if (r[ofs_src + p_ch] > 0x7F) { - wg[ofs_dst + 1] = r[ofs_src + p_ch]; - wo[ofs_dst + 1] = 0; - } else { - wg[ofs_dst + 1] = 0; - wo[ofs_dst + 1] = r[ofs_src + p_ch] * 2; - } - } - } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); - r_font->set_texture_image(0, Vector2i(p_sz, 0), p_page, img_g); - - Ref<Image> img_o = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_o)); - r_font->set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_o); -} - Error ResourceImporterBMFont::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing BMFont font from: " + p_source_file); Ref<FontData> font; font.instantiate(); - font->set_antialiased(false); - font->set_multichannel_signed_distance_field(false); - font->set_force_autohinter(false); - font->set_hinting(TextServer::HINTING_NONE); - font->set_oversampling(1.0f); - - FileAccessRef f = FileAccess::open(p_source_file, FileAccess::READ); - if (f == nullptr) { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, TTR("Cannot open font from file ") + "\"" + p_source_file + "\"."); - } - - int base_size = 16; - int height = 0; - int ascent = 0; - int outline = 0; - - bool packed = false; - uint8_t ch[4] = { 0, 0, 0, 0 }; // RGBA - int first_gl_ch = -1; - int first_ol_ch = -1; - int first_cm_ch = -1; - - unsigned char magic[4]; - f->get_buffer((unsigned char *)&magic, 4); - if (magic[0] == 'B' && magic[1] == 'M' && magic[2] == 'F') { - // Binary BMFont file. - ERR_FAIL_COND_V_MSG(magic[3] != 3, ERR_CANT_CREATE, vformat(TTR("Version %d of BMFont is not supported."), (int)magic[3])); - - uint8_t block_type = f->get_8(); - uint32_t block_size = f->get_32(); - while (!f->eof_reached()) { - uint64_t off = f->get_position(); - switch (block_type) { - case 1: /* info */ { - ERR_FAIL_COND_V_MSG(block_size < 15, ERR_CANT_CREATE, TTR("Invalid BMFont info block size.")); - base_size = f->get_16(); - uint8_t flags = f->get_8(); - ERR_FAIL_COND_V_MSG(flags & 0x02, ERR_CANT_CREATE, TTR("Non-unicode version of BMFont is not supported.")); - f->get_8(); // non-unicode charset, skip - f->get_16(); // stretch_h, skip - f->get_8(); // aa, skip - f->get_32(); // padding, skip - f->get_16(); // spacing, skip - outline = f->get_8(); - // font name, skip - font->set_fixed_size(base_size); - } break; - case 2: /* common */ { - ERR_FAIL_COND_V_MSG(block_size != 15, ERR_CANT_CREATE, TTR("Invalid BMFont common block size.")); - height = f->get_16(); - ascent = f->get_16(); - f->get_32(); // scale, skip - f->get_16(); // pages, skip - uint8_t flags = f->get_8(); - packed = (flags & 0x01); - ch[3] = f->get_8(); - ch[0] = f->get_8(); - ch[1] = f->get_8(); - ch[2] = f->get_8(); - for (int i = 0; i < 4; i++) { - if (ch[i] == 0 && first_gl_ch == -1) { - first_gl_ch = i; - } - if (ch[i] == 1 && first_ol_ch == -1) { - first_ol_ch = i; - } - if (ch[i] == 2 && first_cm_ch == -1) { - first_cm_ch = i; - } - } - } break; - case 3: /* pages */ { - int page = 0; - CharString cs; - char32_t c = f->get_8(); - while (!f->eof_reached() && f->get_position() <= off + block_size) { - if (c == '\0') { - String base_dir = p_source_file.get_base_dir(); - String file = base_dir.plus_file(String::utf8(cs.ptr(), cs.length())); - if (RenderingServer::get_singleton() != nullptr) { - Ref<Image> img; - img.instantiate(); - Error err = ImageLoader::load_image(file, img); - ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, TTR("Can't load font texture: ") + "\"" + file + "\"."); - - if (packed) { - if (ch[3] == 0) { // 4 x 8 bit monochrome, no outline - outline = 0; - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_packed_8bit(font, img, page, base_size); - } else if ((ch[3] == 2) && (outline > 0)) { // 4 x 4 bit monochrome, gl + outline - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_packed_4bit(font, img, page, base_size); - } else { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, TTR("Unsupported BMFont texture format.")); - } - } else { - if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline - outline = 0; - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - font->set_texture_image(0, Vector2i(base_size, 0), page, img); - } else if ((ch[0] == 2) && (ch[1] == 2) && (ch[2] == 2) && (ch[3] == 2) && (outline > 0)) { // RGBA4 color, gl + outline - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_rgba_4bit(font, img, page, base_size); - } else if ((first_gl_ch >= 0) && (first_ol_ch >= 0) && (outline > 0)) { // 1 x 8 bit monochrome, gl + outline - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_mono_8bit(font, img, page, first_gl_ch, base_size, 0); - _convert_mono_8bit(font, img, page, first_ol_ch, base_size, 1); - } else if ((first_cm_ch >= 0) && (outline > 0)) { // 1 x 4 bit monochrome, gl + outline - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_mono_4bit(font, img, page, first_cm_ch, base_size, 1); - } else if (first_gl_ch >= 0) { // 1 x 8 bit monochrome, no outline - outline = 0; - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_mono_8bit(font, img, page, first_gl_ch, base_size, 0); - } else { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, TTR("Unsupported BMFont texture format.")); - } - } - } - page++; - cs = ""; - } else { - cs += c; - } - c = f->get_8(); - } - } break; - case 4: /* chars */ { - int char_count = block_size / 20; - for (int i = 0; i < char_count; i++) { - Vector2 advance; - Vector2 size; - Vector2 offset; - Rect2 uv_rect; - - char32_t idx = f->get_32(); - uv_rect.position.x = (int16_t)f->get_16(); - uv_rect.position.y = (int16_t)f->get_16(); - uv_rect.size.width = (int16_t)f->get_16(); - size.width = uv_rect.size.width; - uv_rect.size.height = (int16_t)f->get_16(); - size.height = uv_rect.size.height; - offset.x = (int16_t)f->get_16(); - offset.y = (int16_t)f->get_16() - ascent; - advance.x = (int16_t)f->get_16(); - if (advance.x < 0) { - advance.x = size.width + 1; - } - - int texture_idx = f->get_8(); - uint8_t channel = f->get_8(); - - ERR_FAIL_COND_V_MSG(!packed && channel != 15, ERR_CANT_CREATE, TTR("Invalid glyph channel.")); - int ch_off = 0; - switch (channel) { - case 1: - ch_off = 2; - break; // B - case 2: - ch_off = 1; - break; // G - case 4: - ch_off = 0; - break; // R - case 8: - ch_off = 3; - break; // A - default: - ch_off = 0; - break; - } - font->set_glyph_advance(0, base_size, idx, advance); - font->set_glyph_offset(0, Vector2i(base_size, 0), idx, offset); - font->set_glyph_size(0, Vector2i(base_size, 0), idx, size); - font->set_glyph_uv_rect(0, Vector2i(base_size, 0), idx, uv_rect); - font->set_glyph_texture_idx(0, Vector2i(base_size, 0), idx, texture_idx * (packed ? 4 : 1) + ch_off); - if (outline > 0) { - font->set_glyph_offset(0, Vector2i(base_size, 1), idx, offset); - font->set_glyph_size(0, Vector2i(base_size, 1), idx, size); - font->set_glyph_uv_rect(0, Vector2i(base_size, 1), idx, uv_rect); - font->set_glyph_texture_idx(0, Vector2i(base_size, 1), idx, texture_idx * (packed ? 4 : 1) + ch_off); - } - } - } break; - case 5: /* kerning */ { - int pair_count = block_size / 10; - for (int i = 0; i < pair_count; i++) { - Vector2i kpk; - kpk.x = f->get_32(); - kpk.y = f->get_32(); - font->set_kerning(0, base_size, kpk, Vector2((int16_t)f->get_16(), 0)); - } - } break; - default: { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, TTR("Invalid BMFont block type.")); - } break; - } - f->seek(off + block_size); - block_type = f->get_8(); - block_size = f->get_32(); - } - - } else { - // Text BMFont file. - f->seek(0); - while (true) { - String line = f->get_line(); - - int delimiter = line.find(" "); - String type = line.substr(0, delimiter); - int pos = delimiter + 1; - Map<String, String> keys; - - while (pos < line.size() && line[pos] == ' ') { - pos++; - } - - while (pos < line.size()) { - int eq = line.find("=", pos); - if (eq == -1) { - break; - } - String key = line.substr(pos, eq - pos); - int end = -1; - String value; - if (line[eq + 1] == '"') { - end = line.find("\"", eq + 2); - if (end == -1) { - break; - } - value = line.substr(eq + 2, end - 1 - eq - 1); - pos = end + 1; - } else { - end = line.find(" ", eq + 1); - if (end == -1) { - end = line.size(); - } - value = line.substr(eq + 1, end - eq); - pos = end; - } - - while (pos < line.size() && line[pos] == ' ') { - pos++; - } - - keys[key] = value; - } - - if (type == "info") { - if (keys.has("size")) { - base_size = keys["size"].to_int(); - font->set_fixed_size(base_size); - } - if (keys.has("outline")) { - outline = keys["outline"].to_int(); - } - ERR_FAIL_COND_V_MSG((!keys.has("unicode") || keys["unicode"].to_int() != 1), ERR_CANT_CREATE, TTR("Non-unicode version of BMFont is not supported.")); - } else if (type == "common") { - if (keys.has("lineHeight")) { - height = keys["lineHeight"].to_int(); - } - if (keys.has("base")) { - ascent = keys["base"].to_int(); - } - if (keys.has("packed")) { - packed = (keys["packed"].to_int() == 1); - } - if (keys.has("alphaChnl")) { - ch[3] = keys["alphaChnl"].to_int(); - } - if (keys.has("redChnl")) { - ch[0] = keys["redChnl"].to_int(); - } - if (keys.has("greenChnl")) { - ch[1] = keys["greenChnl"].to_int(); - } - if (keys.has("blueChnl")) { - ch[2] = keys["blueChnl"].to_int(); - } - for (int i = 0; i < 4; i++) { - if (ch[i] == 0 && first_gl_ch == -1) { - first_gl_ch = i; - } - if (ch[i] == 1 && first_ol_ch == -1) { - first_ol_ch = i; - } - if (ch[i] == 2 && first_cm_ch == -1) { - first_cm_ch = i; - } - } - } else if (type == "page") { - int page = 0; - if (keys.has("id")) { - page = keys["id"].to_int(); - } - if (keys.has("file")) { - String base_dir = p_source_file.get_base_dir(); - String file = base_dir.plus_file(keys["file"]); - if (RenderingServer::get_singleton() != nullptr) { - Ref<Image> img; - img.instantiate(); - Error err = ImageLoader::load_image(file, img); - ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, TTR("Can't load font texture: ") + "\"" + file + "\"."); - if (packed) { - if (ch[3] == 0) { // 4 x 8 bit monochrome, no outline - outline = 0; - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_packed_8bit(font, img, page, base_size); - } else if ((ch[3] == 2) && (outline > 0)) { // 4 x 4 bit monochrome, gl + outline - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_packed_4bit(font, img, page, base_size); - } else { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, TTR("Unsupported BMFont texture format.")); - } - } else { - if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline - outline = 0; - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - font->set_texture_image(0, Vector2i(base_size, 0), page, img); - } else if ((ch[0] == 2) && (ch[1] == 2) && (ch[2] == 2) && (ch[3] == 2) && (outline > 0)) { // RGBA4 color, gl + outline - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_rgba_4bit(font, img, page, base_size); - } else if ((first_gl_ch >= 0) && (first_ol_ch >= 0) && (outline > 0)) { // 1 x 8 bit monochrome, gl + outline - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_mono_8bit(font, img, page, first_gl_ch, base_size, 0); - _convert_mono_8bit(font, img, page, first_ol_ch, base_size, 1); - } else if ((first_cm_ch >= 0) && (outline > 0)) { // 1 x 4 bit monochrome, gl + outline - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_mono_4bit(font, img, page, first_cm_ch, base_size, 1); - } else if (first_gl_ch >= 0) { // 1 x 8 bit monochrome, no outline - outline = 0; - ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, TTR("Unsupported BMFont texture format.")); - _convert_mono_8bit(font, img, page, first_gl_ch, base_size, 0); - } else { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, TTR("Unsupported BMFont texture format.")); - } - } - } - } - } else if (type == "char") { - char32_t idx = 0; - Vector2 advance; - Vector2 size; - Vector2 offset; - Rect2 uv_rect; - int texture_idx = -1; - uint8_t channel = 15; - - if (keys.has("id")) { - idx = keys["id"].to_int(); - } - if (keys.has("x")) { - uv_rect.position.x = keys["x"].to_int(); - } - if (keys.has("y")) { - uv_rect.position.y = keys["y"].to_int(); - } - if (keys.has("width")) { - uv_rect.size.width = keys["width"].to_int(); - size.width = keys["width"].to_int(); - } - if (keys.has("height")) { - uv_rect.size.height = keys["height"].to_int(); - size.height = keys["height"].to_int(); - } - if (keys.has("xoffset")) { - offset.x = keys["xoffset"].to_int(); - } - if (keys.has("yoffset")) { - offset.y = keys["yoffset"].to_int() - ascent; - } - if (keys.has("page")) { - texture_idx = keys["page"].to_int(); - } - if (keys.has("xadvance")) { - advance.x = keys["xadvance"].to_int(); - } - if (advance.x < 0) { - advance.x = size.width + 1; - } - if (keys.has("chnl")) { - channel = keys["chnl"].to_int(); - } - - ERR_FAIL_COND_V_MSG(!packed && channel != 15, ERR_CANT_CREATE, TTR("Invalid glyph channel.")); - int ch_off = 0; - switch (channel) { - case 1: - ch_off = 2; - break; // B - case 2: - ch_off = 1; - break; // G - case 4: - ch_off = 0; - break; // R - case 8: - ch_off = 3; - break; // A - default: - ch_off = 0; - break; - } - font->set_glyph_advance(0, base_size, idx, advance); - font->set_glyph_offset(0, Vector2i(base_size, 0), idx, offset); - font->set_glyph_size(0, Vector2i(base_size, 0), idx, size); - font->set_glyph_uv_rect(0, Vector2i(base_size, 0), idx, uv_rect); - font->set_glyph_texture_idx(0, Vector2i(base_size, 0), idx, texture_idx * (packed ? 4 : 1) + ch_off); - if (outline > 0) { - font->set_glyph_offset(0, Vector2i(base_size, 1), idx, offset); - font->set_glyph_size(0, Vector2i(base_size, 1), idx, size); - font->set_glyph_uv_rect(0, Vector2i(base_size, 1), idx, uv_rect); - font->set_glyph_texture_idx(0, Vector2i(base_size, 1), idx, texture_idx * (packed ? 4 : 1) + ch_off); - } - } else if (type == "kerning") { - Vector2i kpk; - if (keys.has("first")) { - kpk.x = keys["first"].to_int(); - } - if (keys.has("second")) { - kpk.y = keys["second"].to_int(); - } - if (keys.has("amount")) { - font->set_kerning(0, base_size, kpk, Vector2(keys["amount"].to_int(), 0)); - } - } - - if (f->eof_reached()) { - break; - } - } - } - font->set_ascent(0, base_size, ascent); - font->set_descent(0, base_size, height - ascent); + Error err = font->load_bitmap_font(p_source_file); + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load font to file \"" + p_source_file + "\"."); int flg = ResourceSaver::SaverFlags::FLAG_BUNDLE_RESOURCES | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS; if ((bool)p_options["compress"]) { @@ -787,7 +78,7 @@ Error ResourceImporterBMFont::import(const String &p_source_file, const String & } print_verbose("Saving to: " + p_save_path + ".fontdata"); - Error err = ResourceSaver::save(p_save_path + ".fontdata", font, flg); + err = ResourceSaver::save(p_save_path + ".fontdata", font, flg); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save font to file \"" + p_save_path + ".res\"."); print_verbose("Done saving to: " + p_save_path + ".fontdata"); return OK; diff --git a/editor/import/resource_importer_bmfont.h b/editor/import/resource_importer_bmfont.h index 065703132a..e5a96e2c40 100644 --- a/editor/import/resource_importer_bmfont.h +++ b/editor/import/resource_importer_bmfont.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -45,8 +45,8 @@ public: virtual String get_save_extension() const override; virtual String get_resource_type() const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index 07647d8b6a..f0ee14bdcb 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,7 +55,7 @@ String ResourceImporterCSVTranslation::get_resource_type() const { return "Translation"; } -bool ResourceImporterCSVTranslation::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterCSVTranslation::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -67,7 +67,7 @@ String ResourceImporterCSVTranslation::get_preset_name(int p_idx) const { return ""; } -void ResourceImporterCSVTranslation::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterCSVTranslation::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "delimiter", PROPERTY_HINT_ENUM, "Comma,Semicolon,Tab"), 0)); } @@ -99,8 +99,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const Vector<Ref<Translation>> translations; for (int i = 1; i < line.size(); i++) { - String locale = line[i]; - ERR_FAIL_COND_V_MSG(!TranslationServer::is_locale_valid(locale), ERR_PARSE_ERROR, "Error importing CSV translation: '" + locale + "' is not a valid locale."); + String locale = TranslationServer::get_singleton()->standardize_locale(line[i]); locales.push_back(locale); Ref<Translation> translation; @@ -113,7 +112,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const while (line.size() == locales.size() + 1) { String key = line[0]; - if (key != "") { + if (!key.is_empty()) { for (int i = 1; i < line.size(); i++) { translations.write[i - 1]->add_message(key, line[i].c_unescape()); } diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h index d53e91e38b..8f6cf94984 100644 --- a/editor/import/resource_importer_csv_translation.h +++ b/editor/import/resource_importer_csv_translation.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,8 +46,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_dynamicfont.cpp b/editor/import/resource_importer_dynamicfont.cpp index 8e01adbd56..11f563a982 100644 --- a/editor/import/resource_importer_dynamicfont.cpp +++ b/editor/import/resource_importer_dynamicfont.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,12 +30,12 @@ #include "resource_importer_dynamicfont.h" -#include "dynamicfont_import_settings.h" - #include "core/io/file_access.h" #include "core/io/resource_saver.h" +#include "dynamicfont_import_settings.h" #include "editor/editor_node.h" -#include "modules/modules_enabled.gen.h" + +#include "modules/modules_enabled.gen.h" // For freetype. String ResourceImporterDynamicFont::get_importer_name() const { return "font_data_dynamic"; @@ -66,7 +66,7 @@ String ResourceImporterDynamicFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterDynamicFont::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option == "msdf_pixel_range" && !bool(p_options["multichannel_signed_distance_field"])) { return false; } @@ -94,7 +94,7 @@ String ResourceImporterDynamicFont::get_preset_name(int p_idx) const { } } -void ResourceImporterDynamicFont::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { bool msdf = p_preset == PRESET_MSDF; r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); @@ -107,6 +107,7 @@ void ResourceImporterDynamicFont::get_import_options(List<ImportOption> *r_optio r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "opentype_feature_overrides"), Dictionary())); r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "preload/char_ranges"), Vector<String>())); r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "preload/glyph_ranges"), Vector<String>())); @@ -174,6 +175,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str bool msdf = p_options["multichannel_signed_distance_field"]; int px_range = p_options["msdf_pixel_range"]; int px_size = p_options["msdf_size"]; + Dictionary ot_ov = p_options["opentype_feature_overrides"]; bool autohinter = p_options["force_autohinter"]; int hinting = p_options["hinting"]; @@ -190,6 +192,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str font->set_multichannel_signed_distance_field(msdf); font->set_msdf_pixel_range(px_range); font->set_msdf_size(px_size); + font->set_opentype_feature_overrides(ot_ov); font->set_fixed_size(0); font->set_force_autohinter(autohinter); font->set_hinting((TextServer::Hinting)hinting); diff --git a/editor/import/resource_importer_dynamicfont.h b/editor/import/resource_importer_dynamicfont.h index 52f256ab96..a55d639e10 100644 --- a/editor/import/resource_importer_dynamicfont.h +++ b/editor/import/resource_importer_dynamicfont.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,8 +57,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; bool has_advanced_options() const override; void show_advanced_options(const String &p_path) override; diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp index 2dea359188..e6a822d827 100644 --- a/editor/import/resource_importer_image.cpp +++ b/editor/import/resource_importer_image.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,7 +55,7 @@ String ResourceImporterImage::get_resource_type() const { return "Image"; } -bool ResourceImporterImage::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterImage::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -67,7 +67,7 @@ String ResourceImporterImage::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterImage::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterImage::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { } Error ResourceImporterImage::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { diff --git a/editor/import/resource_importer_image.h b/editor/import/resource_importer_image.h index 7c8d5e228e..81aedc91e8 100644 --- a/editor/import/resource_importer_image.h +++ b/editor/import/resource_importer_image.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,8 +47,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index 997280d1dd..0a15284ef5 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -55,11 +55,11 @@ String ResourceImporterImageFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterImageFont::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterImageFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } -void ResourceImporterImageFont::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterImageFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "character_ranges"), Vector<String>())); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "columns"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rows"), 1)); diff --git a/editor/import/resource_importer_imagefont.h b/editor/import/resource_importer_imagefont.h index 9b2b38596f..c1116d5a83 100644 --- a/editor/import/resource_importer_imagefont.h +++ b/editor/import/resource_importer_imagefont.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,8 +47,8 @@ public: virtual String get_save_extension() const override; virtual String get_resource_type() const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index d5bb21443c..7ca61e83e7 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -118,7 +118,7 @@ String ResourceImporterLayeredTexture::get_resource_type() const { ERR_FAIL_V(String()); } -bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option == "compress/lossy_quality" && p_options.has("compress/mode")) { return int(p_options["compress/mode"]) == COMPRESS_LOSSY; } @@ -133,7 +133,7 @@ String ResourceImporterLayeredTexture::get_preset_name(int p_idx) const { return ""; } -void ResourceImporterLayeredTexture::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterLayeredTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless (PNG),Lossy (WebP),Video RAM (S3TC/ETC/BPTC),Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_compression", PROPERTY_HINT_ENUM, "Disabled,Opaque Only,Always"), 1)); @@ -392,7 +392,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const bool can_s3tc = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_s3tc"); if (can_bptc) { - formats_imported.push_back("bptc"); //needs to be aded anyway + formats_imported.push_back("bptc"); // Needs to be added anyway. } bool can_compress_hdr = hdr_compression > 0; @@ -450,12 +450,6 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const formats_imported.push_back("etc2"); } - if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc")) { - _save_tex(slices, p_save_path + ".etc2." + extension, compress_mode, lossy, Image::COMPRESS_ETC2, csource, used_channels, mipmaps, true); - r_platform_variants->push_back("pvrtc"); - formats_imported.push_back("pvrtc"); - } - if (!ok_on_pc) { EditorNode::add_io_error("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC."); } @@ -481,7 +475,6 @@ const char *ResourceImporterLayeredTexture::compression_formats[] = { "s3tc", "etc", "etc2", - "pvrtc", nullptr }; String ResourceImporterLayeredTexture::get_import_settings_string() const { diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 86e9c5bde8..ee8e7dc615 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -84,15 +84,13 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; void _save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2); virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - void update_imports(); - virtual bool are_import_settings_valid(const String &p_path) const override; virtual String get_import_settings_string() const override; diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 34bc0a7d8d..96645665aa 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,10 +32,10 @@ #include "core/io/file_access.h" #include "core/io/resource_saver.h" -#include "editor/import/scene_importer_mesh.h" -#include "editor/import/scene_importer_mesh_node_3d.h" +#include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/node_3d.h" +#include "scene/resources/importer_mesh.h" #include "scene/resources/mesh.h" #include "scene/resources/surface_tool.h" @@ -235,7 +235,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ while (l.length() && l[l.length() - 1] == '\\') { String add = f->get_line().strip_edges(); l += add; - if (add == String()) { + if (add.is_empty()) { break; } } @@ -301,7 +301,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ surf_tool->set_normal(normals[norm]); } - if (face[idx].size() >= 2 && face[idx][1] != String()) { + if (face[idx].size() >= 2 && !face[idx][1].is_empty()) { int uv = face[idx][1].to_int() - 1; if (uv < 0) { uv += uvs.size() + 1; @@ -363,9 +363,9 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ mesh = surf_tool->commit(mesh, mesh_flags); - if (current_material != String()) { + if (!current_material.is_empty()) { mesh->surface_set_name(mesh->get_surface_count() - 1, current_material.get_basename()); - } else if (current_group != String()) { + } else if (!current_group.is_empty()) { mesh->surface_set_name(mesh->get_surface_count() - 1, current_group); } @@ -405,11 +405,11 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ current_material_library = l.replace("mtllib", "").strip_edges(); if (!material_map.has(current_material_library)) { Map<String, Ref<StandardMaterial3D>> lib; - Error err = _parse_material_library(current_material_library, lib, r_missing_deps); - if (err == ERR_CANT_OPEN) { - String dir = p_path.get_base_dir(); - err = _parse_material_library(dir.plus_file(current_material_library), lib, r_missing_deps); + String lib_path = current_material_library; + if (lib_path.is_relative_path()) { + lib_path = p_path.get_base_dir().plus_file(current_material_library); } + Error err = _parse_material_library(lib_path, lib, r_missing_deps); if (err == OK) { material_map[current_material_library] = lib; } @@ -424,7 +424,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ return OK; } -Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { List<Ref<Mesh>> meshes; Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, false, Vector3(1, 1, 1), Vector3(0, 0, 0), r_missing_deps); @@ -439,16 +439,16 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in Node3D *scene = memnew(Node3D); for (const Ref<Mesh> &m : meshes) { - Ref<EditorSceneImporterMesh> mesh; + Ref<ImporterMesh> mesh; mesh.instantiate(); for (int i = 0; i < m->get_surface_count(); i++) { mesh->add_surface(m->surface_get_primitive_type(i), m->surface_get_arrays(i), Array(), Dictionary(), m->surface_get_material(i)); } - EditorSceneImporterMeshNode3D *mi = memnew(EditorSceneImporterMeshNode3D); + ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D); mi->set_mesh(mesh); mi->set_name(m->get_name()); - scene->add_child(mi); + scene->add_child(mi, true); mi->set_owner(scene); } @@ -459,7 +459,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in return scene; } -Ref<Animation> EditorOBJImporter::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref<Animation> EditorOBJImporter::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { return Ref<Animation>(); } @@ -504,14 +504,14 @@ String ResourceImporterOBJ::get_preset_name(int p_idx) const { return ""; } -void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterOBJ::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_tangents"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "scale_mesh"), Vector3(1, 1, 1))); r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "offset_mesh"), Vector3(0, 0, 0))); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "optimize_mesh"), true)); } -bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterOBJ::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index 414e0c1fe6..d7e3f0209d 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,14 +33,14 @@ #include "resource_importer_scene.h" -class EditorOBJImporter : public EditorSceneImporter { - GDCLASS(EditorOBJImporter, EditorSceneImporter); +class EditorOBJImporter : public EditorSceneFormatImporter { + GDCLASS(EditorOBJImporter, EditorSceneFormatImporter); public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; + virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override; EditorOBJImporter(); }; @@ -59,11 +59,14 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; + // Threaded import can currently cause deadlocks, see GH-48265. + virtual bool can_import_threaded() const override { return false; } + ResourceImporterOBJ(); }; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 9f617be4ee..af9a2f9ebe 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,13 +30,13 @@ #include "resource_importer_scene.h" +#include "core/error/error_macros.h" #include "core/io/resource_saver.h" #include "editor/editor_node.h" -#include "editor/import/editor_importer_bake_reset.h" #include "editor/import/scene_import_settings.h" -#include "editor/import/scene_importer_mesh_node_3d.h" #include "scene/3d/area_3d.h" #include "scene/3d/collision_shape_3d.h" +#include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/navigation_region_3d.h" #include "scene/3d/physics_body_3d.h" @@ -44,14 +44,15 @@ #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" #include "scene/resources/box_shape_3d.h" +#include "scene/resources/importer_mesh.h" #include "scene/resources/packed_scene.h" #include "scene/resources/resource_format_text.h" #include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" -#include "scene/resources/world_margin_shape_3d.h" +#include "scene/resources/world_boundary_shape_3d.h" -uint32_t EditorSceneImporter::get_import_flags() const { +uint32_t EditorSceneFormatImporter::get_import_flags() const { int ret; if (GDVIRTUAL_CALL(_get_import_flags, ret)) { return ret; @@ -60,7 +61,7 @@ uint32_t EditorSceneImporter::get_import_flags() const { ERR_FAIL_V(0); } -void EditorSceneImporter::get_extensions(List<String> *r_extensions) const { +void EditorSceneFormatImporter::get_extensions(List<String> *r_extensions) const { Vector<String> arr; if (GDVIRTUAL_CALL(_get_extensions, arr)) { for (int i = 0; i < arr.size(); i++) { @@ -72,43 +73,49 @@ void EditorSceneImporter::get_extensions(List<String> *r_extensions) const { ERR_FAIL(); } -Node *EditorSceneImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { - Object *ret; - if (GDVIRTUAL_CALL(_import_scene, p_path, p_flags, p_bake_fps, ret)) { +Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { + Dictionary options_dict; + for (const KeyValue<StringName, Variant> &elem : p_options) { + options_dict[elem.key] = elem.value; + } + Object *ret = nullptr; + if (GDVIRTUAL_CALL(_import_scene, p_path, p_flags, options_dict, p_bake_fps, ret)) { return Object::cast_to<Node>(ret); } ERR_FAIL_V(nullptr); } -Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref<Animation> EditorSceneFormatImporter::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { + Dictionary options_dict; + for (const KeyValue<StringName, Variant> &elem : p_options) { + options_dict[elem.key] = elem.value; + } Ref<Animation> ret; - if (GDVIRTUAL_CALL(_import_animation, p_path, p_flags, p_bake_fps, ret)) { + if (GDVIRTUAL_CALL(_import_animation, p_path, p_flags, options_dict, p_bake_fps, ret)) { return ret; } ERR_FAIL_V(nullptr); } -//for documenters, these functions are useful when an importer calls an external conversion helper (like, fbx2gltf), -//and you want to load the resulting file - -Node *EditorSceneImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { - return ResourceImporterScene::get_singleton()->import_scene_from_other_importer(this, p_path, p_flags, p_bake_fps); +void EditorSceneFormatImporter::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) { + GDVIRTUAL_CALL(_get_import_options, p_path); } -Ref<Animation> EditorSceneImporter::import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) { - return ResourceImporterScene::get_singleton()->import_animation_from_other_importer(this, p_path, p_flags, p_bake_fps); +Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) { + Variant ret; + GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret); + return ret; } -void EditorSceneImporter::_bind_methods() { - ClassDB::bind_method(D_METHOD("import_scene_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_scene_from_other_importer); - ClassDB::bind_method(D_METHOD("import_animation_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_animation_from_other_importer); - +void EditorSceneFormatImporter::_bind_methods() { GDVIRTUAL_BIND(_get_import_flags); GDVIRTUAL_BIND(_get_extensions); - GDVIRTUAL_BIND(_import_scene, "path", "flags", "bake_fps"); - GDVIRTUAL_BIND(_import_animation, "path", "flags", "bake_fps"); + GDVIRTUAL_BIND(_import_scene, "path", "flags", "options", "bake_fps"); + GDVIRTUAL_BIND(_import_animation, "path", "flags", "options", "bake_fps"); + GDVIRTUAL_BIND(_get_import_options, "path"); + GDVIRTUAL_BIND(_get_option_visibility, "path", "option"); BIND_CONSTANT(IMPORT_SCENE); BIND_CONSTANT(IMPORT_ANIMATION); @@ -143,6 +150,105 @@ void EditorScenePostImport::init(const String &p_source_file) { EditorScenePostImport::EditorScenePostImport() { } +/////////////////////////////////////////////////////// + +Variant EditorScenePostImportPlugin::get_option_value(const StringName &p_name) const { + ERR_FAIL_COND_V_MSG(current_options == nullptr && current_options_dict == nullptr, Variant(), "get_option_value called from a function where option values are not available."); + ERR_FAIL_COND_V_MSG(current_options && !current_options->has(p_name), Variant(), "get_option_value called with unexisting option argument: " + String(p_name)); + ERR_FAIL_COND_V_MSG(current_options_dict && !current_options_dict->has(p_name), Variant(), "get_option_value called with unexisting option argument: " + String(p_name)); + if (current_options) { + (*current_options)[p_name]; + } + if (current_options_dict) { + (*current_options_dict)[p_name]; + } + return Variant(); +} +void EditorScenePostImportPlugin::add_import_option(const String &p_name, Variant p_default_value) { + ERR_FAIL_COND_MSG(current_option_list == nullptr, "add_import_option() can only be called from get_import_options()"); + add_import_option_advanced(p_default_value.get_type(), p_name, p_default_value); +} +void EditorScenePostImportPlugin::add_import_option_advanced(Variant::Type p_type, const String &p_name, Variant p_default_value, PropertyHint p_hint, const String &p_hint_string, int p_usage_flags) { + ERR_FAIL_COND_MSG(current_option_list == nullptr, "add_import_option_advanced() can only be called from get_import_options()"); + current_option_list->push_back(ResourceImporter::ImportOption(PropertyInfo(p_type, p_name, p_hint, p_hint_string, p_usage_flags), p_default_value)); +} + +void EditorScenePostImportPlugin::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) { + current_option_list = r_options; + GDVIRTUAL_CALL(_get_internal_import_options, p_category); + current_option_list = nullptr; +} +Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { + current_options = &p_options; + Variant ret; + GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_option, ret); + current_options = nullptr; + return ret; +} +Variant EditorScenePostImportPlugin::get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { + current_options = &p_options; + Variant ret; + GDVIRTUAL_CALL(_get_internal_option_update_view_required, p_category, p_option, ret); + current_options = nullptr; + return ret; +} + +void EditorScenePostImportPlugin::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, RES p_resource, const Dictionary &p_options) { + current_options_dict = &p_options; + GDVIRTUAL_CALL(_internal_process, p_category, p_base_scene, p_node, p_resource); + current_options_dict = nullptr; +} + +void EditorScenePostImportPlugin::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) { + current_option_list = r_options; + GDVIRTUAL_CALL(_get_import_options, p_path); + current_option_list = nullptr; +} +Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { + current_options = &p_options; + Variant ret; + GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret); + current_options = nullptr; + return ret; +} + +void EditorScenePostImportPlugin::pre_process(Node *p_scene, const Map<StringName, Variant> &p_options) { + current_options = &p_options; + GDVIRTUAL_CALL(_pre_process, p_scene); + current_options = nullptr; +} +void EditorScenePostImportPlugin::post_process(Node *p_scene, const Map<StringName, Variant> &p_options) { + current_options = &p_options; + GDVIRTUAL_CALL(_post_process, p_scene); + current_options = nullptr; +} + +void EditorScenePostImportPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_option_value", "name"), &EditorScenePostImportPlugin::get_option_value); + + ClassDB::bind_method(D_METHOD("add_import_option", "name", "value"), &EditorScenePostImportPlugin::add_import_option); + ClassDB::bind_method(D_METHOD("add_import_option_advanced", "type", "name", "default_value", "hint", "hint_string", "usage_flags"), &EditorScenePostImportPlugin::add_import_option_advanced, DEFVAL(PROPERTY_HINT_NONE), DEFVAL(""), DEFVAL(PROPERTY_USAGE_DEFAULT)); + + GDVIRTUAL_BIND(_get_internal_import_options, "category"); + GDVIRTUAL_BIND(_get_internal_option_visibility, "category", "option"); + GDVIRTUAL_BIND(_get_internal_option_update_view_required, "category", "option"); + GDVIRTUAL_BIND(_internal_process, "category", "base_node", "node", "resource"); + GDVIRTUAL_BIND(_get_import_options, "path"); + GDVIRTUAL_BIND(_get_option_visibility, "path", "option"); + GDVIRTUAL_BIND(_pre_process, "scene"); + GDVIRTUAL_BIND(_post_process, "scene"); + + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_NODE); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MESH); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MATERIAL); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_ANIMATION); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE); + BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MAX); +} + +///////////////////////////////////////////////////////// + String ResourceImporterScene::get_importer_name() const { return "scene"; } @@ -152,7 +258,7 @@ String ResourceImporterScene::get_visible_name() const { } void ResourceImporterScene::get_recognized_extensions(List<String> *p_extensions) const { - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneFormatImporter>>::Element *E = importers.front(); E; E = E->next()) { E->get()->get_extensions(p_extensions); } } @@ -169,7 +275,7 @@ int ResourceImporterScene::get_format_version() const { return 1; } -bool ResourceImporterScene::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterScene::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option.begins_with("animation/")) { if (p_option != "animation/import" && !bool(p_options["animation/import"])) { return false; @@ -180,6 +286,20 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const return false; } + for (int i = 0; i < post_importer_plugins.size(); i++) { + Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_path, p_option, p_options); + if (ret.get_type() == Variant::BOOL) { + return ret; + } + } + + for (Ref<EditorSceneFormatImporter> importer : importers) { + Variant ret = importer->get_option_visibility(p_path, p_option, p_options); + if (ret.get_type() == Variant::BOOL) { + return ret; + } + } + return true; } @@ -233,8 +353,9 @@ static String _fixstr(const String &p_what, const String &p_str) { return what; } -static void _pre_gen_shape_list(Ref<EditorSceneImporterMesh> &mesh, Vector<Ref<Shape3D>> &r_shape_list, bool p_convex) { +static void _pre_gen_shape_list(Ref<ImporterMesh> &mesh, Vector<Ref<Shape3D>> &r_shape_list, bool p_convex) { ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value"); + ERR_FAIL_NULL_MSG(mesh->get_mesh(), "Cannot generate shape list with null mesh value"); if (!p_convex) { Ref<Shape3D> shape = mesh->create_trimesh_shape(); r_shape_list.push_back(shape); @@ -249,16 +370,17 @@ static void _pre_gen_shape_list(Ref<EditorSceneImporterMesh> &mesh, Vector<Ref<S } } -Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map) { - // children first +Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, List<Pair<NodePath, Node *>> &r_node_renames) { + // Children first. for (int i = 0; i < p_node->get_child_count(); i++) { - Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map); + Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map, r_node_renames); if (!r) { - i--; //was erased + i--; // Was erased. } } String name = p_node->get_name(); + NodePath original_path = p_root->get_path_to(p_node); // Used to detect renames due to import hints. bool isroot = p_node == p_root; @@ -267,10 +389,10 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E return nullptr; } - if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + if (Object::cast_to<ImporterMeshInstance3D>(p_node)) { + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); - Ref<EditorSceneImporterMesh> m = mi->get_mesh(); + Ref<ImporterMesh> m = mi->get_mesh(); if (m.is_valid()) { for (int i = 0; i < m->get_surface_count(); i++) { @@ -293,14 +415,21 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E } if (Object::cast_to<AnimationPlayer>(p_node)) { - //remove animations referencing non-importable nodes AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node); + // Node paths in animation tracks are relative to the following path (this is used to fix node paths below). + Node *ap_root = ap->get_node(ap->get_root()); + NodePath path_prefix = p_root->get_path_to(ap_root); + + bool nodes_were_renamed = r_node_renames.size() != 0; + List<StringName> anims; ap->get_animation_list(&anims); for (const StringName &E : anims) { Ref<Animation> anim = ap->get_animation(E); ERR_CONTINUE(anim.is_null()); + + // Remove animation tracks referencing non-importable nodes. for (int i = 0; i < anim->get_track_count(); i++) { NodePath path = anim->track_get_path(i); @@ -314,12 +443,33 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E } } + // Fix node paths in animations, in case nodes were renamed earlier due to import hints. + if (nodes_were_renamed) { + for (int i = 0; i < anim->get_track_count(); i++) { + NodePath path = anim->track_get_path(i); + // Convert track path to absolute node path without subnames (some manual work because we are not in the scene tree). + Vector<StringName> absolute_path_names = path_prefix.get_names(); + absolute_path_names.append_array(path.get_names()); + NodePath absolute_path(absolute_path_names, false); + absolute_path.simplify(); + // Fix paths to renamed nodes. + for (const Pair<NodePath, Node *> &F : r_node_renames) { + if (F.first == absolute_path) { + NodePath new_path(ap_root->get_path_to(F.second).get_names(), path.get_subnames(), false); + print_verbose(vformat("Fix: Correcting node path in animation track: %s should be %s", path, new_path)); + anim->track_set_path(i, new_path); + break; // Only one match is possible. + } + } + } + } + String animname = E; const int loop_string_count = 3; - static const char *loop_strings[loop_string_count] = { "loops", "loop", "cycle" }; + static const char *loop_strings[loop_string_count] = { "loop_mode", "loop", "cycle" }; for (int i = 0; i < loop_string_count; i++) { if (_teststr(animname, loop_strings[i])) { - anim->set_loop(true); + anim->set_loop_mode(Animation::LoopMode::LOOP_LINEAR); animname = _fixstr(animname, loop_strings[i]); ap->rename_animation(E, animname); } @@ -331,13 +481,22 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E if (isroot) { return p_node; } - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + + String fixed_name; + if (_teststr(name, "colonly")) { + fixed_name = _fixstr(name, "colonly"); + } else if (_teststr(name, "convcolonly")) { + fixed_name = _fixstr(name, "convcolonly"); + } + + ERR_FAIL_COND_V(fixed_name.is_empty(), nullptr); + + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); if (mi) { - Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); + Ref<ImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { Vector<Ref<Shape3D>> shapes; - String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(name, "colonly")) { @@ -348,14 +507,6 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E collision_map[mesh] = shapes; } - if (_teststr(name, "colonly")) { - fixed_name = _fixstr(name, "colonly"); - } else if (_teststr(name, "convcolonly")) { - fixed_name = _fixstr(name, "convcolonly"); - } - - ERR_FAIL_COND_V(fixed_name == String(), nullptr); - if (shapes.size()) { StaticBody3D *col = memnew(StaticBody3D); col->set_transform(mi->get_transform()); @@ -371,11 +522,11 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E } else if (p_node->has_meta("empty_draw_type")) { String empty_draw_type = String(p_node->get_meta("empty_draw_type")); StaticBody3D *sb = memnew(StaticBody3D); - sb->set_name(_fixstr(name, "colonly")); + sb->set_name(fixed_name); Object::cast_to<Node3D>(sb)->set_transform(Object::cast_to<Node3D>(p_node)->get_transform()); p_node->replace_by(sb); memdelete(p_node); - p_node = nullptr; + p_node = sb; CollisionShape3D *colshape = memnew(CollisionShape3D); if (empty_draw_type == "CUBE") { BoxShape3D *boxShape = memnew(BoxShape3D); @@ -387,24 +538,24 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E colshape->set_shape(rayShape); Object::cast_to<Node3D>(sb)->rotate_x(Math_PI / 2); } else if (empty_draw_type == "IMAGE") { - WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D); - colshape->set_shape(world_margin_shape); + WorldBoundaryShape3D *world_boundary_shape = memnew(WorldBoundaryShape3D); + colshape->set_shape(world_boundary_shape); } else { SphereShape3D *sphereShape = memnew(SphereShape3D); sphereShape->set_radius(1); colshape->set_shape(sphereShape); } - sb->add_child(colshape); + sb->add_child(colshape, true); colshape->set_owner(sb->get_owner()); } - } else if (_teststr(name, "rigid") && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { + } else if (_teststr(name, "rigid") && Object::cast_to<ImporterMeshInstance3D>(p_node)) { if (isroot) { return p_node; } - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); - Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); + Ref<ImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { Vector<Ref<Shape3D>> shapes; @@ -414,22 +565,22 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E _pre_gen_shape_list(mesh, shapes, true); } - RigidBody3D *rigid_body = memnew(RigidBody3D); - rigid_body->set_name(_fixstr(name, "rigid")); + RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); + rigid_body->set_name(_fixstr(name, "rigid_body")); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); p_node = rigid_body; mi->set_transform(Transform3D()); - rigid_body->add_child(mi); + rigid_body->add_child(mi, true); mi->set_owner(rigid_body->get_owner()); _add_shapes(rigid_body, shapes); } - } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<ImporterMeshInstance3D>(p_node)) { + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); - Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); + Ref<ImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { Vector<Ref<Shape3D>> shapes; @@ -450,7 +601,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E fixed_name = _fixstr(name, "convcol"); } - if (fixed_name != String()) { + if (!fixed_name.is_empty()) { if (mi->get_parent() && !mi->get_parent()->has_node(fixed_name)) { mi->set_name(fixed_name); } @@ -458,21 +609,21 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E if (shapes.size()) { StaticBody3D *col = memnew(StaticBody3D); - mi->add_child(col); + mi->add_child(col, true); col->set_owner(mi->get_owner()); _add_shapes(col, shapes); } } - } else if (_teststr(name, "navmesh") && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { + } else if (_teststr(name, "navmesh") && Object::cast_to<ImporterMeshInstance3D>(p_node)) { if (isroot) { return p_node; } - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); - Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); + Ref<ImporterMesh> mesh = mi->get_mesh(); ERR_FAIL_COND_V(mesh.is_null(), nullptr); NavigationRegion3D *nmi = memnew(NavigationRegion3D); @@ -484,12 +635,12 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E memdelete(p_node); p_node = nmi; - } else if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { + } else if (Object::cast_to<ImporterMeshInstance3D>(p_node)) { //last attempt, maybe collision inside the mesh data - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); - Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); + Ref<ImporterMesh> mesh = mi->get_mesh(); if (!mesh.is_null()) { Vector<Ref<Shape3D>> shapes; if (collision_map.has(mesh)) { @@ -506,7 +657,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E if (shapes.size()) { StaticBody3D *col = memnew(StaticBody3D); - p_node->add_child(col); + p_node->add_child(col, true); col->set_owner(p_node->get_owner()); _add_shapes(col, shapes); @@ -514,10 +665,18 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E } } + if (p_node) { + NodePath new_path = p_root->get_path_to(p_node); + if (new_path != original_path) { + print_verbose(vformat("Fix: Renamed %s to %s", original_path, new_path)); + r_node_renames.push_back({ original_path, p_node }); + } + } + return p_node; } -Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { +Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps); @@ -546,10 +705,30 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< return nullptr; } - if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + { + ObjectID node_id = p_node->get_instance_id(); + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_NODE, p_root, p_node, RES(), node_settings); + if (ObjectDB::get_instance(node_id) == nullptr) { //may have been erased, so do not continue + break; + } + } + } + + if (Object::cast_to<ImporterMeshInstance3D>(p_node)) { + ObjectID node_id = p_node->get_instance_id(); + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, p_root, p_node, RES(), node_settings); + if (ObjectDB::get_instance(node_id) == nullptr) { //may have been erased, so do not continue + break; + } + } + } + + if (Object::cast_to<ImporterMeshInstance3D>(p_node)) { + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); - Ref<EditorSceneImporterMesh> m = mi->get_mesh(); + Ref<ImporterMesh> m = mi->get_mesh(); if (m.is_valid()) { if (!r_scanned_meshes.has(m)) { @@ -563,8 +742,13 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< mat_id = mat->get_name(); } - if (mat_id != String() && p_material_data.has(mat_id)) { + if (!mat_id.is_empty() && p_material_data.has(mat_id)) { Dictionary matdata = p_material_data[mat_id]; + + for (int j = 0; j < post_importer_plugins.size(); j++) { + post_importer_plugins.write[j]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MATERIAL, p_root, p_node, mat, matdata); + } + if (matdata.has("use_external/enabled") && bool(matdata["use_external/enabled"]) && matdata.has("use_external/path")) { String path = matdata["use_external/path"]; Ref<Material> external_mat = ResourceLoader::load(path); @@ -616,19 +800,19 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< switch (mesh_physics_mode) { case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: { StaticBody3D *col = memnew(StaticBody3D); - p_node->add_child(col); + p_node->add_child(col, true); col->set_owner(p_node->get_owner()); col->set_transform(get_collision_shapes_transform(node_settings)); base = col; } break; case MESH_PHYSICS_RIGID_BODY_AND_MESH: { - RigidBody3D *rigid_body = memnew(RigidBody3D); + RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); rigid_body->set_name(p_node->get_name()); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); p_node = rigid_body; mi->set_transform(Transform3D()); - rigid_body->add_child(mi); + rigid_body->add_child(mi, true); mi->set_owner(rigid_body->get_owner()); base = rigid_body; } break; @@ -657,7 +841,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< for (const Ref<Shape3D> &E : shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E); - base->add_child(cshape); + base->add_child(cshape, true); cshape->set_owner(base->get_owner()); idx++; @@ -669,10 +853,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } //navmesh (node may have changed type above) - if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { - EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + if (Object::cast_to<ImporterMeshInstance3D>(p_node)) { + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node); - Ref<EditorSceneImporterMesh> m = mi->get_mesh(); + Ref<ImporterMesh> m = mi->get_mesh(); if (m.is_valid()) { if (node_settings.has("generate/navmesh")) { @@ -690,7 +874,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< memdelete(p_node); p_node = nmi; } else { - mi->add_child(nmi); + mi->add_child(nmi, true); nmi->set_owner(mi->get_owner()); } } @@ -714,6 +898,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } } + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, p_root, p_node, RES(), node_settings); + } + bool use_optimizer = node_settings["optimizer/enabled"]; float anim_optimizer_linerr = node_settings["optimizer/max_linear_error"]; float anim_optimizer_angerr = node_settings["optimizer/max_angular_error"]; @@ -731,7 +919,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< String name = node_settings["clip_" + itos(i + 1) + "/name"]; int from_frame = node_settings["clip_" + itos(i + 1) + "/start_frame"]; int end_frame = node_settings["clip_" + itos(i + 1) + "/end_frame"]; - bool loop = node_settings["clip_" + itos(i + 1) + "/loops"]; + Animation::LoopMode loop_mode = static_cast<Animation::LoopMode>((int)node_settings["clip_" + itos(i + 1) + "/loop_mode"]); bool save_to_file = node_settings["clip_" + itos(i + 1) + "/save_to_file/enabled"]; bool save_to_path = node_settings["clip_" + itos(i + 1) + "/save_to_file/path"]; bool save_to_file_keep_custom = node_settings["clip_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"]; @@ -739,7 +927,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< animation_clips.push_back(name); animation_clips.push_back(from_frame / p_animation_fps); animation_clips.push_back(end_frame / p_animation_fps); - animation_clips.push_back(loop); + animation_clips.push_back(loop_mode); animation_clips.push_back(save_to_file); animation_clips.push_back(save_to_path); animation_clips.push_back(save_to_file_keep_custom); @@ -766,7 +954,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } } - anim->set_loop(anim_settings["settings/loops"]); + anim->set_loop_mode(static_cast<Animation::LoopMode>((int)anim_settings["settings/loop_mode"])); bool save = anim_settings["save_to_file/enabled"]; String path = anim_settings["save_to_file/path"]; bool keep_custom = anim_settings["save_to_file/keep_custom_tracks"]; @@ -778,6 +966,48 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } } } + + AnimationImportTracks import_tracks_mode[TRACK_CHANNEL_MAX] = { + AnimationImportTracks(int(node_settings["import_tracks/position"])), + AnimationImportTracks(int(node_settings["import_tracks/rotation"])), + AnimationImportTracks(int(node_settings["import_tracks/scale"])) + }; + + if (anims.size() > 1 && (import_tracks_mode[0] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[1] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[2] != ANIMATION_IMPORT_TRACKS_IF_PRESENT)) { + _optimize_track_usage(ap, import_tracks_mode); + } + } + + if (post_importer_plugins.size()) { + List<StringName> anims; + ap->get_animation_list(&anims); + for (const StringName &name : anims) { + if (p_animation_data.has(name)) { + Ref<Animation> anim = ap->get_animation(name); + Dictionary anim_settings = p_animation_data[name]; + { + //fill with default values + List<ImportOption> iopts; + get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts); + for (const ImportOption &F : iopts) { + if (!anim_settings.has(F.option.name)) { + anim_settings[F.option.name] = F.default_value; + } + } + } + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION, p_root, p_node, anim, node_settings); + } + } + } + } + + bool use_compression = node_settings["compression/enabled"]; + int anim_compression_page_size = node_settings["compression/page_size"]; + + if (use_compression) { + _compress_animations(ap, anim_compression_page_size); } } @@ -798,7 +1028,7 @@ Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> ani old_anim->copy_track(i, anim); } } - anim->set_loop(old_anim->has_loop()); + anim->set_loop_mode(old_anim->get_loop_mode()); } } @@ -817,6 +1047,7 @@ Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> ani void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all) { if (!anim->has_animation("default")) { + ERR_FAIL_COND_MSG(p_clips.size() > 0, "To create clips, animations must be named \"default\"."); return; } @@ -826,7 +1057,7 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ String name = p_clips[i]; float from = p_clips[i + 1]; float to = p_clips[i + 2]; - bool loop = p_clips[i + 3]; + Animation::LoopMode loop_mode = static_cast<Animation::LoopMode>((int)p_clips[i + 3]); bool save_to_file = p_clips[i + 4]; String save_to_path = p_clips[i + 5]; bool keep_current = p_clips[i + 6]; @@ -850,44 +1081,71 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ new_anim->track_set_path(dtrack, default_anim->track_get_path(j)); if (kt > (from + 0.01) && k > 0) { - if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) { - Quaternion q; + if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) { Vector3 p; + default_anim->position_track_interpolate(j, from, &p); + new_anim->position_track_insert_key(dtrack, 0, p); + } else if (default_anim->track_get_type(j) == Animation::TYPE_ROTATION_3D) { + Quaternion r; + default_anim->rotation_track_interpolate(j, from, &r); + new_anim->rotation_track_insert_key(dtrack, 0, r); + } else if (default_anim->track_get_type(j) == Animation::TYPE_SCALE_3D) { Vector3 s; - default_anim->transform_track_interpolate(j, from, &p, &q, &s); - new_anim->transform_track_insert_key(dtrack, 0, p, q, s); - } - if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) { + default_anim->scale_track_interpolate(j, from, &s); + new_anim->scale_track_insert_key(dtrack, 0, s); + } else if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) { Variant var = default_anim->value_track_interpolate(j, from); new_anim->track_insert_key(dtrack, 0, var); + } else if (default_anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) { + float interp; + default_anim->blend_shape_track_interpolate(j, from, &interp); + new_anim->blend_shape_track_insert_key(dtrack, 0, interp); } } } - if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) { - Quaternion q; + if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) { Vector3 p; + default_anim->position_track_get_key(j, k, &p); + new_anim->position_track_insert_key(dtrack, kt - from, p); + } else if (default_anim->track_get_type(j) == Animation::TYPE_ROTATION_3D) { + Quaternion r; + default_anim->rotation_track_get_key(j, k, &r); + new_anim->rotation_track_insert_key(dtrack, kt - from, r); + } else if (default_anim->track_get_type(j) == Animation::TYPE_SCALE_3D) { Vector3 s; - default_anim->transform_track_get_key(j, k, &p, &q, &s); - new_anim->transform_track_insert_key(dtrack, kt - from, p, q, s); - } - if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) { + default_anim->scale_track_get_key(j, k, &s); + new_anim->scale_track_insert_key(dtrack, kt - from, s); + } else if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) { Variant var = default_anim->track_get_key_value(j, k); new_anim->track_insert_key(dtrack, kt - from, var); + } else if (default_anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) { + float interp; + default_anim->blend_shape_track_get_key(j, k, &interp); + new_anim->blend_shape_track_insert_key(dtrack, kt - from, interp); } } if (dtrack != -1 && kt >= to) { - if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) { - Quaternion q; + if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) { Vector3 p; + default_anim->position_track_interpolate(j, to, &p); + new_anim->position_track_insert_key(dtrack, to - from, p); + } else if (default_anim->track_get_type(j) == Animation::TYPE_ROTATION_3D) { + Quaternion r; + default_anim->rotation_track_interpolate(j, to, &r); + new_anim->rotation_track_insert_key(dtrack, to - from, r); + } else if (default_anim->track_get_type(j) == Animation::TYPE_SCALE_3D) { Vector3 s; - default_anim->transform_track_interpolate(j, to, &p, &q, &s); - new_anim->transform_track_insert_key(dtrack, to - from, p, q, s); - } - if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) { + default_anim->scale_track_interpolate(j, to, &s); + new_anim->scale_track_insert_key(dtrack, to - from, s); + } else if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) { Variant var = default_anim->value_track_interpolate(j, to); new_anim->track_insert_key(dtrack, to - from, var); + } else if (default_anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) { + float interp; + default_anim->blend_shape_track_interpolate(j, to, &interp); + new_anim->blend_shape_track_insert_key(dtrack, to - from, interp); } } } @@ -896,25 +1154,40 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ new_anim->add_track(default_anim->track_get_type(j)); dtrack = new_anim->get_track_count() - 1; new_anim->track_set_path(dtrack, default_anim->track_get_path(j)); - if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) { - Quaternion q; + if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) { Vector3 p; + default_anim->position_track_interpolate(j, from, &p); + new_anim->position_track_insert_key(dtrack, 0, p); + default_anim->position_track_interpolate(j, to, &p); + new_anim->position_track_insert_key(dtrack, to - from, p); + } else if (default_anim->track_get_type(j) == Animation::TYPE_ROTATION_3D) { + Quaternion r; + default_anim->rotation_track_interpolate(j, from, &r); + new_anim->rotation_track_insert_key(dtrack, 0, r); + default_anim->rotation_track_interpolate(j, to, &r); + new_anim->rotation_track_insert_key(dtrack, to - from, r); + } else if (default_anim->track_get_type(j) == Animation::TYPE_SCALE_3D) { Vector3 s; - default_anim->transform_track_interpolate(j, from, &p, &q, &s); - new_anim->transform_track_insert_key(dtrack, 0, p, q, s); - default_anim->transform_track_interpolate(j, to, &p, &q, &s); - new_anim->transform_track_insert_key(dtrack, to - from, p, q, s); - } - if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) { + default_anim->scale_track_interpolate(j, from, &s); + new_anim->scale_track_insert_key(dtrack, 0, s); + default_anim->scale_track_interpolate(j, to, &s); + new_anim->scale_track_insert_key(dtrack, to - from, s); + } else if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) { Variant var = default_anim->value_track_interpolate(j, from); new_anim->track_insert_key(dtrack, 0, var); Variant to_var = default_anim->value_track_interpolate(j, to); new_anim->track_insert_key(dtrack, to - from, to_var); + } else if (default_anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) { + float interp; + default_anim->blend_shape_track_interpolate(j, from, &interp); + new_anim->blend_shape_track_insert_key(dtrack, 0, interp); + default_anim->blend_shape_track_interpolate(j, to, &interp); + new_anim->blend_shape_track_insert_key(dtrack, to - from, interp); } } } - new_anim->set_loop(loop); + new_anim->set_loop_mode(loop_mode); new_anim->set_length(to - from); anim->add_animation(name, new_anim); @@ -936,6 +1209,15 @@ void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_ } } +void ResourceImporterScene::_compress_animations(AnimationPlayer *anim, int p_page_size_kb) { + List<StringName> anim_names; + anim->get_animation_list(&anim_names); + for (const StringName &E : anim_names) { + Ref<Animation> a = anim->get_animation(E); + a->compress(p_page_size_kb * 1024); + } +} + void ResourceImporterScene::get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const { switch (p_category) { case INTERNAL_IMPORT_CATEGORY_NODE: { @@ -980,13 +1262,15 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/shadow_meshes", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lightmap_uv", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lods", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "lods/normal_split_angle", PROPERTY_HINT_RANGE, "0,180,0.1,degrees"), 25.0f)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "lods/normal_merge_angle", PROPERTY_HINT_RANGE, "0,180,0.1,degrees"), 60.0f)); } break; case INTERNAL_IMPORT_CATEGORY_MATERIAL: { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "use_external/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "use_external/path", PROPERTY_HINT_FILE, "*.material,*.res,*.tres"), "")); } break; case INTERNAL_IMPORT_CATEGORY_ANIMATION: { - r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "settings/loops"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "settings/loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Pingpong"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "save_to_file/path", PROPERTY_HINT_SAVE_FILE, "*.res,*.tres"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/keep_custom_tracks"), "")); @@ -997,13 +1281,18 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_linear_error"), 0.05)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angular_error"), 0.01)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angle"), 22)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compression/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compression/page_size", PROPERTY_HINT_RANGE, "4,512,1,suffix:kb"), 8)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/position", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/rotation", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/scale", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/amount", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); for (int i = 0; i < 256; i++) { r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "slice_" + itos(i + 1) + "/name"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/start_frame"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/end_frame"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/loops"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Pingpong"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "slice_" + itos(i + 1) + "/save_to_file/path", PROPERTY_HINT_SAVE_FILE, ".res,*.tres"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"), false)); @@ -1012,6 +1301,10 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p default: { } } + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->get_internal_import_options(EditorScenePostImportPlugin::InternalImportCategory(p_category), r_options); + } } bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { @@ -1059,27 +1352,28 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor if (p_option == "primitive/position" || p_option == "primitive/rotation") { const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); return generate_physics && - physics_shape >= SHAPE_TYPE_BOX; + physics_shape >= SHAPE_TYPE_BOX; } if (p_option == "primitive/size") { const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); return generate_physics && - physics_shape == SHAPE_TYPE_BOX; + physics_shape == SHAPE_TYPE_BOX; } if (p_option == "primitive/radius") { const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); - return generate_physics && (physics_shape == SHAPE_TYPE_SPHERE || - physics_shape == SHAPE_TYPE_CYLINDER || - physics_shape == SHAPE_TYPE_CAPSULE); + return generate_physics && + (physics_shape == SHAPE_TYPE_SPHERE || + physics_shape == SHAPE_TYPE_CYLINDER || + physics_shape == SHAPE_TYPE_CAPSULE); } if (p_option == "primitive/height") { const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); return generate_physics && - (physics_shape == SHAPE_TYPE_CYLINDER || - physics_shape == SHAPE_TYPE_CAPSULE); + (physics_shape == SHAPE_TYPE_CYLINDER || + physics_shape == SHAPE_TYPE_CAPSULE); } } break; case INTERNAL_IMPORT_CATEGORY_MESH: { @@ -1098,13 +1392,16 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor } } break; case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: { - if (p_option.begins_with("animation/optimizer/") && p_option != "animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"])) { + if (p_option.begins_with("optimizer/") && p_option != "optimizer/enabled" && !bool(p_options["optimizer/enabled"])) { + return false; + } + if (p_option.begins_with("compression/") && p_option != "compression/enabled" && !bool(p_options["compression/enabled"])) { return false; } - if (p_option.begins_with("animation/slice_")) { - int max_slice = p_options["animation/slices/amount"]; - int slice = p_option.get_slice("/", 1).get_slice("_", 1).to_int() - 1; + if (p_option.begins_with("slice_")) { + int max_slice = p_options["slices/amount"]; + int slice = p_option.get_slice("_", 1).to_int() - 1; if (slice >= max_slice) { return false; } @@ -1114,6 +1411,13 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor } } + for (int i = 0; i < post_importer_plugins.size(); i++) { + Variant ret = post_importer_plugins.write[i]->get_internal_option_visibility(EditorScenePostImportPlugin::InternalImportCategory(p_category), p_option, p_options); + if (ret.get_type() == Variant::BOOL) { + return ret; + } + } + return true; } @@ -1141,10 +1445,18 @@ bool ResourceImporterScene::get_internal_option_update_view_required(InternalImp default: { } } + + for (int i = 0; i < post_importer_plugins.size(); i++) { + Variant ret = post_importer_plugins.write[i]->get_internal_option_update_view_required(EditorScenePostImportPlugin::InternalImportCategory(p_category), p_option, p_options); + if (ret.get_type() == Variant::BOOL) { + return ret; + } + } + return false; } -void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterScene::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_type", PROPERTY_HINT_TYPE_STRING, "Node"), "Node3D")); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_name"), "Scene Root")); @@ -1154,7 +1466,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in String script_ext_hint; for (const String &E : script_extentions) { - if (script_ext_hint != "") { + if (!script_ext_hint.is_empty()) { script_ext_hint += ","; } script_ext_hint += "*." + E; @@ -1164,15 +1476,22 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/create_shadow_meshes"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static,Static Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 2)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI),Static Lightmaps,Dynamic (VoxelGI only)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/bake_reset_animation"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 30)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), "")); - r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), Dictionary())); + r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), Dictionary())); + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->get_import_options(p_path, r_options); + } + + for (Ref<EditorSceneFormatImporter> importer : importers) { + importer->get_import_options(p_path, r_options); + } } void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner) { @@ -1186,66 +1505,8 @@ void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_ } } -Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) { - Ref<EditorSceneImporter> importer; - String ext = p_path.get_extension().to_lower(); - - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { - if (E->get().ptr() == p_exception) { - continue; - } - List<String> extensions; - E->get()->get_extensions(&extensions); - - for (const String &F : extensions) { - if (F.to_lower() == ext) { - importer = E; - break; - } - } - - if (importer.is_valid()) { - break; - } - } - - ERR_FAIL_COND_V(!importer.is_valid(), nullptr); - - List<String> missing; - Error err; - return importer->import_scene(p_path, p_flags, p_bake_fps, &missing, &err); -} - -Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) { - Ref<EditorSceneImporter> importer; - String ext = p_path.get_extension().to_lower(); - - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { - if (E->get().ptr() == p_exception) { - continue; - } - List<String> extensions; - E->get()->get_extensions(&extensions); - - for (const String &F : extensions) { - if (F.to_lower() == ext) { - importer = E; - break; - } - } - - if (importer.is_valid()) { - break; - } - } - - ERR_FAIL_COND_V(!importer.is_valid(), nullptr); - - return importer->import_animation(p_path, p_flags, p_bake_fps); -} - 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) { - EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + ImporterMeshInstance3D *src_mesh_node = Object::cast_to<ImporterMeshInstance3D>(p_node); if (src_mesh_node) { //is mesh MeshInstance3D *mesh_node = memnew(MeshInstance3D); @@ -1259,6 +1520,8 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m //do mesh processing bool generate_lods = p_generate_lods; + float split_angle = 25.0f; + float merge_angle = 60.0f; bool create_shadow_meshes = p_create_shadow_meshes; bool bake_lightmaps = p_light_bake_mode == LIGHT_BAKE_STATIC_LIGHTMAPS; String save_to_file; @@ -1271,7 +1534,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m mesh_id = src_mesh_node->get_mesh()->get_name(); } - if (mesh_id != String() && p_mesh_data.has(mesh_id)) { + if (!mesh_id.is_empty() && p_mesh_data.has(mesh_id)) { Dictionary mesh_settings = p_mesh_data[mesh_id]; if (mesh_settings.has("generate/shadow_meshes")) { @@ -1301,17 +1564,30 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } } + if (mesh_settings.has("lods/normal_split_angle")) { + split_angle = mesh_settings["lods/normal_split_angle"]; + } + + if (mesh_settings.has("lods/normal_merge_angle")) { + merge_angle = mesh_settings["lods/normal_merge_angle"]; + } + if (mesh_settings.has("save_to_file/enabled") && bool(mesh_settings["save_to_file/enabled"]) && mesh_settings.has("save_to_file/path")) { save_to_file = mesh_settings["save_to_file/path"]; if (!save_to_file.is_resource_file()) { save_to_file = ""; } } + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MESH, nullptr, src_mesh_node, src_mesh_node->get_mesh(), mesh_settings); + } } if (generate_lods) { - src_mesh_node->get_mesh()->generate_lods(); + src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle); } + if (create_shadow_meshes) { src_mesh_node->get_mesh()->create_shadow_mesh(); } @@ -1348,7 +1624,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } } - if (save_to_file != String()) { + if (!save_to_file.is_empty()) { Ref<Mesh> existing = Ref<Resource>(ResourceCache::get(save_to_file)); if (existing.is_valid()) { //if somehow an existing one is useful, create @@ -1384,7 +1660,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } break; case LIGHT_BAKE_STATIC: case LIGHT_BAKE_STATIC_LIGHTMAPS: { - mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_BAKED); + mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_STATIC); } break; } @@ -1402,20 +1678,171 @@ void ResourceImporterScene::_add_shapes(Node *p_node, const Vector<Ref<Shape3D>> for (const Ref<Shape3D> &E : p_shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E); - p_node->add_child(cshape); + p_node->add_child(cshape, true); cshape->set_owner(p_node->get_owner()); } } +void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions) { + List<StringName> anims; + p_player->get_animation_list(&anims); + Node *parent = p_player->get_parent(); + ERR_FAIL_COND(parent == nullptr); + OrderedHashMap<NodePath, uint32_t> used_tracks[TRACK_CHANNEL_MAX]; + bool tracks_to_add = false; + static const Animation::TrackType track_types[TRACK_CHANNEL_MAX] = { Animation::TYPE_POSITION_3D, Animation::TYPE_ROTATION_3D, Animation::TYPE_SCALE_3D, Animation::TYPE_BLEND_SHAPE }; + for (const StringName &I : anims) { + Ref<Animation> anim = p_player->get_animation(I); + for (int i = 0; i < anim->get_track_count(); i++) { + for (int j = 0; j < TRACK_CHANNEL_MAX; j++) { + if (anim->track_get_type(i) != track_types[j]) { + continue; + } + switch (p_track_actions[j]) { + case ANIMATION_IMPORT_TRACKS_IF_PRESENT: { + // Do Nothing. + } break; + case ANIMATION_IMPORT_TRACKS_IF_PRESENT_FOR_ALL: { + used_tracks[j].insert(anim->track_get_path(i), 0); + tracks_to_add = true; + } break; + case ANIMATION_IMPORT_TRACKS_NEVER: { + anim->remove_track(i); + i--; + } break; + } + } + } + } + + if (!tracks_to_add) { + return; + } + + uint32_t pass = 0; + for (const StringName &I : anims) { + Ref<Animation> anim = p_player->get_animation(I); + for (int j = 0; j < TRACK_CHANNEL_MAX; j++) { + if (p_track_actions[j] != ANIMATION_IMPORT_TRACKS_IF_PRESENT_FOR_ALL) { + continue; + } + + pass++; + + for (int i = 0; i < anim->get_track_count(); i++) { + if (anim->track_get_type(i) != track_types[j]) { + continue; + } + + NodePath path = anim->track_get_path(i); + + ERR_CONTINUE(!used_tracks[j].has(path)); // Should never happen. + + used_tracks[j][path] = pass; + } + + for (OrderedHashMap<NodePath, uint32_t>::Element J = used_tracks[j].front(); J; J = J.next()) { + if (J.get() == pass) { + continue; + } + + NodePath path = J.key(); + Node *n = parent->get_node(path); + + if (j == TRACK_CHANNEL_BLEND_SHAPE) { + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(n); + if (mi && path.get_subname_count() > 0) { + StringName bs = path.get_subname(0); + bool valid; + float value = mi->get(bs, &valid); + if (valid) { + int track_idx = anim->add_track(track_types[j]); + anim->track_set_path(track_idx, path); + anim->track_set_imported(track_idx, true); + anim->blend_shape_track_insert_key(track_idx, 0, value); + } + } + + } else { + Skeleton3D *skel = Object::cast_to<Skeleton3D>(n); + Node3D *n3d = Object::cast_to<Node3D>(n); + Vector3 loc; + Quaternion rot; + Vector3 scale; + if (skel && path.get_subname_count() > 0) { + StringName bone = path.get_subname(0); + int bone_idx = skel->find_bone(bone); + if (bone_idx == -1) { + continue; + } + // Note that this is using get_bone_pose to update the bone pose cache. + _ALLOW_DISCARD_ skel->get_bone_pose(bone_idx); + loc = skel->get_bone_pose_position(bone_idx); + rot = skel->get_bone_pose_rotation(bone_idx); + scale = skel->get_bone_pose_scale(bone_idx); + } else if (n3d) { + loc = n3d->get_position(); + rot = n3d->get_transform().basis.get_rotation_quaternion(); + scale = n3d->get_scale(); + } else { + continue; + } + + // Ensure insertion keeps tracks together and ordered by type (loc/rot/scale) + int insert_at_pos = -1; + for (int k = 0; k < anim->get_track_count(); k++) { + NodePath tpath = anim->track_get_path(k); + + if (path == tpath) { + Animation::TrackType ttype = anim->track_get_type(k); + if (insert_at_pos == -1) { + // First insert, determine whether replacing or kicking back + if (track_types[j] < ttype) { + insert_at_pos = k; + break; // No point in continuing. + } else { + insert_at_pos = k + 1; + } + } else if (ttype < track_types[j]) { + // Kick back. + insert_at_pos = k + 1; + } + } else if (insert_at_pos >= 0) { + break; + } + } + int track_idx = anim->add_track(track_types[j], insert_at_pos); + + anim->track_set_path(track_idx, path); + anim->track_set_imported(track_idx, true); + switch (j) { + case TRACK_CHANNEL_POSITION: { + anim->position_track_insert_key(track_idx, 0, loc); + } break; + case TRACK_CHANNEL_ROTATION: { + anim->rotation_track_insert_key(track_idx, 0, rot); + } break; + case TRACK_CHANNEL_SCALE: { + anim->scale_track_insert_key(track_idx, 0, scale); + } break; + default: { + } + } + } + } + } + } +} + Node *ResourceImporterScene::pre_import(const String &p_source_file) { - Ref<EditorSceneImporter> importer; + Ref<EditorSceneFormatImporter> importer; String ext = p_source_file.get_extension().to_lower(); EditorProgress progress("pre-import", TTR("Pre-Import Scene"), 0); progress.step(TTR("Importing Scene..."), 0); - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneFormatImporter>>::Element *E = importers.front(); E; E = E->next()) { List<String> extensions; E->get()->get_extensions(&extensions); @@ -1434,14 +1861,14 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { ERR_FAIL_COND_V(!importer.is_valid(), nullptr); Error err = OK; - Node *scene = importer->import_scene(p_source_file, EditorSceneImporter::IMPORT_ANIMATION | EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, 15, nullptr, &err); + Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, Map<StringName, Variant>(), 15, nullptr, &err); if (!scene || err != OK) { return nullptr; } - Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> collision_map; - - _pre_fix_node(scene, scene, collision_map); + Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; + List<Pair<NodePath, Node *>> node_renames; + _pre_fix_node(scene, scene, collision_map, node_renames); return scene; } @@ -1449,13 +1876,13 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { const String &src_path = p_source_file; - Ref<EditorSceneImporter> importer; + Ref<EditorSceneFormatImporter> importer; String ext = src_path.get_extension().to_lower(); EditorProgress progress("import", TTR("Import Scene"), 104); progress.step(TTR("Importing Scene..."), 0); - for (Set<Ref<EditorSceneImporter>>::Element *E = importers.front(); E; E = E->next()) { + for (Set<Ref<EditorSceneFormatImporter>>::Element *E = importers.front(); E; E = E->next()) { List<String> extensions; E->get()->get_extensions(&extensions); @@ -1478,21 +1905,21 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p int import_flags = 0; if (bool(p_options["animation/import"])) { - import_flags |= EditorSceneImporter::IMPORT_ANIMATION; + import_flags |= EditorSceneFormatImporter::IMPORT_ANIMATION; } if (bool(p_options["skins/use_named_skins"])) { - import_flags |= EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS; + import_flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; } bool ensure_tangents = p_options["meshes/ensure_tangents"]; if (ensure_tangents) { - import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS; + import_flags |= EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS; } Error err = OK; List<String> missing_deps; // for now, not much will be done with this - Node *scene = importer->import_scene(src_path, import_flags, fps, &missing_deps, &err); + Node *scene = importer->import_scene(src_path, import_flags, p_options, fps, &missing_deps, &err); if (!scene || err != OK) { return err; } @@ -1514,17 +1941,18 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p animation_data = subresources["animations"]; } - Set<Ref<EditorSceneImporterMesh>> scanned_meshes; - Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> collision_map; + Set<Ref<ImporterMesh>> scanned_meshes; + Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map; + List<Pair<NodePath, Node *>> node_renames; - _pre_fix_node(scene, scene, collision_map); - _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps); - bool use_bake_reset_animation = p_options["animation/bake_reset_animation"]; - if (use_bake_reset_animation) { - BakeReset bake_reset; - bake_reset._bake_animation_pose(scene, "RESET"); + _pre_fix_node(scene, scene, collision_map, node_renames); + + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->pre_process(scene, p_options); } + _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps); + String root_type = p_options["nodes/root_type"]; root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class. @@ -1600,7 +2028,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p String post_import_script_path = p_options["import_script/path"]; Ref<EditorScenePostImport> post_import_script; - if (post_import_script_path != "") { + if (!post_import_script_path.is_empty()) { Ref<Script> scr = ResourceLoader::load(post_import_script_path); if (!scr.is_valid()) { EditorNode::add_io_error(TTR("Couldn't load post-import script:") + " " + post_import_script_path); @@ -1626,6 +2054,10 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } } + for (int i = 0; i < post_importer_plugins.size(); i++) { + post_importer_plugins.write[i]->post_process(scene, p_options); + } + progress.step(TTR("Saving..."), 104); Ref<PackedScene> packer = memnew(PackedScene); @@ -1657,15 +2089,15 @@ ResourceImporterScene::ResourceImporterScene() { /////////////////////////////////////// -uint32_t EditorSceneImporterESCN::get_import_flags() const { +uint32_t EditorSceneFormatImporterESCN::get_import_flags() const { return IMPORT_SCENE; } -void EditorSceneImporterESCN::get_extensions(List<String> *r_extensions) const { +void EditorSceneFormatImporterESCN::get_extensions(List<String> *r_extensions) const { r_extensions->push_back("escn"); } -Node *EditorSceneImporterESCN::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { +Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { Error error; Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error); ERR_FAIL_COND_V_MSG(!ps.is_valid(), nullptr, "Cannot load scene as text resource from path '" + p_path + "'."); @@ -1676,6 +2108,6 @@ Node *EditorSceneImporterESCN::import_scene(const String &p_path, uint32_t p_fla return scene; } -Ref<Animation> EditorSceneImporterESCN::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { +Ref<Animation> EditorSceneFormatImporterESCN::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { ERR_FAIL_V(Ref<Animation>()); } diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index e232b715be..13b55b5754 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,9 @@ #ifndef RESOURCEIMPORTERSCENE_H #define RESOURCEIMPORTERSCENE_H +#include "core/error/error_macros.h" #include "core/io/resource_importer.h" +#include "core/variant/dictionary.h" #include "scene/3d/node_3d.h" #include "scene/resources/animation.h" #include "scene/resources/mesh.h" @@ -41,20 +43,22 @@ class Material; class AnimationPlayer; -class EditorSceneImporterMesh; -class EditorSceneImporter : public RefCounted { - GDCLASS(EditorSceneImporter, RefCounted); +class ImporterMesh; +class EditorSceneFormatImporter : public RefCounted { + GDCLASS(EditorSceneFormatImporter, RefCounted); protected: static void _bind_methods(); - Node *import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps); - Ref<Animation> import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps); + Node *import_scene_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options, int p_bake_fps); + Ref<Animation> import_animation_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options, int p_bake_fps); GDVIRTUAL0RC(int, _get_import_flags) GDVIRTUAL0RC(Vector<String>, _get_extensions) - GDVIRTUAL3R(Object *, _import_scene, String, uint32_t, uint32_t) - GDVIRTUAL3R(Ref<Animation>, _import_animation, String, uint32_t, uint32_t) + GDVIRTUAL4R(Object *, _import_scene, String, uint32_t, Dictionary, uint32_t) + GDVIRTUAL4R(Ref<Animation>, _import_animation, String, uint32_t, Dictionary, uint32_t) + GDVIRTUAL1(_get_import_options, String) + GDVIRTUAL2RC(Variant, _get_option_visibility, String, String) public: enum ImportFlags { @@ -67,10 +71,12 @@ public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); + virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps); + virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options); + virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options); - EditorSceneImporter() {} + EditorSceneFormatImporter() {} }; class EditorScenePostImport : public RefCounted { @@ -90,18 +96,72 @@ public: EditorScenePostImport(); }; +class EditorScenePostImportPlugin : public RefCounted { + GDCLASS(EditorScenePostImportPlugin, RefCounted); + +public: + enum InternalImportCategory { + INTERNAL_IMPORT_CATEGORY_NODE, + INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, + INTERNAL_IMPORT_CATEGORY_MESH, + INTERNAL_IMPORT_CATEGORY_MATERIAL, + INTERNAL_IMPORT_CATEGORY_ANIMATION, + INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, + INTERNAL_IMPORT_CATEGORY_MAX + }; + +private: + mutable const Map<StringName, Variant> *current_options = nullptr; + mutable const Dictionary *current_options_dict = nullptr; + List<ResourceImporter::ImportOption> *current_option_list = nullptr; + InternalImportCategory current_category = INTERNAL_IMPORT_CATEGORY_MAX; + +protected: + GDVIRTUAL1(_get_internal_import_options, int) + GDVIRTUAL2RC(Variant, _get_internal_option_visibility, int, String) + GDVIRTUAL2RC(Variant, _get_internal_option_update_view_required, int, String) + GDVIRTUAL4(_internal_process, int, Node *, Node *, RES) + GDVIRTUAL1(_get_import_options, String) + GDVIRTUAL2RC(Variant, _get_option_visibility, String, String) + GDVIRTUAL1(_pre_process, Node *) + GDVIRTUAL1(_post_process, Node *) + + static void _bind_methods(); + +public: + Variant get_option_value(const StringName &p_name) const; + void add_import_option(const String &p_name, Variant p_default_value); + void add_import_option_advanced(Variant::Type p_type, const String &p_name, Variant p_default_value, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = String(), int p_usage_flags = PROPERTY_USAGE_DEFAULT); + + virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options); + virtual Variant get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + virtual Variant get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + + virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, RES p_resource, const Dictionary &p_options); + + virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options); + virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const; + + virtual void pre_process(Node *p_scene, const Map<StringName, Variant> &p_options); + virtual void post_process(Node *p_scene, const Map<StringName, Variant> &p_options); + + EditorScenePostImportPlugin() {} +}; + +VARIANT_ENUM_CAST(EditorScenePostImportPlugin::InternalImportCategory) + class ResourceImporterScene : public ResourceImporter { GDCLASS(ResourceImporterScene, ResourceImporter); - Set<Ref<EditorSceneImporter>> importers; + Set<Ref<EditorSceneFormatImporter>> importers; static ResourceImporterScene *singleton; enum LightBakeMode { LIGHT_BAKE_DISABLED, - LIGHT_BAKE_DYNAMIC, LIGHT_BAKE_STATIC, - LIGHT_BAKE_STATIC_LIGHTMAPS + LIGHT_BAKE_STATIC_LIGHTMAPS, + LIGHT_BAKE_DYNAMIC, }; enum MeshPhysicsMode { @@ -144,13 +204,33 @@ class ResourceImporterScene : public ResourceImporter { 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); + enum AnimationImportTracks { + ANIMATION_IMPORT_TRACKS_IF_PRESENT, + ANIMATION_IMPORT_TRACKS_IF_PRESENT_FOR_ALL, + ANIMATION_IMPORT_TRACKS_NEVER, + }; + enum TrackChannel { + TRACK_CHANNEL_POSITION, + TRACK_CHANNEL_ROTATION, + TRACK_CHANNEL_SCALE, + TRACK_CHANNEL_BLEND_SHAPE, + TRACK_CHANNEL_MAX + }; + + void _optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions); + + mutable Vector<Ref<EditorScenePostImportPlugin>> post_importer_plugins; + public: static ResourceImporterScene *get_singleton() { return singleton; } - const Set<Ref<EditorSceneImporter>> &get_importers() const { return importers; } + void add_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin) { post_importer_plugins.push_back(p_plugin); } + void remove_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin) { post_importer_plugins.erase(p_plugin); } + + const Set<Ref<EditorSceneFormatImporter>> &get_importers() const { return importers; } - void add_importer(Ref<EditorSceneImporter> p_importer) { importers.insert(p_importer); } - void remove_importer(Ref<EditorSceneImporter> p_importer) { importers.erase(p_importer); } + void add_importer(Ref<EditorSceneFormatImporter> p_importer) { importers.insert(p_importer); } + void remove_importer(Ref<EditorSceneFormatImporter> p_importer) { importers.erase(p_importer); } virtual String get_importer_name() const override; virtual String get_visible_name() const override; @@ -163,37 +243,35 @@ public: virtual String get_preset_name(int p_idx) const override; enum InternalImportCategory { - INTERNAL_IMPORT_CATEGORY_NODE, - INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, - INTERNAL_IMPORT_CATEGORY_MESH, - INTERNAL_IMPORT_CATEGORY_MATERIAL, - INTERNAL_IMPORT_CATEGORY_ANIMATION, - INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, - INTERNAL_IMPORT_CATEGORY_MAX + INTERNAL_IMPORT_CATEGORY_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_NODE, + INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, + INTERNAL_IMPORT_CATEGORY_MESH = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MESH, + INTERNAL_IMPORT_CATEGORY_MATERIAL = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MATERIAL, + INTERNAL_IMPORT_CATEGORY_ANIMATION = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION, + INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, + INTERNAL_IMPORT_CATEGORY_MAX = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MAX }; void get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const; bool get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; bool get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; // Import scenes *after* everything else (such as textures). virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } - Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map); - Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); + Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, List<Pair<NodePath, Node *>> &r_node_renames); + Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks); void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all); void _optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle); + void _compress_animations(AnimationPlayer *anim, int p_page_size_kb); Node *pre_import(const String &p_source_file); virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - Node *import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); - Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); - virtual bool has_advanced_options() const override; virtual void show_advanced_options(const String &p_path) override; @@ -208,14 +286,14 @@ public: static Transform3D get_collision_shapes_transform(const M &p_options); }; -class EditorSceneImporterESCN : public EditorSceneImporter { - GDCLASS(EditorSceneImporterESCN, EditorSceneImporter); +class EditorSceneFormatImporterESCN : public EditorSceneFormatImporter { + GDCLASS(EditorSceneFormatImporterESCN, EditorSceneFormatImporter); public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; + virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override; }; #include "scene/resources/box_shape_3d.h" diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp index c01d8068da..cc34259a2d 100644 --- a/editor/import/resource_importer_shader_file.cpp +++ b/editor/import/resource_importer_shader_file.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -65,10 +65,10 @@ String ResourceImporterShaderFile::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterShaderFile::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterShaderFile::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { } -bool ResourceImporterShaderFile::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterShaderFile::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } diff --git a/editor/import/resource_importer_shader_file.h b/editor/import/resource_importer_shader_file.h index c421132ec2..858c2e783c 100644 --- a/editor/import/resource_importer_shader_file.h +++ b/editor/import/resource_importer_shader_file.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,8 +46,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 61745cb6ee..f21012258c 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,6 +37,8 @@ #include "editor/editor_node.h" void ResourceImporterTexture::_texture_reimport_roughness(const Ref<StreamTexture2D> &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { + ERR_FAIL_COND(p_tex.is_null()); + MutexLock lock(singleton->mutex); StringName path = p_tex->get_path(); @@ -51,6 +53,8 @@ void ResourceImporterTexture::_texture_reimport_roughness(const Ref<StreamTextur } void ResourceImporterTexture::_texture_reimport_3d(const Ref<StreamTexture2D> &p_tex) { + ERR_FAIL_COND(p_tex.is_null()); + MutexLock lock(singleton->mutex); StringName path = p_tex->get_path(); @@ -63,6 +67,8 @@ void ResourceImporterTexture::_texture_reimport_3d(const Ref<StreamTexture2D> &p } void ResourceImporterTexture::_texture_reimport_normal(const Ref<StreamTexture2D> &p_tex) { + ERR_FAIL_COND(p_tex.is_null()); + MutexLock lock(singleton->mutex); StringName path = p_tex->get_path(); @@ -86,28 +92,28 @@ void ResourceImporterTexture::update_imports() { return; } - for (Map<StringName, MakeInfo>::Element *E = make_flags.front(); E; E = E->next()) { + for (const KeyValue<StringName, MakeInfo> &E : make_flags) { Ref<ConfigFile> cf; cf.instantiate(); - String src_path = String(E->key()) + ".import"; + String src_path = String(E.key) + ".import"; Error err = cf->load(src_path); ERR_CONTINUE(err != OK); bool changed = false; - if (E->get().flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0) { + if (E.value.flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0) { cf->set_value("params", "compress/normal_map", 1); changed = true; } - if (E->get().flags & MAKE_ROUGHNESS_FLAG && int(cf->get_value("params", "roughness/mode")) == 0) { - cf->set_value("params", "roughness/mode", E->get().channel_for_roughness + 2); - cf->set_value("params", "roughness/src_normal", E->get().normal_path_for_roughness); + if (E.value.flags & MAKE_ROUGHNESS_FLAG && int(cf->get_value("params", "roughness/mode")) == 0) { + cf->set_value("params", "roughness/mode", E.value.channel_for_roughness + 2); + cf->set_value("params", "roughness/src_normal", E.value.normal_path_for_roughness); changed = true; } - if (E->get().flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d/compress_to"))) { + if (E.value.flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d/compress_to"))) { int compress_to = cf->get_value("params", "detect_3d/compress_to"); cf->set_value("params", "detect_3d/compress_to", 0); if (compress_to == 1) { @@ -121,7 +127,7 @@ void ResourceImporterTexture::update_imports() { if (changed) { cf->save(src_path); - to_reimport.push_back(E->key()); + to_reimport.push_back(E.key); } } @@ -153,7 +159,7 @@ String ResourceImporterTexture::get_resource_type() const { return "StreamTexture2D"; } -bool ResourceImporterTexture::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterTexture::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option == "compress/lossy_quality") { int compress_mode = int(p_options["compress/mode"]); if (compress_mode != COMPRESS_LOSSY && compress_mode != COMPRESS_VRAM_COMPRESSED) { @@ -194,7 +200,7 @@ String ResourceImporterTexture::get_preset_name(int p_idx) const { return preset_names[p_idx]; } -void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,VRAM Compressed,VRAM Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), p_preset == PRESET_3D ? 2 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_compression", PROPERTY_HINT_ENUM, "Disabled,Opaque Only,Always"), 1)); @@ -205,20 +211,24 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options, r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "mipmaps/generate"), (p_preset == PRESET_3D ? true : false))); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "mipmaps/limit", PROPERTY_HINT_RANGE, "-1,256"), -1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "roughness/mode", PROPERTY_HINT_ENUM, "Detect,Disabled,Red,Green,Blue,Alpha,Gray"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "roughness/src_normal", PROPERTY_HINT_FILE, "*.bmp,*.dds,*.exr,*.jpeg,*.jpg,*.hdr,*.png,*.svg,*.svgz,*.tga,*.webp"), "")); + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "roughness/src_normal", PROPERTY_HINT_FILE, "*.bmp,*.dds,*.exr,*.jpeg,*.jpg,*.hdr,*.png,*.svg,*.tga,*.webp"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/fix_alpha_border"), p_preset != PRESET_3D)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/normal_map_invert_y"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/HDR_as_SRGB"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "detect_3d/compress_to", PROPERTY_HINT_ENUM, "Disabled,VRAM Compressed,Basis Universal"), (p_preset == PRESET_DETECT) ? 1 : 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 1.0)); + + if (p_path.get_extension() == "svg") { + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 1.0)); + } } void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) { switch (p_compress_mode) { case COMPRESS_LOSSLESS: { - bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png"); + bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png") || + !Image::_webp_mem_loader_func; // WebP module disabled. bool use_webp = !lossless_force_png && p_image->get_width() <= 16383 && p_image->get_height() <= 16383; // WebP has a size limit f->store_32(use_webp ? StreamTexture2D::DATA_FORMAT_WEBP : StreamTexture2D::DATA_FORMAT_PNG); f->store_16(p_image->get_width()); @@ -401,11 +411,14 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String int size_limit = p_options["process/size_limit"]; bool hdr_as_srgb = p_options["process/HDR_as_SRGB"]; int normal = p_options["compress/normal_map"]; - float scale = p_options["svg/scale"]; int hdr_compression = p_options["compress/hdr_compression"]; int bptc_ldr = p_options["compress/bptc_ldr"]; int roughness = p_options["roughness/mode"]; String normal_map = p_options["roughness/src_normal"]; + float scale = 1.0; + if (p_options.has("svg/scale")) { + scale = p_options["svg/scale"]; + } Ref<Image> normal_image; Image::RoughnessChannel roughness_channel = Image::ROUGHNESS_CHANNEL_R; @@ -549,12 +562,6 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String formats_imported.push_back("etc"); } - if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc")) { - _save_stex(image, p_save_path + ".pvrtc.stex", compress_mode, lossy, Image::COMPRESS_PVRTC1_4, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); - r_platform_variants->push_back("pvrtc"); - formats_imported.push_back("pvrtc"); - } - if (!ok_on_pc) { EditorNode::add_io_error("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC."); } @@ -579,7 +586,6 @@ const char *ResourceImporterTexture::compression_formats[] = { "s3tc", "etc", "etc2", - "pvrtc", nullptr }; String ResourceImporterTexture::get_import_settings_string() const { diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index 41220009cd..ea2318fb33 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -95,8 +95,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index dec1466da1..d2a9fe2538 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -59,7 +59,7 @@ String ResourceImporterTextureAtlas::get_resource_type() const { return "Texture2D"; } -bool ResourceImporterTextureAtlas::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterTextureAtlas::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -71,9 +71,10 @@ String ResourceImporterTextureAtlas::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterTextureAtlas::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterTextureAtlas::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "atlas_file", PROPERTY_HINT_SAVE_FILE, "*.png"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_mode", PROPERTY_HINT_ENUM, "Region,Mesh2D"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "crop_to_region"), false)); } String ResourceImporterTextureAtlas::get_option_group_file() const { @@ -131,9 +132,9 @@ static void _plot_triangle(Vector2i *vertices, const Vector2i &p_offset, bool p_ double xf = x[0]; double xt = x[0] + dx_upper; // if y[0] == y[1], special case int max_y = MIN(y[2], height - p_offset.y - 1); - for (int yi = y[0]; yi <= max_y; yi++) { + for (int yi = y[0]; yi < max_y; yi++) { if (yi >= 0) { - for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < width ? xt : width - 1); xi++) { + for (int xi = (xf > 0 ? int(xf) : 0); xi < (xt <= src_width ? xt : src_width); xi++) { int px = xi, py = yi; int sx = px, sy = py; sx = CLAMP(sx, 0, src_width - 1); @@ -155,7 +156,7 @@ static void _plot_triangle(Vector2i *vertices, const Vector2i &p_offset, bool p_ p_image->set_pixel(px, py, color); } - for (int xi = (xf < width ? int(xf) : width - 1); xi >= (xt > 0 ? xt : 0); xi--) { + for (int xi = (xf < src_width ? int(xf) : src_width - 1); xi >= (xt > 0 ? xt : 0); xi--) { int px = xi, py = yi; int sx = px, sy = py; sx = CLAMP(sx, 0, src_width - 1); @@ -206,6 +207,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file ERR_CONTINUE(err != OK); pack_data.image = image; + pack_data.is_cropped = options["crop_to_region"]; int mode = options["import_mode"]; @@ -324,7 +326,10 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file atlas_texture.instantiate(); atlas_texture->set_atlas(cache); atlas_texture->set_region(Rect2(offset, pack_data.region.size)); - atlas_texture->set_margin(Rect2(pack_data.region.position, Size2(pack_data.image->get_width(), pack_data.image->get_height()) - pack_data.region.size)); + + if (!pack_data.is_cropped) { + atlas_texture->set_margin(Rect2(pack_data.region.position, pack_data.image->get_size() - pack_data.region.size)); + } texture = atlas_texture; } else { diff --git a/editor/import/resource_importer_texture_atlas.h b/editor/import/resource_importer_texture_atlas.h index b675d12477..a5e47dee99 100644 --- a/editor/import/resource_importer_texture_atlas.h +++ b/editor/import/resource_importer_texture_atlas.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,6 +38,7 @@ class ResourceImporterTextureAtlas : public ResourceImporter { struct PackData { Rect2 region; + bool is_cropped = false; bool is_mesh = false; Vector<int> chart_pieces; //one for region, many for mesh Vector<Vector<Vector2>> chart_vertices; //for mesh @@ -59,8 +60,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual String get_option_group_file() const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index 2db1db9e51..8cb9a47fb5 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -58,7 +58,7 @@ String ResourceImporterWAV::get_resource_type() const { return "AudioStreamSample"; } -bool ResourceImporterWAV::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterWAV::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option == "force/max_rate_hz" && !bool(p_options["force/max_rate"])) { return false; } @@ -74,7 +74,7 @@ String ResourceImporterWAV::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterWAV::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterWAV::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/8_bit"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/mono"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/max_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); @@ -252,13 +252,13 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s //loop point info! /** - * Consider exploring next document: - * http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/RIFFNEW.pdf - * Especially on page: - * 16 - 17 - * Timestamp: - * 22:38 06.07.2017 GMT - **/ + * Consider exploring next document: + * http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/RIFFNEW.pdf + * Especially on page: + * 16 - 17 + * Timestamp: + * 22:38 06.07.2017 GMT + **/ for (int i = 0; i < 10; i++) { file->get_32(); // i wish to know why should i do this... no doc! @@ -272,7 +272,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s if (loop_type == 0x00) { loop = AudioStreamSample::LOOP_FORWARD; } else if (loop_type == 0x01) { - loop = AudioStreamSample::LOOP_PING_PONG; + loop = AudioStreamSample::LOOP_PINGPONG; } else if (loop_type == 0x02) { loop = AudioStreamSample::LOOP_BACKWARD; } diff --git a/editor/import/resource_importer_wav.h b/editor/import/resource_importer_wav.h index 7413dbd11c..a5b576ceb9 100644 --- a/editor/import/resource_importer_wav.h +++ b/editor/import/resource_importer_wav.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,8 +46,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; static void _compress_ima_adpcm(const Vector<float> &p_data, Vector<uint8_t> &dst_data) { /*p_sample_data->data = (void*)malloc(len); diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 4bcb6863fb..eed1888c6a 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,8 @@ #include "scene_import_settings.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" -#include "editor/import/scene_importer_mesh_node_3d.h" +#include "scene/3d/importer_mesh_instance_3d.h" +#include "scene/resources/importer_mesh.h" #include "scene/resources/surface_tool.h" class SceneImportSettingsData : public Object { @@ -91,7 +92,7 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma if (p_material->has_meta("import_id")) { import_id = p_material->get_meta("import_id"); has_import_id = true; - } else if (p_material->get_name() != "") { + } else if (!p_material->get_name().is_empty()) { import_id = p_material->get_name(); has_import_id = true; } else { @@ -147,7 +148,7 @@ void SceneImportSettings::_fill_mesh(Tree *p_tree, const Ref<Mesh> &p_mesh, Tree if (p_mesh->has_meta("import_id")) { import_id = p_mesh->get_meta("import_id"); has_import_id = true; - } else if (p_mesh->get_name() != String()) { + } else if (!p_mesh->get_name().is_empty()) { import_id = p_mesh->get_name(); has_import_id = true; } else { @@ -240,7 +241,7 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { p_node->set_meta("import_id", import_id); } - EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); + ImporterMeshInstance3D *src_mesh_node = Object::cast_to<ImporterMeshInstance3D>(p_node); if (src_mesh_node) { MeshInstance3D *mesh_node = memnew(MeshInstance3D); @@ -249,7 +250,7 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { mesh_node->set_skin(src_mesh_node->get_skin()); mesh_node->set_skeleton_path(src_mesh_node->get_skeleton_path()); if (src_mesh_node->get_mesh().is_valid()) { - Ref<EditorSceneImporterMesh> editor_mesh = src_mesh_node->get_mesh(); + Ref<ImporterMesh> editor_mesh = src_mesh_node->get_mesh(); mesh_node->set_mesh(editor_mesh->get_mesh()); } @@ -326,7 +327,7 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { MeshInstance3D *collider_view = memnew(MeshInstance3D); collider_view->set_name("collider_view"); collider_view->set_visible(false); - mesh_node->add_child(collider_view); + mesh_node->add_child(collider_view, true); collider_view->set_owner(mesh_node); Transform3D accum_xform; @@ -413,7 +414,7 @@ void SceneImportSettings::_update_camera() { float rot_y = cam_rot_y; float zoom = cam_zoom; - if (selected_type == "Node" || selected_type == "") { + if (selected_type == "Node" || selected_type.is_empty()) { camera_aabb = contents_aabb; } else { if (mesh_preview->get_mesh().is_valid()) { @@ -434,7 +435,7 @@ void SceneImportSettings::_update_camera() { } } - Vector3 center = camera_aabb.position + camera_aabb.size * 0.5; + Vector3 center = camera_aabb.get_center(); float camera_size = camera_aabb.get_longest_axis_size(); camera->set_orthogonal(camera_size * zoom, 0.0001, camera_size * 2); @@ -663,7 +664,7 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { List<ResourceImporter::ImportOption> options; if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { - ResourceImporterScene::get_singleton()->get_import_options(&options); + ResourceImporterScene::get_singleton()->get_import_options(base_path, &options); } else { ResourceImporterScene::get_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); } @@ -736,21 +737,21 @@ void SceneImportSettings::_viewport_input(const Ref<InputEvent> &p_input) { zoom = &md.cam_zoom; } Ref<InputEventMouseMotion> mm = p_input; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { (*rot_x) -= mm->get_relative().y * 0.01 * EDSCALE; (*rot_y) -= mm->get_relative().x * 0.01 * EDSCALE; (*rot_x) = CLAMP((*rot_x), -Math_PI / 2, Math_PI / 2); _update_camera(); } Ref<InputEventMouseButton> mb = p_input; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { (*zoom) *= 1.1; if ((*zoom) > 10.0) { (*zoom) = 10.0; } _update_camera(); } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::WHEEL_UP) { (*zoom) /= 1.1; if ((*zoom) < 0.1) { (*zoom) = 0.1; @@ -771,52 +772,52 @@ void SceneImportSettings::_re_import() { Dictionary subresources; - for (Map<String, NodeData>::Element *E = node_map.front(); E; E = E->next()) { - if (E->get().settings.size()) { + for (KeyValue<String, NodeData> &E : node_map) { + if (E.value.settings.size()) { Dictionary d; - for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { - d[String(F->key())] = F->get(); + for (const KeyValue<StringName, Variant> &F : E.value.settings) { + d[String(F.key)] = F.value; } - nodes[E->key()] = d; + nodes[E.key] = d; } } if (nodes.size()) { subresources["nodes"] = nodes; } - for (Map<String, MaterialData>::Element *E = material_map.front(); E; E = E->next()) { - if (E->get().settings.size()) { + for (KeyValue<String, MaterialData> &E : material_map) { + if (E.value.settings.size()) { Dictionary d; - for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { - d[String(F->key())] = F->get(); + for (const KeyValue<StringName, Variant> &F : E.value.settings) { + d[String(F.key)] = F.value; } - materials[E->key()] = d; + materials[E.key] = d; } } if (materials.size()) { subresources["materials"] = materials; } - for (Map<String, MeshData>::Element *E = mesh_map.front(); E; E = E->next()) { - if (E->get().settings.size()) { + for (KeyValue<String, MeshData> &E : mesh_map) { + if (E.value.settings.size()) { Dictionary d; - for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { - d[String(F->key())] = F->get(); + for (const KeyValue<StringName, Variant> &F : E.value.settings) { + d[String(F.key)] = F.value; } - meshes[E->key()] = d; + meshes[E.key] = d; } } if (meshes.size()) { subresources["meshes"] = meshes; } - for (Map<String, AnimationData>::Element *E = animation_map.front(); E; E = E->next()) { - if (E->get().settings.size()) { + for (KeyValue<String, AnimationData> &E : animation_map) { + if (E.value.settings.size()) { Dictionary d; - for (Map<StringName, Variant>::Element *F = E->get().settings.front(); F; F = F->next()) { - d[String(F->key())] = F->get(); + for (const KeyValue<StringName, Variant> &F : E.value.settings) { + d[String(F.key)] = F.value; } - animations[E->key()] = d; + animations[E.key] = d; } } if (animations.size()) { @@ -889,8 +890,8 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { switch (current_action) { case ACTION_EXTRACT_MATERIALS: { - for (Map<String, MaterialData>::Element *E = material_map.front(); E; E = E->next()) { - MaterialData &md = material_map[E->key()]; + for (const KeyValue<String, MaterialData> &E : material_map) { + MaterialData &md = material_map[E.key]; TreeItem *item = external_path_tree->create_item(root); @@ -905,7 +906,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { item->set_text(2, "Already External"); item->set_tooltip(2, TTR("This material already references an external file, no action will be taken.\nDisable the external property for it to be extracted again.")); } else { - item->set_metadata(0, E->key()); + item->set_metadata(0, E.key); item->set_editable(0, true); item->set_checked(0, true); String path = p_path.plus_file(name); @@ -942,8 +943,8 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { external_paths->get_ok_button()->set_text(TTR("Extract")); } break; case ACTION_CHOOSE_MESH_SAVE_PATHS: { - for (Map<String, MeshData>::Element *E = mesh_map.front(); E; E = E->next()) { - MeshData &md = mesh_map[E->key()]; + for (const KeyValue<String, MeshData> &E : mesh_map) { + MeshData &md = mesh_map[E.key]; TreeItem *item = external_path_tree->create_item(root); @@ -958,7 +959,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { item->set_text(2, "Already Saving"); item->set_tooltip(2, TTR("This mesh already saves to an external resource, no action will be taken.")); } else { - item->set_metadata(0, E->key()); + item->set_metadata(0, E.key); item->set_editable(0, true); item->set_checked(0, true); String path = p_path.plus_file(name); @@ -995,8 +996,8 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { external_paths->get_ok_button()->set_text(TTR("Set Paths")); } break; case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: { - for (Map<String, AnimationData>::Element *E = animation_map.front(); E; E = E->next()) { - AnimationData &ad = animation_map[E->key()]; + for (const KeyValue<String, AnimationData> &E : animation_map) { + AnimationData &ad = animation_map[E.key]; TreeItem *item = external_path_tree->create_item(root); @@ -1010,7 +1011,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { item->set_text(2, "Already Saving"); item->set_tooltip(2, TTR("This animation already saves to an external resource, no action will be taken.")); } else { - item->set_metadata(0, E->key()); + item->set_metadata(0, E.key); item->set_editable(0, true); item->set_checked(0, true); String path = p_path.plus_file(name); diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index c7c94af493..4edf05c7bb 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp deleted file mode 100644 index 5e6dd08e79..0000000000 --- a/editor/import/scene_importer_mesh.cpp +++ /dev/null @@ -1,889 +0,0 @@ -/*************************************************************************/ -/* scene_importer_mesh.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "scene_importer_mesh.h" - -#include "core/math/math_defs.h" -#include "scene/resources/surface_tool.h" - -#include <cstdint> - -void EditorSceneImporterMesh::add_blend_shape(const String &p_name) { - ERR_FAIL_COND(surfaces.size() > 0); - blend_shapes.push_back(p_name); -} - -int EditorSceneImporterMesh::get_blend_shape_count() const { - return blend_shapes.size(); -} - -String EditorSceneImporterMesh::get_blend_shape_name(int p_blend_shape) const { - ERR_FAIL_INDEX_V(p_blend_shape, blend_shapes.size(), String()); - return blend_shapes[p_blend_shape]; -} - -void EditorSceneImporterMesh::set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode) { - blend_shape_mode = p_blend_shape_mode; -} - -Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const { - return blend_shape_mode; -} - -void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name, const uint32_t p_flags) { - ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); - ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX); - Surface s; - s.primitive = p_primitive; - s.arrays = p_arrays; - s.name = p_name; - s.flags = p_flags; - - Vector<Vector3> vertex_array = p_arrays[Mesh::ARRAY_VERTEX]; - int vertex_count = vertex_array.size(); - ERR_FAIL_COND(vertex_count == 0); - - for (int i = 0; i < blend_shapes.size(); i++) { - Array bsdata = p_blend_shapes[i]; - ERR_FAIL_COND(bsdata.size() != Mesh::ARRAY_MAX); - Vector<Vector3> vertex_data = bsdata[Mesh::ARRAY_VERTEX]; - ERR_FAIL_COND(vertex_data.size() != vertex_count); - Surface::BlendShape bs; - bs.arrays = bsdata; - s.blend_shape_data.push_back(bs); - } - - List<Variant> lods; - p_lods.get_key_list(&lods); - for (const Variant &E : lods) { - ERR_CONTINUE(!E.is_num()); - Surface::LOD lod; - lod.distance = E; - lod.indices = p_lods[E]; - ERR_CONTINUE(lod.indices.size() == 0); - s.lods.push_back(lod); - } - - s.material = p_material; - - surfaces.push_back(s); - mesh.unref(); -} - -int EditorSceneImporterMesh::get_surface_count() const { - return surfaces.size(); -} - -Mesh::PrimitiveType EditorSceneImporterMesh::get_surface_primitive_type(int p_surface) { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Mesh::PRIMITIVE_MAX); - return surfaces[p_surface].primitive; -} -Array EditorSceneImporterMesh::get_surface_arrays(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); - return surfaces[p_surface].arrays; -} -String EditorSceneImporterMesh::get_surface_name(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), String()); - return surfaces[p_surface].name; -} -void EditorSceneImporterMesh::set_surface_name(int p_surface, const String &p_name) { - ERR_FAIL_INDEX(p_surface, surfaces.size()); - surfaces.write[p_surface].name = p_name; - mesh.unref(); -} - -Array EditorSceneImporterMesh::get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); - ERR_FAIL_INDEX_V(p_blend_shape, surfaces[p_surface].blend_shape_data.size(), Array()); - return surfaces[p_surface].blend_shape_data[p_blend_shape].arrays; -} -int EditorSceneImporterMesh::get_surface_lod_count(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); - return surfaces[p_surface].lods.size(); -} -Vector<int> EditorSceneImporterMesh::get_surface_lod_indices(int p_surface, int p_lod) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Vector<int>()); - ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), Vector<int>()); - - return surfaces[p_surface].lods[p_lod].indices; -} - -float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); - ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), 0); - return surfaces[p_surface].lods[p_lod].distance; -} - -uint32_t EditorSceneImporterMesh::get_surface_format(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); - return surfaces[p_surface].flags; -} - -Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>()); - return surfaces[p_surface].material; -} - -void EditorSceneImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_material) { - ERR_FAIL_INDEX(p_surface, surfaces.size()); - surfaces.write[p_surface].material = p_material; - mesh.unref(); -} - -Basis EditorSceneImporterMesh::compute_rotation_matrix_from_ortho_6d(Vector3 p_x_raw, Vector3 p_y_raw) { - Vector3 x = p_x_raw.normalized(); - Vector3 z = x.cross(p_y_raw); - z = z.normalized(); - Vector3 y = z.cross(x); - Basis basis; - basis.set_axis(Vector3::AXIS_X, x); - basis.set_axis(Vector3::AXIS_Y, y); - basis.set_axis(Vector3::AXIS_Z, z); - return basis; -} - -void EditorSceneImporterMesh::generate_lods() { - if (!SurfaceTool::simplify_func) { - return; - } - if (!SurfaceTool::simplify_scale_func) { - return; - } - if (!SurfaceTool::simplify_sloppy_func) { - return; - } - if (!SurfaceTool::simplify_with_attrib_func) { - return; - } - - for (int i = 0; i < surfaces.size(); i++) { - if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) { - continue; - } - - surfaces.write[i].lods.clear(); - Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX]; - Vector<int> indices = surfaces[i].arrays[RS::ARRAY_INDEX]; - if (indices.size() == 0) { - continue; //no lods if no indices - } - Vector<Vector3> normals = surfaces[i].arrays[RS::ARRAY_NORMAL]; - uint32_t vertex_count = vertices.size(); - const Vector3 *vertices_ptr = vertices.ptr(); - Vector<float> attributes; - Vector<float> normal_weights; - int32_t attribute_count = 6; - if (normals.size()) { - attributes.resize(normals.size() * attribute_count); - for (int32_t normal_i = 0; normal_i < normals.size(); normal_i++) { - Basis basis; - basis.set_euler(normals[normal_i]); - Vector3 basis_x = basis.get_axis(0); - Vector3 basis_y = basis.get_axis(1); - basis = compute_rotation_matrix_from_ortho_6d(basis_x, basis_y); - basis_x = basis.get_axis(0); - basis_y = basis.get_axis(1); - attributes.write[normal_i * attribute_count + 0] = basis_x.x; - attributes.write[normal_i * attribute_count + 1] = basis_x.y; - attributes.write[normal_i * attribute_count + 2] = basis_x.z; - attributes.write[normal_i * attribute_count + 3] = basis_y.x; - attributes.write[normal_i * attribute_count + 4] = basis_y.y; - attributes.write[normal_i * attribute_count + 5] = basis_y.z; - } - normal_weights.resize(vertex_count); - for (int32_t weight_i = 0; weight_i < normal_weights.size(); weight_i++) { - normal_weights.write[weight_i] = 1.0; - } - } else { - attribute_count = 0; - } - const int min_indices = 10; - const float error_tolerance = 1.44224'95703; // Cube root of 3 - const float threshold = 1.0 / error_tolerance; - int index_target = indices.size() * threshold; - float max_mesh_error_percentage = 1e0f; - float mesh_error = 0.0f; - float scale = SurfaceTool::simplify_scale_func((const float *)vertices_ptr, vertex_count, sizeof(Vector3)); - while (index_target > min_indices) { - Vector<int> new_indices; - new_indices.resize(indices.size()); - size_t new_len = SurfaceTool::simplify_with_attrib_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, max_mesh_error_percentage, &mesh_error, (float *)attributes.ptrw(), normal_weights.ptrw(), attribute_count); - if ((int)new_len > (index_target * error_tolerance)) { - break; - } - Surface::LOD lod; - lod.distance = mesh_error * scale; - if (Math::is_zero_approx(mesh_error)) { - break; - } - if (new_len <= 0) { - break; - } - new_indices.resize(new_len); - lod.indices = new_indices; - print_line("Lod " + itos(surfaces.write[i].lods.size()) + " begin with " + itos(indices.size() / 3) + " triangles and shoot for " + itos(index_target / 3) + " triangles. Got " + itos(new_len / 3) + " triangles. Lod screen ratio " + rtos(lod.distance)); - surfaces.write[i].lods.push_back(lod); - index_target *= threshold; - } - } -} - -bool EditorSceneImporterMesh::has_mesh() const { - return mesh.is_valid(); -} - -Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<ArrayMesh> &p_base) { - ERR_FAIL_COND_V(surfaces.size() == 0, Ref<ArrayMesh>()); - - if (mesh.is_null()) { - if (p_base.is_valid()) { - mesh = p_base; - } - if (mesh.is_null()) { - mesh.instantiate(); - } - mesh->set_name(get_name()); - if (has_meta("import_id")) { - mesh->set_meta("import_id", get_meta("import_id")); - } - for (int i = 0; i < blend_shapes.size(); i++) { - mesh->add_blend_shape(blend_shapes[i]); - } - mesh->set_blend_shape_mode(blend_shape_mode); - for (int i = 0; i < surfaces.size(); i++) { - Array bs_data; - if (surfaces[i].blend_shape_data.size()) { - for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) { - bs_data.push_back(surfaces[i].blend_shape_data[j].arrays); - } - } - Dictionary lods; - if (surfaces[i].lods.size()) { - for (int j = 0; j < surfaces[i].lods.size(); j++) { - lods[surfaces[i].lods[j].distance] = surfaces[i].lods[j].indices; - } - } - - mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods, surfaces[i].flags); - if (surfaces[i].material.is_valid()) { - mesh->surface_set_material(mesh->get_surface_count() - 1, surfaces[i].material); - } - if (surfaces[i].name != String()) { - mesh->surface_set_name(mesh->get_surface_count() - 1, surfaces[i].name); - } - } - - mesh->set_lightmap_size_hint(lightmap_size_hint); - - if (shadow_mesh.is_valid()) { - Ref<ArrayMesh> shadow = shadow_mesh->get_mesh(); - mesh->set_shadow_mesh(shadow); - } - } - - return mesh; -} - -void EditorSceneImporterMesh::clear() { - surfaces.clear(); - blend_shapes.clear(); - mesh.unref(); -} - -void EditorSceneImporterMesh::create_shadow_mesh() { - if (shadow_mesh.is_valid()) { - shadow_mesh.unref(); - } - - //no shadow mesh for blendshapes - if (blend_shapes.size() > 0) { - return; - } - //no shadow mesh for skeletons - for (int i = 0; i < surfaces.size(); i++) { - if (surfaces[i].arrays[RS::ARRAY_BONES].get_type() != Variant::NIL) { - return; - } - if (surfaces[i].arrays[RS::ARRAY_WEIGHTS].get_type() != Variant::NIL) { - return; - } - } - - shadow_mesh.instantiate(); - - for (int i = 0; i < surfaces.size(); i++) { - LocalVector<int> vertex_remap; - Vector<Vector3> new_vertices; - Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX]; - int vertex_count = vertices.size(); - { - Map<Vector3, int> unique_vertices; - const Vector3 *vptr = vertices.ptr(); - for (int j = 0; j < vertex_count; j++) { - Vector3 v = vptr[j]; - - Map<Vector3, int>::Element *E = unique_vertices.find(v); - - if (E) { - vertex_remap.push_back(E->get()); - } else { - int vcount = unique_vertices.size(); - unique_vertices[v] = vcount; - vertex_remap.push_back(vcount); - new_vertices.push_back(v); - } - } - } - - Array new_surface; - new_surface.resize(RS::ARRAY_MAX); - Dictionary lods; - - // print_line("original vertex count: " + itos(vertices.size()) + " new vertex count: " + itos(new_vertices.size())); - - new_surface[RS::ARRAY_VERTEX] = new_vertices; - - Vector<int> indices = surfaces[i].arrays[RS::ARRAY_INDEX]; - if (indices.size()) { - int index_count = indices.size(); - const int *index_rptr = indices.ptr(); - Vector<int> new_indices; - new_indices.resize(indices.size()); - int *index_wptr = new_indices.ptrw(); - - for (int j = 0; j < index_count; j++) { - int index = index_rptr[j]; - ERR_FAIL_INDEX(index, vertex_count); - index_wptr[j] = vertex_remap[index]; - } - - new_surface[RS::ARRAY_INDEX] = new_indices; - - // Make sure the same LODs as the full version are used. - // This makes it more coherent between rendered model and its shadows. - for (int j = 0; j < surfaces[i].lods.size(); j++) { - indices = surfaces[i].lods[j].indices; - - index_count = indices.size(); - index_rptr = indices.ptr(); - new_indices.resize(indices.size()); - index_wptr = new_indices.ptrw(); - - for (int k = 0; k < index_count; k++) { - int index = index_rptr[j]; - ERR_FAIL_INDEX(index, vertex_count); - index_wptr[j] = vertex_remap[index]; - } - - lods[surfaces[i].lods[j].distance] = new_indices; - } - } - - shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name, surfaces[i].flags); - } -} - -Ref<EditorSceneImporterMesh> EditorSceneImporterMesh::get_shadow_mesh() const { - return shadow_mesh; -} - -void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) { - clear(); - if (p_data.has("blend_shape_names")) { - blend_shapes = p_data["blend_shape_names"]; - } - if (p_data.has("surfaces")) { - Array surface_arr = p_data["surfaces"]; - for (int i = 0; i < surface_arr.size(); i++) { - Dictionary s = surface_arr[i]; - ERR_CONTINUE(!s.has("primitive")); - ERR_CONTINUE(!s.has("arrays")); - Mesh::PrimitiveType prim = Mesh::PrimitiveType(int(s["primitive"])); - ERR_CONTINUE(prim >= Mesh::PRIMITIVE_MAX); - Array arr = s["arrays"]; - Dictionary lods; - String name; - if (s.has("name")) { - name = s["name"]; - } - if (s.has("lods")) { - lods = s["lods"]; - } - Array blend_shapes; - if (s.has("blend_shapes")) { - blend_shapes = s["blend_shapes"]; - } - Ref<Material> material; - if (s.has("material")) { - material = s["material"]; - } - uint32_t flags = 0; - if (s.has("flags")) { - flags = s["flags"]; - } - add_surface(prim, arr, blend_shapes, lods, material, name, flags); - } - } -} -Dictionary EditorSceneImporterMesh::_get_data() const { - Dictionary data; - if (blend_shapes.size()) { - data["blend_shape_names"] = blend_shapes; - } - Array surface_arr; - for (int i = 0; i < surfaces.size(); i++) { - Dictionary d; - d["primitive"] = surfaces[i].primitive; - d["arrays"] = surfaces[i].arrays; - if (surfaces[i].blend_shape_data.size()) { - Array bs_data; - for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) { - bs_data.push_back(surfaces[i].blend_shape_data[j].arrays); - } - d["blend_shapes"] = bs_data; - } - if (surfaces[i].lods.size()) { - Dictionary lods; - for (int j = 0; j < surfaces[i].lods.size(); j++) { - lods[surfaces[i].lods[j].distance] = surfaces[i].lods[j].indices; - } - d["lods"] = lods; - } - - if (surfaces[i].material.is_valid()) { - d["material"] = surfaces[i].material; - } - - if (surfaces[i].name != String()) { - d["name"] = surfaces[i].name; - } - - if (surfaces[i].flags != 0) { - d["flags"] = surfaces[i].flags; - } - - surface_arr.push_back(d); - } - data["surfaces"] = surface_arr; - return data; -} - -Vector<Face3> EditorSceneImporterMesh::get_faces() const { - Vector<Face3> faces; - for (int i = 0; i < surfaces.size(); i++) { - if (surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) { - Vector<Vector3> vertices = surfaces[i].arrays[Mesh::ARRAY_VERTEX]; - Vector<int> indices = surfaces[i].arrays[Mesh::ARRAY_INDEX]; - if (indices.size()) { - for (int j = 0; j < indices.size(); j += 3) { - Face3 f; - f.vertex[0] = vertices[indices[j + 0]]; - f.vertex[1] = vertices[indices[j + 1]]; - f.vertex[2] = vertices[indices[j + 2]]; - faces.push_back(f); - } - } else { - for (int j = 0; j < vertices.size(); j += 3) { - Face3 f; - f.vertex[0] = vertices[j + 0]; - f.vertex[1] = vertices[j + 1]; - f.vertex[2] = vertices[j + 2]; - faces.push_back(f); - } - } - } - } - - return faces; -} - -Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const { - ERR_FAIL_COND_V(!Mesh::convex_decomposition_function, Vector<Ref<Shape3D>>()); - - const Vector<Face3> faces = get_faces(); - int face_count = faces.size(); - - Vector<Vector3> vertices; - uint32_t vertex_count = 0; - vertices.resize(face_count * 3); - Vector<uint32_t> indices; - indices.resize(face_count * 3); - { - Map<Vector3, uint32_t> vertex_map; - Vector3 *vertex_w = vertices.ptrw(); - uint32_t *index_w = indices.ptrw(); - for (int i = 0; i < face_count; i++) { - for (int j = 0; j < 3; j++) { - const Vector3 &vertex = faces[i].vertex[j]; - Map<Vector3, uint32_t>::Element *found_vertex = vertex_map.find(vertex); - uint32_t index; - if (found_vertex) { - index = found_vertex->get(); - } else { - index = ++vertex_count; - vertex_map[vertex] = index; - vertex_w[index] = vertex; - } - index_w[i * 3 + j] = index; - } - } - } - vertices.resize(vertex_count); - - Vector<Vector<Vector3>> decomposed = Mesh::convex_decomposition_function((real_t *)vertices.ptr(), vertex_count, indices.ptr(), face_count, p_settings, nullptr); - - Vector<Ref<Shape3D>> ret; - - for (int i = 0; i < decomposed.size(); i++) { - Ref<ConvexPolygonShape3D> shape; - shape.instantiate(); - shape->set_points(decomposed[i]); - ret.push_back(shape); - } - - return ret; -} - -Ref<Shape3D> EditorSceneImporterMesh::create_trimesh_shape() const { - Vector<Face3> faces = get_faces(); - if (faces.size() == 0) { - return Ref<Shape3D>(); - } - - Vector<Vector3> face_points; - face_points.resize(faces.size() * 3); - - for (int i = 0; i < face_points.size(); i += 3) { - Face3 f = faces.get(i / 3); - face_points.set(i, f.vertex[0]); - face_points.set(i + 1, f.vertex[1]); - face_points.set(i + 2, f.vertex[2]); - } - - Ref<ConcavePolygonShape3D> shape = memnew(ConcavePolygonShape3D); - shape->set_faces(face_points); - return shape; -} - -Ref<NavigationMesh> EditorSceneImporterMesh::create_navigation_mesh() { - Vector<Face3> faces = get_faces(); - if (faces.size() == 0) { - return Ref<NavigationMesh>(); - } - - Map<Vector3, int> unique_vertices; - LocalVector<int> face_indices; - - for (int i = 0; i < faces.size(); i++) { - for (int j = 0; j < 3; j++) { - Vector3 v = faces[i].vertex[j]; - int idx; - if (unique_vertices.has(v)) { - idx = unique_vertices[v]; - } else { - idx = unique_vertices.size(); - unique_vertices[v] = idx; - } - face_indices.push_back(idx); - } - } - - Vector<Vector3> vertices; - vertices.resize(unique_vertices.size()); - for (Map<Vector3, int>::Element *E = unique_vertices.front(); E; E = E->next()) { - vertices.write[E->get()] = E->key(); - } - - Ref<NavigationMesh> nm; - nm.instantiate(); - nm->set_vertices(vertices); - - Vector<int> v3; - v3.resize(3); - for (uint32_t i = 0; i < face_indices.size(); i += 3) { - v3.write[0] = face_indices[i + 0]; - v3.write[1] = face_indices[i + 1]; - v3.write[2] = face_indices[i + 2]; - nm->add_polygon(v3); - } - - return nm; -} - -extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, const uint8_t *p_cache_data, bool *r_use_cache, uint8_t **r_mesh_cache, int *r_mesh_cache_size, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y); - -struct EditorSceneImporterMeshLightmapSurface { - Ref<Material> material; - LocalVector<SurfaceTool::Vertex> vertices; - Mesh::PrimitiveType primitive = Mesh::PrimitiveType::PRIMITIVE_MAX; - uint32_t format = 0; - String name; -}; - -Error EditorSceneImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache) { - ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); - ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes."); - - LocalVector<float> vertices; - LocalVector<float> normals; - LocalVector<int> indices; - LocalVector<float> uv; - LocalVector<Pair<int, int>> uv_indices; - - Vector<EditorSceneImporterMeshLightmapSurface> lightmap_surfaces; - - // Keep only the scale - Basis basis = p_base_transform.get_basis(); - Vector3 scale = Vector3(basis.get_axis(0).length(), basis.get_axis(1).length(), basis.get_axis(2).length()); - - Transform3D transform; - transform.scale(scale); - - Basis normal_basis = transform.basis.inverse().transposed(); - - for (int i = 0; i < get_surface_count(); i++) { - EditorSceneImporterMeshLightmapSurface s; - s.primitive = get_surface_primitive_type(i); - - ERR_FAIL_COND_V_MSG(s.primitive != Mesh::PRIMITIVE_TRIANGLES, ERR_UNAVAILABLE, "Only triangles are supported for lightmap unwrap."); - Array arrays = get_surface_arrays(i); - s.material = get_surface_material(i); - s.name = get_surface_name(i); - - SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices, &s.format); - - PackedVector3Array rvertices = arrays[Mesh::ARRAY_VERTEX]; - int vc = rvertices.size(); - - PackedVector3Array rnormals = arrays[Mesh::ARRAY_NORMAL]; - - int vertex_ofs = vertices.size() / 3; - - vertices.resize((vertex_ofs + vc) * 3); - normals.resize((vertex_ofs + vc) * 3); - uv_indices.resize(vertex_ofs + vc); - - for (int j = 0; j < vc; j++) { - Vector3 v = transform.xform(rvertices[j]); - Vector3 n = normal_basis.xform(rnormals[j]).normalized(); - - vertices[(j + vertex_ofs) * 3 + 0] = v.x; - vertices[(j + vertex_ofs) * 3 + 1] = v.y; - vertices[(j + vertex_ofs) * 3 + 2] = v.z; - normals[(j + vertex_ofs) * 3 + 0] = n.x; - normals[(j + vertex_ofs) * 3 + 1] = n.y; - normals[(j + vertex_ofs) * 3 + 2] = n.z; - uv_indices[j + vertex_ofs] = Pair<int, int>(i, j); - } - - PackedInt32Array rindices = arrays[Mesh::ARRAY_INDEX]; - int ic = rindices.size(); - - float eps = 1.19209290e-7F; // Taken from xatlas.h - if (ic == 0) { - for (int j = 0; j < vc / 3; j++) { - Vector3 p0 = transform.xform(rvertices[j * 3 + 0]); - Vector3 p1 = transform.xform(rvertices[j * 3 + 1]); - Vector3 p2 = transform.xform(rvertices[j * 3 + 2]); - - if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { - continue; - } - - indices.push_back(vertex_ofs + j * 3 + 0); - indices.push_back(vertex_ofs + j * 3 + 1); - indices.push_back(vertex_ofs + j * 3 + 2); - } - - } else { - for (int j = 0; j < ic / 3; j++) { - Vector3 p0 = transform.xform(rvertices[rindices[j * 3 + 0]]); - Vector3 p1 = transform.xform(rvertices[rindices[j * 3 + 1]]); - Vector3 p2 = transform.xform(rvertices[rindices[j * 3 + 2]]); - - if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { - continue; - } - - indices.push_back(vertex_ofs + rindices[j * 3 + 0]); - indices.push_back(vertex_ofs + rindices[j * 3 + 1]); - indices.push_back(vertex_ofs + rindices[j * 3 + 2]); - } - } - - lightmap_surfaces.push_back(s); - } - - //unwrap - - bool use_cache = true; // Used to request cache generation and to know if cache was used - uint8_t *gen_cache; - int gen_cache_size; - float *gen_uvs; - int *gen_vertices; - int *gen_indices; - int gen_vertex_count; - int gen_index_count; - int size_x; - int size_y; - - bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), p_src_cache.ptr(), &use_cache, &gen_cache, &gen_cache_size, &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y); - - if (!ok) { - return ERR_CANT_CREATE; - } - - //remove surfaces - clear(); - - //create surfacetools for each surface.. - LocalVector<Ref<SurfaceTool>> surfaces_tools; - - for (int i = 0; i < lightmap_surfaces.size(); i++) { - Ref<SurfaceTool> st; - st.instantiate(); - st->begin(Mesh::PRIMITIVE_TRIANGLES); - st->set_material(lightmap_surfaces[i].material); - st->set_meta("name", lightmap_surfaces[i].name); - surfaces_tools.push_back(st); //stay there - } - - print_verbose("Mesh: Gen indices: " + itos(gen_index_count)); - - //go through all indices - for (int i = 0; i < gen_index_count; i += 3) { - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], (int)uv_indices.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], (int)uv_indices.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], (int)uv_indices.size(), ERR_BUG); - - ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); - - int surface = uv_indices[gen_vertices[gen_indices[i + 0]]].first; - - for (int j = 0; j < 3; j++) { - SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second]; - - if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_COLOR) { - surfaces_tools[surface]->set_color(v.color); - } - if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_TEX_UV) { - surfaces_tools[surface]->set_uv(v.uv); - } - if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_NORMAL) { - surfaces_tools[surface]->set_normal(v.normal); - } - if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_TANGENT) { - Plane t; - t.normal = v.tangent; - t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; - surfaces_tools[surface]->set_tangent(t); - } - if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_BONES) { - surfaces_tools[surface]->set_bones(v.bones); - } - if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_WEIGHTS) { - surfaces_tools[surface]->set_weights(v.weights); - } - - Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); - surfaces_tools[surface]->set_uv2(uv2); - - surfaces_tools[surface]->add_vertex(v.vertex); - } - } - - //generate surfaces - for (unsigned int i = 0; i < surfaces_tools.size(); i++) { - surfaces_tools[i]->index(); - Array arrays = surfaces_tools[i]->commit_to_arrays(); - add_surface(surfaces_tools[i]->get_primitive(), arrays, Array(), Dictionary(), surfaces_tools[i]->get_material(), surfaces_tools[i]->get_meta("name")); - } - - set_lightmap_size_hint(Size2(size_x, size_y)); - - if (gen_cache_size > 0) { - r_dst_cache.resize(gen_cache_size); - memcpy(r_dst_cache.ptrw(), gen_cache, gen_cache_size); - memfree(gen_cache); - } - - if (!use_cache) { - // Cache was not used, free the buffers - memfree(gen_vertices); - memfree(gen_indices); - memfree(gen_uvs); - } - - return OK; -} - -void EditorSceneImporterMesh::set_lightmap_size_hint(const Size2i &p_size) { - lightmap_size_hint = p_size; -} - -Size2i EditorSceneImporterMesh::get_lightmap_size_hint() const { - return lightmap_size_hint; -} - -void EditorSceneImporterMesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &EditorSceneImporterMesh::add_blend_shape); - ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &EditorSceneImporterMesh::get_blend_shape_count); - ClassDB::bind_method(D_METHOD("get_blend_shape_name", "blend_shape_idx"), &EditorSceneImporterMesh::get_blend_shape_name); - - ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode); - ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode); - - ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name", "flags"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()), DEFVAL(0)); - - ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count); - ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type); - ClassDB::bind_method(D_METHOD("get_surface_name", "surface_idx"), &EditorSceneImporterMesh::get_surface_name); - ClassDB::bind_method(D_METHOD("get_surface_arrays", "surface_idx"), &EditorSceneImporterMesh::get_surface_arrays); - ClassDB::bind_method(D_METHOD("get_surface_blend_shape_arrays", "surface_idx", "blend_shape_idx"), &EditorSceneImporterMesh::get_surface_blend_shape_arrays); - ClassDB::bind_method(D_METHOD("get_surface_lod_count", "surface_idx"), &EditorSceneImporterMesh::get_surface_lod_count); - ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size); - ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices); - ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material); - ClassDB::bind_method(D_METHOD("get_surface_format", "surface_idx"), &EditorSceneImporterMesh::get_surface_format); - - ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &EditorSceneImporterMesh::set_surface_name); - ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &EditorSceneImporterMesh::set_surface_material); - - ClassDB::bind_method(D_METHOD("get_mesh", "base_mesh"), &EditorSceneImporterMesh::get_mesh, DEFVAL(Ref<ArrayMesh>())); - ClassDB::bind_method(D_METHOD("clear"), &EditorSceneImporterMesh::clear); - - ClassDB::bind_method(D_METHOD("_set_data", "data"), &EditorSceneImporterMesh::_set_data); - ClassDB::bind_method(D_METHOD("_get_data"), &EditorSceneImporterMesh::_get_data); - - ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &EditorSceneImporterMesh::set_lightmap_size_hint); - ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &EditorSceneImporterMesh::get_lightmap_size_hint); - - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); -} diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h deleted file mode 100644 index d32b1fdf74..0000000000 --- a/editor/import/scene_importer_mesh.h +++ /dev/null @@ -1,124 +0,0 @@ -/*************************************************************************/ -/* scene_importer_mesh.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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_SCENE_IMPORTER_MESH_H -#define EDITOR_SCENE_IMPORTER_MESH_H - -#include "core/io/resource.h" -#include "scene/resources/concave_polygon_shape_3d.h" -#include "scene/resources/convex_polygon_shape_3d.h" -#include "scene/resources/mesh.h" -#include "scene/resources/navigation_mesh.h" - -#include <cstdint> - -// The following classes are used by importers instead of ArrayMesh and MeshInstance3D -// so the data is not registered (hence, quality loss), importing happens faster and -// its easier to modify before saving - -class EditorSceneImporterMesh : public Resource { - GDCLASS(EditorSceneImporterMesh, Resource) - - struct Surface { - Mesh::PrimitiveType primitive; - Array arrays; - struct BlendShape { - Array arrays; - }; - Vector<BlendShape> blend_shape_data; - struct LOD { - Vector<int> indices; - float distance; - }; - Vector<LOD> lods; - Ref<Material> material; - String name; - uint32_t flags = 0; - }; - Vector<Surface> surfaces; - Vector<String> blend_shapes; - Mesh::BlendShapeMode blend_shape_mode = Mesh::BLEND_SHAPE_MODE_NORMALIZED; - - Ref<ArrayMesh> mesh; - - Ref<EditorSceneImporterMesh> shadow_mesh; - - Size2i lightmap_size_hint; - Basis compute_rotation_matrix_from_ortho_6d(Vector3 p_x_raw, Vector3 y_raw); - -protected: - void _set_data(const Dictionary &p_data); - Dictionary _get_data() const; - - static void _bind_methods(); - -public: - void add_blend_shape(const String &p_name); - int get_blend_shape_count() const; - String get_blend_shape_name(int p_blend_shape) const; - - void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String(), const uint32_t p_flags = 0); - int get_surface_count() const; - - void set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode); - Mesh::BlendShapeMode get_blend_shape_mode() const; - - Mesh::PrimitiveType get_surface_primitive_type(int p_surface); - String get_surface_name(int p_surface) const; - void set_surface_name(int p_surface, const String &p_name); - Array get_surface_arrays(int p_surface) const; - Array get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const; - int get_surface_lod_count(int p_surface) const; - Vector<int> get_surface_lod_indices(int p_surface, int p_lod) const; - float get_surface_lod_size(int p_surface, int p_lod) const; - Ref<Material> get_surface_material(int p_surface) const; - uint32_t get_surface_format(int p_surface) const; - - void set_surface_material(int p_surface, const Ref<Material> &p_material); - - void generate_lods(); - - void create_shadow_mesh(); - Ref<EditorSceneImporterMesh> get_shadow_mesh() const; - - Vector<Face3> get_faces() const; - Vector<Ref<Shape3D>> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const; - Ref<Shape3D> create_trimesh_shape() const; - Ref<NavigationMesh> create_navigation_mesh(); - Error lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache); - - void set_lightmap_size_hint(const Size2i &p_size); - Size2i get_lightmap_size_hint() const; - - bool has_mesh() const; - Ref<ArrayMesh> get_mesh(const Ref<ArrayMesh> &p_base = Ref<ArrayMesh>()); - void clear(); -}; -#endif // EDITOR_SCENE_IMPORTER_MESH_H diff --git a/editor/import/scene_importer_mesh_node_3d.cpp b/editor/import/scene_importer_mesh_node_3d.cpp deleted file mode 100644 index 3c201cf674..0000000000 --- a/editor/import/scene_importer_mesh_node_3d.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/*************************************************************************/ -/* scene_importer_mesh_node_3d.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "scene_importer_mesh_node_3d.h" - -void EditorSceneImporterMeshNode3D::set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh) { - mesh = p_mesh; -} -Ref<EditorSceneImporterMesh> EditorSceneImporterMeshNode3D::get_mesh() const { - return mesh; -} - -void EditorSceneImporterMeshNode3D::set_skin(const Ref<Skin> &p_skin) { - skin = p_skin; -} -Ref<Skin> EditorSceneImporterMeshNode3D::get_skin() const { - return skin; -} - -void EditorSceneImporterMeshNode3D::set_surface_material(int p_idx, const Ref<Material> &p_material) { - ERR_FAIL_COND(p_idx < 0); - if (p_idx >= surface_materials.size()) { - surface_materials.resize(p_idx + 1); - } - - surface_materials.write[p_idx] = p_material; -} -Ref<Material> EditorSceneImporterMeshNode3D::get_surface_material(int p_idx) const { - ERR_FAIL_COND_V(p_idx < 0, Ref<Material>()); - if (p_idx >= surface_materials.size()) { - return Ref<Material>(); - } - return surface_materials[p_idx]; -} - -void EditorSceneImporterMeshNode3D::set_skeleton_path(const NodePath &p_path) { - skeleton_path = p_path; -} -NodePath EditorSceneImporterMeshNode3D::get_skeleton_path() const { - return skeleton_path; -} - -void EditorSceneImporterMeshNode3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &EditorSceneImporterMeshNode3D::set_mesh); - ClassDB::bind_method(D_METHOD("get_mesh"), &EditorSceneImporterMeshNode3D::get_mesh); - - ClassDB::bind_method(D_METHOD("set_skin", "skin"), &EditorSceneImporterMeshNode3D::set_skin); - ClassDB::bind_method(D_METHOD("get_skin"), &EditorSceneImporterMeshNode3D::get_skin); - - ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &EditorSceneImporterMeshNode3D::set_skeleton_path); - ClassDB::bind_method(D_METHOD("get_skeleton_path"), &EditorSceneImporterMeshNode3D::get_skeleton_path); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "EditorSceneImporterMesh"), "set_mesh", "get_mesh"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path"); -} diff --git a/editor/import/scene_importer_mesh_node_3d.h b/editor/import/scene_importer_mesh_node_3d.h deleted file mode 100644 index dec1717c99..0000000000 --- a/editor/import/scene_importer_mesh_node_3d.h +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************/ -/* scene_importer_mesh_node_3d.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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_SCENE_IMPORTER_MESH_NODE_3D_H -#define EDITOR_SCENE_IMPORTER_MESH_NODE_3D_H - -#include "editor/import/scene_importer_mesh.h" -#include "scene/3d/node_3d.h" -#include "scene/resources/skin.h" - -class EditorSceneImporterMesh; - -class EditorSceneImporterMeshNode3D : public Node3D { - GDCLASS(EditorSceneImporterMeshNode3D, Node3D) - - Ref<EditorSceneImporterMesh> mesh; - Ref<Skin> skin; - NodePath skeleton_path; - Vector<Ref<Material>> surface_materials; - -protected: - static void _bind_methods(); - -public: - void set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh); - Ref<EditorSceneImporterMesh> get_mesh() const; - - void set_skin(const Ref<Skin> &p_skin); - Ref<Skin> get_skin() const; - - void set_surface_material(int p_idx, const Ref<Material> &p_material); - Ref<Material> get_surface_material(int p_idx) const; - - void set_skeleton_path(const NodePath &p_path); - NodePath get_skeleton_path() const; -}; -#endif |