diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/gdnative/gdnative.cpp | 20 | ||||
| -rw-r--r-- | modules/gdnative/gdnative_library_editor_plugin.cpp | 16 | ||||
| -rw-r--r-- | modules/gdnative/register_types.cpp | 108 | ||||
| -rw-r--r-- | modules/gdscript/editor/gdscript_translation_parser_plugin.cpp | 178 | ||||
| -rw-r--r-- | modules/gdscript/editor/gdscript_translation_parser_plugin.h | 57 | ||||
| -rw-r--r-- | modules/gdscript/register_types.cpp | 6 | ||||
| -rw-r--r-- | modules/gridmap/grid_map.cpp | 80 | ||||
| -rw-r--r-- | modules/gridmap/grid_map.h | 19 | ||||
| -rw-r--r-- | modules/gridmap/grid_map_editor_plugin.cpp | 57 | ||||
| -rw-r--r-- | modules/gridmap/grid_map_editor_plugin.h | 2 |
10 files changed, 432 insertions, 111 deletions
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 3d747ba41e..bb2da70c3a 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -291,8 +291,26 @@ bool GDNative::initialize() { return false; } #ifdef IPHONE_ENABLED - // on iOS we use static linking + // On iOS we use static linking by default. String path = ""; + + // On iOS dylibs is not allowed, but can be replaced with .framework or .xcframework. + // If they are used, we can run dlopen on them. + // They should be located under Frameworks directory, so we need to replace library path. + if (!lib_path.ends_with(".a")) { + path = ProjectSettings::get_singleton()->globalize_path(lib_path); + + if (!FileAccess::exists(path)) { + String lib_name = lib_path.get_basename().get_file(); + String framework_path_format = "Frameworks/$name.framework/$name"; + + Dictionary format_dict; + format_dict["name"] = lib_name; + String framework_path = framework_path_format.format(format_dict, "$_"); + + path = OS::get_singleton()->get_executable_path().get_base_dir().plus_file(framework_path); + } + } #elif defined(ANDROID_ENABLED) // On Android dynamic libraries are located separately from resource assets, // we should pass library name to dlopen(). The library name is flattened diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp index 5896da4640..1d4d188f23 100644 --- a/modules/gdnative/gdnative_library_editor_plugin.cpp +++ b/modules/gdnative/gdnative_library_editor_plugin.cpp @@ -127,15 +127,24 @@ void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) { String section = (id == BUTTON_SELECT_DEPENDENCES || id == BUTTON_CLEAR_DEPENDENCES) ? "dependencies" : "entry"; if (id == BUTTON_SELECT_LIBRARY || id == BUTTON_SELECT_DEPENDENCES) { + TreeItem *treeItem = Object::cast_to<TreeItem>(item)->get_parent(); EditorFileDialog::FileMode mode = EditorFileDialog::FILE_MODE_OPEN_FILE; if (id == BUTTON_SELECT_DEPENDENCES) { mode = EditorFileDialog::FILE_MODE_OPEN_FILES; + } else if (treeItem->get_text(0) == "iOS") { + mode = EditorFileDialog::FILE_MODE_OPEN_ANY; } file_dialog->set_meta("target", target); file_dialog->set_meta("section", section); file_dialog->clear_filters(); - file_dialog->add_filter(Object::cast_to<TreeItem>(item)->get_parent()->get_metadata(0)); + + String filter_string = treeItem->get_metadata(0); + Vector<String> filters = filter_string.split(",", false, 0); + for (int i = 0; i < filters.size(); i++) { + file_dialog->add_filter(filters[i]); + } + file_dialog->set_file_mode(mode); file_dialog->popup_centered_ratio(); @@ -309,7 +318,9 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { platform_ios.name = "iOS"; platform_ios.entries.push_back("armv7"); platform_ios.entries.push_back("arm64"); - platform_ios.library_extension = "*.dylib"; + // iOS can use both Static and Dynamic libraries. + // Frameworks is actually a folder with files. + platform_ios.library_extension = "*.framework; Framework, *.xcframework; Binary Framework, *.a; Static Library, *.dylib; Dynamic Library"; platforms["iOS"] = platform_ios; } @@ -360,6 +371,7 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { //file_dialog->set_resizable(true); add_child(file_dialog); file_dialog->connect("file_selected", callable_mp(this, &GDNativeLibraryEditor::_on_library_selected)); + file_dialog->connect("dir_selected", callable_mp(this, &GDNativeLibraryEditor::_on_library_selected)); file_dialog->connect("files_selected", callable_mp(this, &GDNativeLibraryEditor::_on_dependencies_selected)); new_architecture_dialog = memnew(ConfirmationDialog); diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 136af5bd1e..d1b1513ac3 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -142,47 +142,85 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty } } + // Add symbols for staticaly linked libraries on iOS if (p_features.has("iOS")) { - // Register symbols in the "fake" dynamic lookup table, because dlsym does not work well on iOS. - LibrarySymbol expected_symbols[] = { - { "gdnative_init", true }, - { "gdnative_terminate", false }, - { "nativescript_init", false }, - { "nativescript_frame", false }, - { "nativescript_thread_enter", false }, - { "nativescript_thread_exit", false }, - { "gdnative_singleton", false } - }; - String declare_pattern = "extern \"C\" void $name(void)$weak;\n"; - String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n" - "extern void add_ios_init_callback(void (*cb)());\n"; - String linker_flags = ""; - for (unsigned long i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) { - String full_name = lib->get_symbol_prefix() + expected_symbols[i].name; - String code = declare_pattern.replace("$name", full_name); - code = code.replace("$weak", expected_symbols[i].is_required ? "" : " __attribute__((weak))"); - additional_code += code; - - if (!expected_symbols[i].is_required) { - if (linker_flags.length() > 0) { - linker_flags += " "; + bool should_fake_dynamic = false; + + List<String> entry_keys; + config->get_section_keys("entry", &entry_keys); + + for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) { + String key = E->get(); + + Vector<String> tags = key.split("."); + + bool skip = false; + for (int i = 0; i < tags.size(); i++) { + bool has_feature = p_features.has(tags[i]); + + if (!has_feature) { + skip = true; + break; } - linker_flags += "-Wl,-U,_" + full_name; } - } - additional_code += String("void $prefixinit() {\n").replace("$prefix", lib->get_symbol_prefix()); - String register_pattern = " if (&$name) register_dynamic_symbol((char *)\"$name\", (void *)$name);\n"; - for (unsigned long i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) { - String full_name = lib->get_symbol_prefix() + expected_symbols[i].name; - additional_code += register_pattern.replace("$name", full_name); + if (skip) { + continue; + } + + String entry_lib_path = config->get_value("entry", key); + if (entry_lib_path.begins_with("res://") && entry_lib_path.ends_with(".a")) { + // If we find static library that was used for export + // we should add a fake loopup table. + // In case of dynamic library being used, + // this symbols will not cause any issues with library loading. + should_fake_dynamic = true; + break; + } } - additional_code += "}\n"; - additional_code += String("struct $prefixstruct {$prefixstruct() {add_ios_init_callback($prefixinit);}};\n").replace("$prefix", lib->get_symbol_prefix()); - additional_code += String("$prefixstruct $prefixstruct_instance;\n").replace("$prefix", lib->get_symbol_prefix()); - add_ios_cpp_code(additional_code); - add_ios_linker_flags(linker_flags); + if (should_fake_dynamic) { + // Register symbols in the "fake" dynamic lookup table, because dlsym does not work well on iOS. + LibrarySymbol expected_symbols[] = { + { "gdnative_init", true }, + { "gdnative_terminate", false }, + { "nativescript_init", false }, + { "nativescript_frame", false }, + { "nativescript_thread_enter", false }, + { "nativescript_thread_exit", false }, + { "gdnative_singleton", false } + }; + String declare_pattern = "extern \"C\" void $name(void)$weak;\n"; + String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n" + "extern void add_ios_init_callback(void (*cb)());\n"; + String linker_flags = ""; + for (unsigned long i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) { + String full_name = lib->get_symbol_prefix() + expected_symbols[i].name; + String code = declare_pattern.replace("$name", full_name); + code = code.replace("$weak", expected_symbols[i].is_required ? "" : " __attribute__((weak))"); + additional_code += code; + + if (!expected_symbols[i].is_required) { + if (linker_flags.length() > 0) { + linker_flags += " "; + } + linker_flags += "-Wl,-U,_" + full_name; + } + } + + additional_code += String("void $prefixinit() {\n").replace("$prefix", lib->get_symbol_prefix()); + String register_pattern = " if (&$name) register_dynamic_symbol((char *)\"$name\", (void *)$name);\n"; + for (unsigned long i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) { + String full_name = lib->get_symbol_prefix() + expected_symbols[i].name; + additional_code += register_pattern.replace("$name", full_name); + } + additional_code += "}\n"; + additional_code += String("struct $prefixstruct {$prefixstruct() {add_ios_init_callback($prefixinit);}};\n").replace("$prefix", lib->get_symbol_prefix()); + additional_code += String("$prefixstruct $prefixstruct_instance;\n").replace("$prefix", lib->get_symbol_prefix()); + + add_ios_cpp_code(additional_code); + add_ios_linker_flags(linker_flags); + } } } diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp new file mode 100644 index 0000000000..a1b18978fc --- /dev/null +++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp @@ -0,0 +1,178 @@ +/*************************************************************************/ +/* gdscript_translation_parser_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "gdscript_translation_parser_plugin.h" + +#include "core/io/resource_loader.h" +#include "modules/gdscript/gdscript.h" + +void GDScriptEditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { + GDScriptLanguage::get_singleton()->get_recognized_extensions(r_extensions); +} + +Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Vector<String> *r_extracted_strings) { + List<String> extensions; + get_recognized_extensions(&extensions); + bool extension_valid = false; + for (auto E = extensions.front(); E; E = E->next()) { + if (p_path.get_extension() == E->get()) { + extension_valid = true; + break; + } + } + + if (!extension_valid) { + Vector<String> temp; + for (auto E = extensions.front(); E; E = E->next()) { + temp.push_back(E->get()); + } + String valid_extensions = String(", ").join(temp); + ERR_PRINT("Argument p_path \"" + p_path + "\" has wrong extension. List of valid extensions: " + valid_extensions); + return ERR_INVALID_PARAMETER; + } + + Error err; + RES loaded_res = ResourceLoader::load(p_path, "", false, &err); + if (err) { + ERR_PRINT("Failed to load " + p_path); + return err; + } + + Ref<GDScript> gdscript = loaded_res; + parse_text(gdscript->get_source_code(), r_extracted_strings); + + return OK; +} + +void GDScriptEditorTranslationParserPlugin::parse_text(const String &p_text, Vector<String> *r_extracted_strings) { + // Parse and match all GDScript function API that involves translation string. + // E.g get_node("Label").text = "something", var test = tr("something"), "something" will be matched and collected. + + Vector<String> parsed_strings; + + // Search translation strings with RegEx. + regex.clear(); + regex.compile(String("|").join(patterns)); + Array results = regex.search_all(p_text); + _get_captured_strings(results, &parsed_strings); + + // Special handling for FileDialog. + Vector<String> temp; + _parse_file_dialog(p_text, &temp); + parsed_strings.append_array(temp); + + // Filter out / and + + String filter = "(?:\\\\\\n|\"[\\s\\\\]*\\+\\s*\")"; + regex.clear(); + regex.compile(filter); + for (int i = 0; i < parsed_strings.size(); i++) { + parsed_strings.set(i, regex.sub(parsed_strings[i], "", true)); + } + + r_extracted_strings->append_array(parsed_strings); +} + +void GDScriptEditorTranslationParserPlugin::_parse_file_dialog(const String &p_source_code, Vector<String> *r_output) { + // FileDialog API has the form .filters = PackedStringArray(["*.png ; PNG Images","*.gd ; GDScript Files"]). + // First filter: Get "*.png ; PNG Images", "*.gd ; GDScript Files" from PackedStringArray. + regex.clear(); + regex.compile(String("|").join(file_dialog_patterns)); + Array results = regex.search_all(p_source_code); + + Vector<String> temp; + _get_captured_strings(results, &temp); + String captured_strings = String(",").join(temp); + + // Second filter: Get the texts after semicolon from "*.png ; PNG Images","*.gd ; GDScript Files". + String second_filter = "\"[^;]+;" + text + "\""; + regex.clear(); + regex.compile(second_filter); + results = regex.search_all(captured_strings); + _get_captured_strings(results, r_output); + for (int i = 0; i < r_output->size(); i++) { + r_output->set(i, r_output->get(i).strip_edges()); + } +} + +void GDScriptEditorTranslationParserPlugin::_get_captured_strings(const Array &p_results, Vector<String> *r_output) { + Ref<RegExMatch> result; + for (int i = 0; i < p_results.size(); i++) { + result = p_results[i]; + for (int j = 0; j < result->get_group_count(); j++) { + String s = result->get_string(j + 1); + // Prevent reading text with only spaces. + if (!s.strip_edges().empty()) { + r_output->push_back(s); + } + } + } +} + +GDScriptEditorTranslationParserPlugin::GDScriptEditorTranslationParserPlugin() { + // Regex search pattern templates. + // The extra complication in the regex pattern is to ensure that the matching works when users write over multiple lines, use tabs etc. + const String dot = "\\.[\\s\\\\]*"; + const String str_assign_template = "[\\s\\\\]*=[\\s\\\\]*\"" + text + "\""; + const String first_arg_template = "[\\s\\\\]*\\([\\s\\\\]*\"" + text + "\"[\\s\\S]*?\\)"; + const String second_arg_template = "[\\s\\\\]*\\([\\s\\S]+?,[\\s\\\\]*\"" + text + "\"[\\s\\S]*?\\)"; + + // Common patterns. + patterns.push_back("tr" + first_arg_template); + patterns.push_back(dot + "text" + str_assign_template); + patterns.push_back(dot + "placeholder_text" + str_assign_template); + patterns.push_back(dot + "hint_tooltip" + str_assign_template); + patterns.push_back(dot + "set_text" + first_arg_template); + patterns.push_back(dot + "set_tooltip" + first_arg_template); + patterns.push_back(dot + "set_placeholder" + first_arg_template); + + // Tabs and TabContainer API. + patterns.push_back(dot + "set_tab_title" + second_arg_template); + patterns.push_back(dot + "add_tab" + first_arg_template); + + // PopupMenu API. + patterns.push_back(dot + "add_check_item" + first_arg_template); + patterns.push_back(dot + "add_icon_check_item" + second_arg_template); + patterns.push_back(dot + "add_icon_item" + second_arg_template); + patterns.push_back(dot + "add_icon_radio_check_item" + second_arg_template); + patterns.push_back(dot + "add_item" + first_arg_template); + patterns.push_back(dot + "add_multistate_item" + first_arg_template); + patterns.push_back(dot + "add_radio_check_item" + first_arg_template); + patterns.push_back(dot + "add_separator" + first_arg_template); + patterns.push_back(dot + "add_submenu_item" + first_arg_template); + patterns.push_back(dot + "set_item_text" + second_arg_template); + //patterns.push_back(dot + "set_item_tooltip" + second_arg_template); //no tr() behind this function. might be bug. + + // FileDialog API - special case. + const String fd_text = "((?:[\\s\\\\]*\"(?:[^\"\\\\]|\\\\[\\s\\S])*(?:\"[\\s\\\\]*\\+[\\s\\\\]*\"(?:[^\"\\\\]|\\\\[\\s\\S])*)*\"[\\s\\\\]*,?)*)"; + const String packed_string_array = "[\\s\\\\]*PackedStringArray[\\s\\\\]*\\([\\s\\\\]*\\[" + fd_text + "\\][\\s\\\\]*\\)"; + file_dialog_patterns.push_back(dot + "add_filter[\\s\\\\]*\\(" + fd_text + "[\\s\\\\]*\\)"); + file_dialog_patterns.push_back(dot + "filters[\\s\\\\]*=" + packed_string_array); + file_dialog_patterns.push_back(dot + "set_filters[\\s\\\\]*\\(" + packed_string_array + "[\\s\\\\]*\\)"); +} diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.h b/modules/gdscript/editor/gdscript_translation_parser_plugin.h new file mode 100644 index 0000000000..ef967845b9 --- /dev/null +++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* gdscript_translation_parser_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H +#define GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H + +#include "editor/editor_translation_parser.h" +#include "modules/regex/regex.h" + +class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlugin { + GDCLASS(GDScriptEditorTranslationParserPlugin, EditorTranslationParserPlugin); + + // Regex and search patterns that are used to match translation strings. + const String text = "((?:[^\"\\\\]|\\\\[\\s\\S])*(?:\"[\\s\\\\]*\\+[\\s\\\\]*\"(?:[^\"\\\\]|\\\\[\\s\\S])*)*)"; + RegEx regex; + Vector<String> patterns; + Vector<String> file_dialog_patterns; + + void _parse_file_dialog(const String &p_source_code, Vector<String> *r_output); + void _get_captured_strings(const Array &p_results, Vector<String> *r_output); + +public: + virtual Error parse_file(const String &p_path, Vector<String> *r_extracted_strings); + virtual void parse_text(const String &p_text, Vector<String> *r_extracted_strings); + virtual void get_recognized_extensions(List<String> *r_extensions) const; + + GDScriptEditorTranslationParserPlugin(); +}; + +#endif // GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 0625123530..53e760ffa7 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -46,7 +46,9 @@ Ref<ResourceFormatSaverGDScript> resource_saver_gd; #include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" +#include "editor/editor_translation_parser.h" #include "editor/gdscript_highlighter.h" +#include "editor/gdscript_translation_parser_plugin.h" #ifndef GDSCRIPT_NO_LSP #include "core/engine.h" @@ -164,6 +166,10 @@ void register_gdscript_types() { #ifdef TOOLS_ENABLED ScriptEditor::register_create_syntax_highlighter_function(GDScriptSyntaxHighlighter::create); EditorNode::add_init_callback(_editor_init); + + Ref<GDScriptEditorTranslationParserPlugin> gdscript_translation_parser_plugin; + gdscript_translation_parser_plugin.instance(); + EditorTranslationParser::get_singleton()->add_parser(gdscript_translation_parser_plugin, EditorTranslationParser::STANDARD); #endif // TOOLS_ENABLED } diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 2975a97bfe..ccf1e49693 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -244,26 +244,26 @@ bool GridMap::get_center_z() const { return center_z; } -void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { +void GridMap::set_cell_item(const Vector3i &p_position, int p_item, int p_rot) { if (baked_meshes.size() && !recreating_octants) { //if you set a cell item, baked meshes go good bye clear_baked_meshes(); _recreate_octant_data(); } - ERR_FAIL_INDEX(ABS(p_x), 1 << 20); - ERR_FAIL_INDEX(ABS(p_y), 1 << 20); - ERR_FAIL_INDEX(ABS(p_z), 1 << 20); + ERR_FAIL_INDEX(ABS(p_position.x), 1 << 20); + ERR_FAIL_INDEX(ABS(p_position.y), 1 << 20); + ERR_FAIL_INDEX(ABS(p_position.z), 1 << 20); IndexKey key; - key.x = p_x; - key.y = p_y; - key.z = p_z; + key.x = p_position.x; + key.y = p_position.y; + key.z = p_position.z; OctantKey ok; - ok.x = p_x / octant_size; - ok.y = p_y / octant_size; - ok.z = p_z / octant_size; + ok.x = p_position.x / octant_size; + ok.y = p_position.y / octant_size; + ok.z = p_position.z / octant_size; if (p_item < 0) { //erase @@ -318,15 +318,15 @@ void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { cell_map[key] = c; } -int GridMap::get_cell_item(int p_x, int p_y, int p_z) const { - ERR_FAIL_INDEX_V(ABS(p_x), 1 << 20, INVALID_CELL_ITEM); - ERR_FAIL_INDEX_V(ABS(p_y), 1 << 20, INVALID_CELL_ITEM); - ERR_FAIL_INDEX_V(ABS(p_z), 1 << 20, INVALID_CELL_ITEM); +int GridMap::get_cell_item(const Vector3i &p_position) const { + ERR_FAIL_INDEX_V(ABS(p_position.x), 1 << 20, INVALID_CELL_ITEM); + ERR_FAIL_INDEX_V(ABS(p_position.y), 1 << 20, INVALID_CELL_ITEM); + ERR_FAIL_INDEX_V(ABS(p_position.z), 1 << 20, INVALID_CELL_ITEM); IndexKey key; - key.x = p_x; - key.y = p_y; - key.z = p_z; + key.x = p_position.x; + key.y = p_position.y; + key.z = p_position.z; if (!cell_map.has(key)) { return INVALID_CELL_ITEM; @@ -334,15 +334,15 @@ int GridMap::get_cell_item(int p_x, int p_y, int p_z) const { return cell_map[key].item; } -int GridMap::get_cell_item_orientation(int p_x, int p_y, int p_z) const { - ERR_FAIL_INDEX_V(ABS(p_x), 1 << 20, -1); - ERR_FAIL_INDEX_V(ABS(p_y), 1 << 20, -1); - ERR_FAIL_INDEX_V(ABS(p_z), 1 << 20, -1); +int GridMap::get_cell_item_orientation(const Vector3i &p_position) const { + ERR_FAIL_INDEX_V(ABS(p_position.x), 1 << 20, -1); + ERR_FAIL_INDEX_V(ABS(p_position.y), 1 << 20, -1); + ERR_FAIL_INDEX_V(ABS(p_position.z), 1 << 20, -1); IndexKey key; - key.x = p_x; - key.y = p_y; - key.z = p_z; + key.x = p_position.x; + key.y = p_position.y; + key.z = p_position.z; if (!cell_map.has(key)) { return -1; @@ -350,20 +350,20 @@ int GridMap::get_cell_item_orientation(int p_x, int p_y, int p_z) const { return cell_map[key].rot; } -Vector3 GridMap::world_to_map(const Vector3 &p_world_pos) const { - Vector3 map_pos = p_world_pos / cell_size; - map_pos.x = floor(map_pos.x); - map_pos.y = floor(map_pos.y); - map_pos.z = floor(map_pos.z); - return map_pos; +Vector3i GridMap::world_to_map(const Vector3 &p_world_position) const { + Vector3 map_position = p_world_position / cell_size; + map_position.x = floor(map_position.x); + map_position.y = floor(map_position.y); + map_position.z = floor(map_position.z); + return Vector3i(map_position); } -Vector3 GridMap::map_to_world(int p_x, int p_y, int p_z) const { +Vector3 GridMap::map_to_world(const Vector3i &p_map_position) const { Vector3 offset = _get_offset(); Vector3 world_pos( - p_x * cell_size.x + offset.x, - p_y * cell_size.y + offset.y, - p_z * cell_size.z + offset.z); + p_map_position.x * cell_size.x + offset.x, + p_map_position.y * cell_size.y + offset.y, + p_map_position.z * cell_size.z + offset.z); return world_pos; } @@ -725,7 +725,7 @@ void GridMap::_recreate_octant_data() { Map<IndexKey, Cell> cell_copy = cell_map; _clear_internal(); for (Map<IndexKey, Cell>::Element *E = cell_copy.front(); E; E = E->next()) { - set_cell_item(E->key().x, E->key().y, E->key().z, E->get().item, E->get().rot); + set_cell_item(Vector3i(E->key()), E->get().item, E->get().rot); } recreating_octants = false; } @@ -799,12 +799,12 @@ void GridMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_octant_size", "size"), &GridMap::set_octant_size); ClassDB::bind_method(D_METHOD("get_octant_size"), &GridMap::get_octant_size); - ClassDB::bind_method(D_METHOD("set_cell_item", "x", "y", "z", "item", "orientation"), &GridMap::set_cell_item, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("get_cell_item", "x", "y", "z"), &GridMap::get_cell_item); - ClassDB::bind_method(D_METHOD("get_cell_item_orientation", "x", "y", "z"), &GridMap::get_cell_item_orientation); + ClassDB::bind_method(D_METHOD("set_cell_item", "position", "item", "orientation"), &GridMap::set_cell_item, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("get_cell_item", "position"), &GridMap::get_cell_item); + ClassDB::bind_method(D_METHOD("get_cell_item_orientation", "position"), &GridMap::get_cell_item_orientation); - ClassDB::bind_method(D_METHOD("world_to_map", "pos"), &GridMap::world_to_map); - ClassDB::bind_method(D_METHOD("map_to_world", "x", "y", "z"), &GridMap::map_to_world); + ClassDB::bind_method(D_METHOD("world_to_map", "world_position"), &GridMap::world_to_map); + ClassDB::bind_method(D_METHOD("map_to_world", "map_position"), &GridMap::map_to_world); ClassDB::bind_method(D_METHOD("_update_octants_callback"), &GridMap::_update_octants_callback); ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &GridMap::resource_changed); diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index 9eb9aee7d1..ca7429ea26 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -59,6 +59,15 @@ class GridMap : public Node3D { return key < p_key.key; } + _FORCE_INLINE_ operator Vector3i() const { + return Vector3i(x, y, z); + } + + IndexKey(Vector3i p_vector) { + x = (int16_t)p_vector.x; + y = (int16_t)p_vector.y; + z = (int16_t)p_vector.z; + } IndexKey() { key = 0; } }; @@ -234,12 +243,12 @@ public: void set_center_z(bool p_enable); bool get_center_z() const; - void set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot = 0); - int get_cell_item(int p_x, int p_y, int p_z) const; - int get_cell_item_orientation(int p_x, int p_y, int p_z) const; + void set_cell_item(const Vector3i &p_position, int p_item, int p_rot = 0); + int get_cell_item(const Vector3i &p_position) const; + int get_cell_item_orientation(const Vector3i &p_position) const; - Vector3 world_to_map(const Vector3 &p_world_pos) const; - Vector3 map_to_world(int p_x, int p_y, int p_z) const; + Vector3i world_to_map(const Vector3 &p_world_position) const; + Vector3 map_to_world(const Vector3i &p_map_position) const; void set_clip(bool p_enabled, bool p_clip_above = true, int p_floor = 0, Vector3::Axis p_axis = Vector3::AXIS_X); diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 1b7ce98721..0e6ec7f520 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -291,15 +291,15 @@ void GridMapEditor::_update_selection_transform() { } else { Vector3 scale = (selection.end - selection.begin + Vector3(1, 1, 1)); scale[edit_axis] = 1.0; - Vector3 pos = selection.begin; - pos[edit_axis] = edit_floor[edit_axis]; + Vector3 position = selection.begin; + position[edit_axis] = edit_floor[edit_axis]; scale *= node->get_cell_size(); - pos *= node->get_cell_size(); + position *= node->get_cell_size(); Transform xf2; xf2.basis.scale(scale); - xf2.origin = pos; + xf2.origin = position; RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); } @@ -414,11 +414,11 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b } if (input_action == INPUT_PASTE) { - paste_indicator.current = Vector3(cell[0], cell[1], cell[2]); + paste_indicator.current = Vector3i(cell[0], cell[1], cell[2]); _update_paste_indicator(); } else if (input_action == INPUT_SELECT) { - selection.current = Vector3(cell[0], cell[1], cell[2]); + selection.current = Vector3i(cell[0], cell[1], cell[2]); if (p_click) { selection.click = selection.current; } @@ -427,7 +427,7 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b return true; } else if (input_action == INPUT_PICK) { - int item = node->get_cell_item(cell[0], cell[1], cell[2]); + int item = node->get_cell_item(Vector3i(cell[0], cell[1], cell[2])); if (item >= 0) { selected_palette = item; mesh_library_palette->set_current(item); @@ -438,23 +438,23 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b } if (input_action == INPUT_PAINT) { SetItem si; - si.pos = Vector3(cell[0], cell[1], cell[2]); + si.position = Vector3i(cell[0], cell[1], cell[2]); si.new_value = selected_palette; si.new_orientation = cursor_rot; - si.old_value = node->get_cell_item(cell[0], cell[1], cell[2]); - si.old_orientation = node->get_cell_item_orientation(cell[0], cell[1], cell[2]); + si.old_value = node->get_cell_item(Vector3i(cell[0], cell[1], cell[2])); + si.old_orientation = node->get_cell_item_orientation(Vector3i(cell[0], cell[1], cell[2])); set_items.push_back(si); - node->set_cell_item(cell[0], cell[1], cell[2], selected_palette, cursor_rot); + node->set_cell_item(Vector3i(cell[0], cell[1], cell[2]), selected_palette, cursor_rot); return true; } else if (input_action == INPUT_ERASE) { SetItem si; - si.pos = Vector3(cell[0], cell[1], cell[2]); + si.position = Vector3i(cell[0], cell[1], cell[2]); si.new_value = -1; si.new_orientation = 0; - si.old_value = node->get_cell_item(cell[0], cell[1], cell[2]); - si.old_orientation = node->get_cell_item_orientation(cell[0], cell[1], cell[2]); + si.old_value = node->get_cell_item(Vector3i(cell[0], cell[1], cell[2])); + si.old_orientation = node->get_cell_item_orientation(Vector3i(cell[0], cell[1], cell[2])); set_items.push_back(si); - node->set_cell_item(cell[0], cell[1], cell[2], -1); + node->set_cell_item(Vector3i(cell[0], cell[1], cell[2]), -1); return true; } @@ -470,8 +470,9 @@ void GridMapEditor::_delete_selection() { for (int i = selection.begin.x; i <= selection.end.x; i++) { for (int j = selection.begin.y; j <= selection.end.y; j++) { for (int k = selection.begin.z; k <= selection.end.z; k++) { - undo_redo->add_do_method(node, "set_cell_item", i, j, k, GridMap::INVALID_CELL_ITEM); - undo_redo->add_undo_method(node, "set_cell_item", i, j, k, node->get_cell_item(i, j, k), node->get_cell_item_orientation(i, j, k)); + Vector3i selected = Vector3i(i, j, k); + undo_redo->add_do_method(node, "set_cell_item", selected, GridMap::INVALID_CELL_ITEM); + undo_redo->add_undo_method(node, "set_cell_item", selected, node->get_cell_item(selected), node->get_cell_item_orientation(selected)); } } } @@ -489,8 +490,9 @@ void GridMapEditor::_fill_selection() { for (int i = selection.begin.x; i <= selection.end.x; i++) { for (int j = selection.begin.y; j <= selection.end.y; j++) { for (int k = selection.begin.z; k <= selection.end.z; k++) { - undo_redo->add_do_method(node, "set_cell_item", i, j, k, selected_palette, cursor_rot); - undo_redo->add_undo_method(node, "set_cell_item", i, j, k, node->get_cell_item(i, j, k), node->get_cell_item_orientation(i, j, k)); + Vector3i selected = Vector3i(i, j, k); + undo_redo->add_do_method(node, "set_cell_item", selected, selected_palette, cursor_rot); + undo_redo->add_undo_method(node, "set_cell_item", selected, node->get_cell_item(selected), node->get_cell_item_orientation(selected)); } } } @@ -515,7 +517,8 @@ void GridMapEditor::_set_clipboard_data() { for (int i = selection.begin.x; i <= selection.end.x; i++) { for (int j = selection.begin.y; j <= selection.end.y; j++) { for (int k = selection.begin.z; k <= selection.end.z; k++) { - int itm = node->get_cell_item(i, j, k); + Vector3i selected = Vector3i(i, j, k); + int itm = node->get_cell_item(selected); if (itm == GridMap::INVALID_CELL_ITEM) { continue; } @@ -524,8 +527,8 @@ void GridMapEditor::_set_clipboard_data() { ClipboardItem item; item.cell_item = itm; - item.grid_offset = Vector3(i, j, k) - selection.begin; - item.orientation = node->get_cell_item_orientation(i, j, k); + item.grid_offset = Vector3(selected) - selection.begin; + item.orientation = node->get_cell_item_orientation(selected); item.instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world_3d()->get_scenario()); clipboard_items.push_back(item); @@ -583,14 +586,14 @@ void GridMapEditor::_do_paste() { for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) { ClipboardItem &item = E->get(); - Vector3 pos = rot.xform(item.grid_offset) + paste_indicator.begin + ofs; + Vector3 position = rot.xform(item.grid_offset) + paste_indicator.begin + ofs; Basis orm; orm.set_orthogonal_index(item.orientation); orm = rot * orm; - undo_redo->add_do_method(node, "set_cell_item", pos.x, pos.y, pos.z, item.cell_item, orm.get_orthogonal_index()); - undo_redo->add_undo_method(node, "set_cell_item", pos.x, pos.y, pos.z, node->get_cell_item(pos.x, pos.y, pos.z), node->get_cell_item_orientation(pos.x, pos.y, pos.z)); + undo_redo->add_do_method(node, "set_cell_item", position, item.cell_item, orm.get_orthogonal_index()); + undo_redo->add_undo_method(node, "set_cell_item", position, node->get_cell_item(position), node->get_cell_item_orientation(position)); } if (reselect) { @@ -667,11 +670,11 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In undo_redo->create_action(TTR("GridMap Paint")); for (List<SetItem>::Element *E = set_items.front(); E; E = E->next()) { const SetItem &si = E->get(); - undo_redo->add_do_method(node, "set_cell_item", si.pos.x, si.pos.y, si.pos.z, si.new_value, si.new_orientation); + undo_redo->add_do_method(node, "set_cell_item", si.position, si.new_value, si.new_orientation); } for (List<SetItem>::Element *E = set_items.back(); E; E = E->prev()) { const SetItem &si = E->get(); - undo_redo->add_undo_method(node, "set_cell_item", si.pos.x, si.pos.y, si.pos.z, si.old_value, si.old_orientation); + undo_redo->add_undo_method(node, "set_cell_item", si.position, si.old_value, si.old_orientation); } undo_redo->commit_action(); diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index 31a01cdc91..84b68ba6e7 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -84,7 +84,7 @@ class GridMapEditor : public VBoxContainer { Label *spin_box_label; struct SetItem { - Vector3 pos; + Vector3i position; int new_value; int new_orientation; int old_value; |