diff options
1167 files changed, 46524 insertions, 25819 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0911ff98bf..b8082fb136 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -51,12 +51,14 @@ doc_classes/* @godotengine/documentation # Editor /editor/*debugger* @godotengine/debugger +/editor/gui/ @godotengine/usability @godotengine/gui-nodes /editor/icons/ @godotengine/usability /editor/import/ @godotengine/import /editor/plugins/*2d_*.* @godotengine/2d-editor /editor/plugins/*3d_*.* @godotengine/3d-editor /editor/plugins/script_*.* @godotengine/script-editor /editor/plugins/*shader*.* @godotengine/shaders +/editor/themes/ @godotengine/usability @godotengine/gui-nodes /editor/code_editor.* @godotengine/script-editor /editor/*dock*.* @godotengine/docks /editor/*shader*.* @godotengine/shaders diff --git a/.github/actions/godot-build/action.yml b/.github/actions/godot-build/action.yml index 377480b123..0a0899db78 100644 --- a/.github/actions/godot-build/action.yml +++ b/.github/actions/godot-build/action.yml @@ -31,6 +31,18 @@ runs: SCONS_CACHE_LIMIT: ${{ inputs.scons-cache-limit }} run: | echo "Building with flags:" platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }} - if [ "${{ inputs.target }}" != "editor" ]; then rm -rf editor; fi # Ensure we don't include editor code. + + if [ "${{ inputs.target }}" != "editor" ]; then + # Ensure we don't include editor code in export template builds. + rm -rf editor + fi + + if [ "${{ github.event.number }}" != "" ]; then + # Set build identifier with pull request number if available. This is displayed throughout the editor. + export BUILD_NAME="gh-${{ github.event.number }}" + else + export BUILD_NAME="gh" + fi + scons platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }} ls -l bin/ diff --git a/.github/workflows/web_builds.yml b/.github/workflows/web_builds.yml index d314991fee..9524b5260b 100644 --- a/.github/workflows/web_builds.yml +++ b/.github/workflows/web_builds.yml @@ -17,7 +17,24 @@ concurrency: jobs: web-template: runs-on: "ubuntu-22.04" - name: Template (target=template_release) + name: ${{ matrix.name }} + strategy: + fail-fast: false + matrix: + include: + - name: Template w/ threads (target=template_release, threads=yes) + cache-name: web-template + target: template_release + sconsflags: threads=yes + tests: false + artifact: true + + - name: Template w/o threads (target=template_release, threads=no) + cache-name: web-nothreads-template + target: template_release + sconsflags: threads=no + tests: false + artifact: true steps: - uses: actions/checkout@v4 @@ -34,6 +51,8 @@ jobs: - name: Setup Godot build cache uses: ./.github/actions/godot-cache + with: + cache-name: ${{ matrix.cache-name }} continue-on-error: true - name: Setup python and scons @@ -42,10 +61,13 @@ jobs: - name: Compilation uses: ./.github/actions/godot-build with: - sconsflags: ${{ env.SCONSFLAGS }} + sconsflags: ${{ env.SCONSFLAGS }} ${{ matrix.sconsflags }} platform: web - target: template_release - tests: false + target: ${{ matrix.target }} + tests: ${{ matrix.tests }} - name: Upload artifact uses: ./.github/actions/upload-artifact + if: ${{ matrix.artifact }} + with: + name: ${{ matrix.cache-name }} diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 4b8a246df0..625aac8c13 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -483,7 +483,7 @@ License: Expat Files: ./thirdparty/thorvg/ Comment: ThorVG -Copyright: 2020-2023, The ThorVG Project +Copyright: 2020-2024, The ThorVG Project License: Expat Files: ./thirdparty/tinyexr/ @@ -508,7 +508,6 @@ Comment: Vulkan Headers Copyright: 2014-2023, The Khronos Group Inc. 2014-2023, Valve Corporation 2014-2023, LunarG, Inc. - 2015-2023, Google Inc. License: Apache-2.0 Files: ./thirdparty/vulkan/vk_mem_alloc.h diff --git a/SConstruct b/SConstruct index c7b9d5bc86..6a4dea2c09 100644 --- a/SConstruct +++ b/SConstruct @@ -183,6 +183,7 @@ opts.Add(BoolVariable("separate_debug_symbols", "Extract debugging symbols to a opts.Add(EnumVariable("lto", "Link-time optimization (production builds)", "none", ("none", "auto", "thin", "full"))) opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False)) opts.Add(BoolVariable("generate_apk", "Generate an APK/AAB after building Android library by calling Gradle", False)) +opts.Add(BoolVariable("threads", "Enable threading support", True)) # Components opts.Add(BoolVariable("deprecated", "Enable compatibility code for deprecated and removed features", True)) @@ -832,6 +833,10 @@ if selected_platform in platform_list: suffix += ".double" suffix += "." + env["arch"] + + if not env["threads"]: + suffix += ".nothreads" + suffix += env.extra_suffix sys.path.remove(tmppath) @@ -972,6 +977,9 @@ if selected_platform in platform_list: env.Tool("compilation_db") env.Alias("compiledb", env.CompilationDatabase()) + if env["threads"]: + env.Append(CPPDEFINES=["THREADS_ENABLED"]) + Export("env") # Build subdirs, the build order is dependent on link order. diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 56e041be1b..90e2e27320 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1393,8 +1393,8 @@ ProjectSettings::ProjectSettings() { // - Have a 16:9 aspect ratio, // - Have both dimensions divisible by 8 to better play along with video recording, // - Be displayable correctly in windowed mode on a 1366×768 display (tested on Windows 10 with default settings). - GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/viewport_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 1152); // 8K resolution - GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/viewport_height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 648); // 8K resolution + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/viewport_width", PROPERTY_HINT_RANGE, "1,7680,1,or_greater"), 1152); // 8K resolution + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/viewport_height", PROPERTY_HINT_RANGE, "1,4320,1,or_greater"), 648); // 8K resolution GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen,Exclusive Fullscreen"), 0); @@ -1410,8 +1410,8 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("display/window/size/extend_to_title", false); GLOBAL_DEF("display/window/size/no_focus", false); - GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 0); // 8K resolution - GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution + GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "1,7680,1,or_greater"), 0); // 8K resolution + GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "1,4320,1,or_greater"), 0); // 8K resolution GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true); GLOBAL_DEF("display/window/energy_saving/keep_screen_on.editor", false); @@ -1462,7 +1462,6 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("debug/settings/crash_handler/message.editor", String("Please include this when reporting the bug on: https://github.com/godotengine/godot/issues")); GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), 2); - GLOBAL_DEF(PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1"), 60); // No negative and limit to 500 due to crashes. GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false); GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "internationalization/rendering/root_node_layout_direction", PROPERTY_HINT_ENUM, "Based on Application Locale,Left-to-Right,Right-to-Left,Based on System Locale"), 0); @@ -1471,11 +1470,11 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true); GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true); - GLOBAL_DEF("rendering/rendering_device/staging_buffer/block_size_kb", 256); - GLOBAL_DEF("rendering/rendering_device/staging_buffer/max_size_mb", 128); - GLOBAL_DEF("rendering/rendering_device/staging_buffer/texture_upload_region_size_px", 64); - GLOBAL_DEF("rendering/rendering_device/pipeline_cache/save_chunk_size_mb", 3.0); - GLOBAL_DEF("rendering/rendering_device/vulkan/max_descriptors_per_pool", 64); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/block_size_kb", PROPERTY_HINT_RANGE, "4,2048,1,or_greater"), 256); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/max_size_mb", PROPERTY_HINT_RANGE, "1,1024,1,or_greater"), 128); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/texture_upload_region_size_px", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/rendering_device/pipeline_cache/save_chunk_size_mb", PROPERTY_HINT_RANGE, "0.000001,64.0,0.001,or_greater"), 3.0); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/vulkan/max_descriptors_per_pool", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64); GLOBAL_DEF_RST("rendering/rendering_device/d3d12/max_resource_descriptors_per_frame", 16384); custom_prop_info["rendering/rendering_device/d3d12/max_resource_descriptors_per_frame"] = PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/max_resource_descriptors_per_frame", PROPERTY_HINT_RANGE, "512,262144"); @@ -1484,6 +1483,8 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF_RST("rendering/rendering_device/d3d12/max_misc_descriptors_per_frame", 512); custom_prop_info["rendering/rendering_device/d3d12/max_misc_descriptors_per_frame"] = PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/max_misc_descriptors_per_frame", PROPERTY_HINT_RANGE, "32,4096"); + GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version"), 610); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), 1); GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"), 0); diff --git a/core/core_bind.cpp b/core/core_bind.cpp index d91c659d1e..e5363f9acc 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1040,6 +1040,10 @@ Vector<Vector3> Geometry3D::clip_polygon(const Vector<Vector3> &p_points, const return ::Geometry3D::clip_polygon(p_points, p_plane); } +Vector<int32_t> Geometry3D::tetrahedralize_delaunay(const Vector<Vector3> &p_points) { + return ::Geometry3D::tetrahedralize_delaunay(p_points); +} + void Geometry3D::_bind_methods() { ClassDB::bind_method(D_METHOD("compute_convex_mesh_points", "planes"), &Geometry3D::compute_convex_mesh_points); ClassDB::bind_method(D_METHOD("build_box_planes", "extents"), &Geometry3D::build_box_planes); @@ -1061,6 +1065,7 @@ void Geometry3D::_bind_methods() { ClassDB::bind_method(D_METHOD("segment_intersects_convex", "from", "to", "planes"), &Geometry3D::segment_intersects_convex); ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &Geometry3D::clip_polygon); + ClassDB::bind_method(D_METHOD("tetrahedralize_delaunay", "points"), &Geometry3D::tetrahedralize_delaunay); } ////// Marshalls ////// @@ -1370,11 +1375,11 @@ Variant ClassDB::instantiate(const StringName &p_class) const { } } -bool ClassDB::class_has_signal(StringName p_class, StringName p_signal) const { +bool ClassDB::class_has_signal(const StringName &p_class, const StringName &p_signal) const { return ::ClassDB::has_signal(p_class, p_signal); } -Dictionary ClassDB::class_get_signal(StringName p_class, StringName p_signal) const { +Dictionary ClassDB::class_get_signal(const StringName &p_class, const StringName &p_signal) const { MethodInfo signal; if (::ClassDB::get_signal(p_class, p_signal, &signal)) { return signal.operator Dictionary(); @@ -1383,7 +1388,7 @@ Dictionary ClassDB::class_get_signal(StringName p_class, StringName p_signal) co } } -TypedArray<Dictionary> ClassDB::class_get_signal_list(StringName p_class, bool p_no_inheritance) const { +TypedArray<Dictionary> ClassDB::class_get_signal_list(const StringName &p_class, bool p_no_inheritance) const { List<MethodInfo> signals; ::ClassDB::get_signal_list(p_class, &signals, p_no_inheritance); TypedArray<Dictionary> ret; @@ -1395,7 +1400,7 @@ TypedArray<Dictionary> ClassDB::class_get_signal_list(StringName p_class, bool p return ret; } -TypedArray<Dictionary> ClassDB::class_get_property_list(StringName p_class, bool p_no_inheritance) const { +TypedArray<Dictionary> ClassDB::class_get_property_list(const StringName &p_class, bool p_no_inheritance) const { List<PropertyInfo> plist; ::ClassDB::get_property_list(p_class, &plist, p_no_inheritance); TypedArray<Dictionary> ret; @@ -1423,11 +1428,11 @@ Error ClassDB::class_set_property(Object *p_object, const StringName &p_property return OK; } -bool ClassDB::class_has_method(StringName p_class, StringName p_method, bool p_no_inheritance) const { +bool ClassDB::class_has_method(const StringName &p_class, const StringName &p_method, bool p_no_inheritance) const { return ::ClassDB::has_method(p_class, p_method, p_no_inheritance); } -TypedArray<Dictionary> ClassDB::class_get_method_list(StringName p_class, bool p_no_inheritance) const { +TypedArray<Dictionary> ClassDB::class_get_method_list(const StringName &p_class, bool p_no_inheritance) const { List<MethodInfo> methods; ::ClassDB::get_method_list(p_class, &methods, p_no_inheritance); TypedArray<Dictionary> ret; @@ -1508,7 +1513,7 @@ StringName ClassDB::class_get_integer_constant_enum(const StringName &p_class, c return ::ClassDB::get_integer_constant_enum(p_class, p_name, p_no_inheritance); } -bool ClassDB::is_class_enabled(StringName p_class) const { +bool ClassDB::is_class_enabled(const StringName &p_class) const { return ::ClassDB::is_class_enabled(p_class); } @@ -1718,6 +1723,16 @@ bool Engine::is_printing_error_messages() const { return ::Engine::get_singleton()->is_printing_error_messages(); } +void Engine::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + String pf = p_function; + if (p_idx == 0 && (pf == "has_singleton" || pf == "get_singleton" || pf == "unregister_singleton")) { + for (const String &E : get_singleton_list()) { + r_options->push_back(E.quote()); + } + } + Object::get_argument_options(p_function, p_idx, r_options); +} + void Engine::_bind_methods() { ClassDB::bind_method(D_METHOD("set_physics_ticks_per_second", "physics_ticks_per_second"), &Engine::set_physics_ticks_per_second); ClassDB::bind_method(D_METHOD("get_physics_ticks_per_second"), &Engine::get_physics_ticks_per_second); diff --git a/core/core_bind.h b/core/core_bind.h index 715e26cf23..94d95f2ce9 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -337,6 +337,7 @@ public: Vector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const TypedArray<Plane> &p_planes); Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane); + Vector<int32_t> tetrahedralize_delaunay(const Vector<Vector3> &p_points); Geometry3D() { singleton = this; } }; @@ -434,17 +435,17 @@ public: bool can_instantiate(const StringName &p_class) const; Variant instantiate(const StringName &p_class) const; - bool class_has_signal(StringName p_class, StringName p_signal) const; - Dictionary class_get_signal(StringName p_class, StringName p_signal) const; - TypedArray<Dictionary> class_get_signal_list(StringName p_class, bool p_no_inheritance = false) const; + bool class_has_signal(const StringName &p_class, const StringName &p_signal) const; + Dictionary class_get_signal(const StringName &p_class, const StringName &p_signal) const; + TypedArray<Dictionary> class_get_signal_list(const StringName &p_class, bool p_no_inheritance = false) const; - TypedArray<Dictionary> class_get_property_list(StringName p_class, bool p_no_inheritance = false) const; + TypedArray<Dictionary> class_get_property_list(const StringName &p_class, bool p_no_inheritance = false) const; Variant class_get_property(Object *p_object, const StringName &p_property) const; Error class_set_property(Object *p_object, const StringName &p_property, const Variant &p_value) const; - bool class_has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false) const; + bool class_has_method(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false) const; - TypedArray<Dictionary> class_get_method_list(StringName p_class, bool p_no_inheritance = false) const; + TypedArray<Dictionary> class_get_method_list(const StringName &p_class, bool p_no_inheritance = false) const; PackedStringArray class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const; bool class_has_integer_constant(const StringName &p_class, const StringName &p_name) const; @@ -455,7 +456,7 @@ public: PackedStringArray class_get_enum_constants(const StringName &p_class, const StringName &p_enum, bool p_no_inheritance = false) const; StringName class_get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false) const; - bool is_class_enabled(StringName p_class) const; + bool is_class_enabled(const StringName &p_class) const; ClassDB() {} ~ClassDB() {} @@ -527,6 +528,8 @@ public: void set_print_error_messages(bool p_enabled); bool is_printing_error_messages() const; + virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; + Engine() { singleton = this; } }; diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 2f70fdf219..3b96fc20c6 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -845,7 +845,7 @@ bool CoreConstants::is_global_enum(const StringName &p_enum) { return _global_enums.has(p_enum); } -void CoreConstants::get_enum_values(StringName p_enum, HashMap<StringName, int64_t> *p_values) { +void CoreConstants::get_enum_values(const StringName &p_enum, HashMap<StringName, int64_t> *p_values) { ERR_FAIL_NULL_MSG(p_values, "Trying to get enum values with null map."); ERR_FAIL_COND_MSG(!_global_enums.has(p_enum), "Trying to get values of non-existing enum."); for (const _CoreConstant &constant : _global_enums[p_enum]) { diff --git a/core/core_constants.h b/core/core_constants.h index 51842490c8..82d626c749 100644 --- a/core/core_constants.h +++ b/core/core_constants.h @@ -45,7 +45,7 @@ public: static bool is_global_constant(const StringName &p_name); static int get_global_constant_index(const StringName &p_name); static bool is_global_enum(const StringName &p_enum); - static void get_enum_values(StringName p_enum, HashMap<StringName, int64_t> *p_values); + static void get_enum_values(const StringName &p_enum, HashMap<StringName, int64_t> *p_values); }; #endif // CORE_CONSTANTS_H diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index 32dc060aa2..0cce44d02f 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -162,7 +162,7 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve singleton_script_debugger->set_skip_breakpoints(p_skip_breakpoints); for (int i = 0; i < p_breakpoints.size(); i++) { - String bp = p_breakpoints[i]; + const String &bp = p_breakpoints[i]; int sp = bp.rfind(":"); ERR_CONTINUE_MSG(sp == -1, "Invalid breakpoint: '" + bp + "', expected file:line format."); diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index a817ea871d..d3b0039e72 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -36,6 +36,7 @@ #include "core/debugger/engine_profiler.h" #include "core/debugger/script_debugger.h" #include "core/input/input.h" +#include "core/io/resource_loader.h" #include "core/object/script_language.h" #include "core/os/os.h" @@ -435,9 +436,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { messages.insert(Thread::get_caller_id(), List<Message>()); } - mutex.lock(); while (is_peer_connected()) { - mutex.unlock(); flush_output(); _poll_messages(); @@ -515,8 +514,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { _send_stack_vars(globals, globals_vals, 2); } else if (command == "reload_scripts") { + script_paths_to_reload = data; + } else if (command == "reload_all_scripts") { reload_all_scripts = true; - } else if (command == "breakpoint") { ERR_FAIL_COND(data.size() < 3); bool set = data[2]; @@ -591,19 +591,36 @@ void RemoteDebugger::poll_events(bool p_is_idle) { } // Reload scripts during idle poll only. - if (p_is_idle && reload_all_scripts) { - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - ScriptServer::get_language(i)->reload_all_scripts(); + if (p_is_idle) { + if (reload_all_scripts) { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptServer::get_language(i)->reload_all_scripts(); + } + reload_all_scripts = false; + } else if (!script_paths_to_reload.is_empty()) { + Array scripts_to_reload; + for (int i = 0; i < script_paths_to_reload.size(); ++i) { + String path = script_paths_to_reload[i]; + Error err = OK; + Ref<Script> script = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); + ERR_CONTINUE_MSG(err != OK, vformat("Could not reload script '%s': %s", path, error_names[err])); + ERR_CONTINUE_MSG(script.is_null(), vformat("Could not reload script '%s': Not a script!", path, error_names[err])); + scripts_to_reload.push_back(script); + } + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptServer::get_language(i)->reload_scripts(scripts_to_reload, true); + } } - reload_all_scripts = false; + script_paths_to_reload.clear(); } } Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bool &r_captured) { r_captured = true; if (p_cmd == "reload_scripts") { + script_paths_to_reload = p_data; + } else if (p_cmd == "reload_all_scripts") { reload_all_scripts = true; - } else if (p_cmd == "breakpoint") { ERR_FAIL_COND_V(p_data.size() < 3, ERR_INVALID_DATA); bool set = p_data[2]; diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index 7c399178c6..519a90e7cc 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -74,6 +74,7 @@ private: int warn_count = 0; int last_reset = 0; bool reload_all_scripts = false; + Array script_paths_to_reload; // Make handlers and send_message thread safe. Mutex mutex; diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 2bac1f6592..ce01531b5c 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -666,12 +666,12 @@ void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExte HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions; -void GDExtension::register_interface_function(StringName p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) { +void GDExtension::register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) { ERR_FAIL_COND_MSG(gdextension_interface_functions.has(p_function_name), "Attempt to register interface function '" + p_function_name + "', which appears to be already registered."); gdextension_interface_functions.insert(p_function_name, p_function_pointer); } -GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(StringName p_function_name) { +GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(const StringName &p_function_name) { GDExtensionInterfaceFunctionPtr *function = gdextension_interface_functions.getptr(p_function_name); ERR_FAIL_NULL_V_MSG(function, nullptr, "Attempt to get non-existent interface function: " + String(p_function_name) + "."); return *function; @@ -715,10 +715,8 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb #endif Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, true, &library_path); - if (err != OK) { - ERR_PRINT("GDExtension dynamic library not found: " + abs_path); - return err; - } + ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + abs_path); + ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + abs_path); #if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) // If we copied the file, let's change the library path to point at the original, diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h index 0d20b8e50c..0b39581751 100644 --- a/core/extension/gdextension.h +++ b/core/extension/gdextension.h @@ -154,8 +154,8 @@ public: void initialize_library(InitializationLevel p_level); void deinitialize_library(InitializationLevel p_level); - static void register_interface_function(StringName p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer); - static GDExtensionInterfaceFunctionPtr get_interface_function(StringName p_function_name); + static void register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer); + static GDExtensionInterfaceFunctionPtr get_interface_function(const StringName &p_function_name); static void initialize_gdextensions(); static void finalize_gdextensions(); diff --git a/core/input/input.cpp b/core/input/input.cpp index 8f976cbaa3..2ba4b1d1e8 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -198,6 +198,7 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S r_options->push_back(name.quote()); } } + Object::get_argument_options(p_function, p_idx, r_options); } void Input::VelocityTrack::update(const Vector2 &p_delta_p) { @@ -1518,7 +1519,7 @@ void Input::add_joy_mapping(String p_mapping, bool p_update_existing) { parse_mapping(p_mapping); if (p_update_existing) { Vector<String> entry = p_mapping.split(","); - String uid = entry[0]; + const String &uid = entry[0]; for (KeyValue<int, Joypad> &E : joy_names) { Joypad &joy = E.value; if (joy.uid == uid) { diff --git a/core/input/input_builders.py b/core/input/input_builders.py index e98e2441e2..94c566493e 100644 --- a/core/input/input_builders.py +++ b/core/input/input_builders.py @@ -45,10 +45,10 @@ def make_default_controller_mappings(target, source, env): platform_mappings[current_platform][guid] = line platform_variables = { - "Linux": "#if LINUXBSD_ENABLED", + "Linux": "#ifdef LINUXBSD_ENABLED", "Windows": "#ifdef WINDOWS_ENABLED", "Mac OS X": "#ifdef MACOS_ENABLED", - "Android": "#if defined(__ANDROID__)", + "Android": "#ifdef ANDROID_ENABLED", "iOS": "#ifdef IOS_ENABLED", "Web": "#ifdef WEB_ENABLED", } diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 78b9ada884..70041ecfd6 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -754,7 +754,7 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur String fullname = E.key; Vector<String> split = fullname.split("."); - String name = split[0]; + const String &name = split[0]; String override_for = split.size() > 1 ? split[1] : String(); if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) { @@ -766,7 +766,7 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur String fullname = E.key; Vector<String> split = fullname.split("."); - String name = split[0]; + const String &name = split[0]; String override_for = split.size() > 1 ? split[1] : String(); if (builtins_with_overrides.has(name) && override_for.is_empty()) { diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 265d9ef56c..5a4d6dd099 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -491,7 +491,7 @@ PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) { } for (int i = 0; i < paths.size(); i++) { - String p = paths[i]; + const String &p = paths[i]; if (p == ".") { continue; } else if (p == "..") { diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 09505ea05d..833fd1adc3 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -73,7 +73,7 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) { Array keys = p_dict.keys(); for (int i = 0; i < keys.size(); ++i) { String encoded_key = String(keys[i]).uri_encode(); - Variant value = p_dict[keys[i]]; + const Variant &value = p_dict[keys[i]]; switch (value.get_type()) { case Variant::ARRAY: { // Repeat the key with every values diff --git a/core/io/image.cpp b/core/io/image.cpp index c72064e4f7..9aa7c9794a 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -3013,6 +3013,7 @@ void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) { } ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_png_mem_unpacker_func = nullptr; ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; diff --git a/core/io/image.h b/core/io/image.h index a21d05187b..be308b0ac1 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -145,6 +145,7 @@ public: }; static ImageMemLoadFunc _png_mem_loader_func; + static ImageMemLoadFunc _png_mem_unpacker_func; static ImageMemLoadFunc _jpg_mem_loader_func; static ImageMemLoadFunc _webp_mem_loader_func; static ImageMemLoadFunc _tga_mem_loader_func; @@ -312,8 +313,8 @@ public: Error save_jpg(const String &p_path, float p_quality = 0.75) const; Vector<uint8_t> save_png_to_buffer() const; Vector<uint8_t> save_jpg_to_buffer(float p_quality = 0.75) const; - Vector<uint8_t> save_exr_to_buffer(bool p_grayscale) const; - Error save_exr(const String &p_path, bool p_grayscale) const; + Vector<uint8_t> save_exr_to_buffer(bool p_grayscale = false) const; + Error save_exr(const String &p_path, bool p_grayscale = false) const; Error save_webp(const String &p_path, const bool p_lossy = false, const float p_quality = 0.75f) const; Vector<uint8_t> save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const; diff --git a/platform/macos/export/plist.cpp b/core/io/plist.cpp index f494c58fc9..86737609bf 100644 --- a/platform/macos/export/plist.cpp +++ b/core/io/plist.cpp @@ -448,7 +448,9 @@ PList::PList() { } PList::PList(const String &p_string) { - load_string(p_string); + String err_str; + bool ok = load_string(p_string, err_str); + ERR_FAIL_COND_MSG(!ok, "PList: " + err_str); } uint64_t PList::read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size) { @@ -642,11 +644,15 @@ bool PList::load_file(const String &p_filename) { String ret; ret.parse_utf8((const char *)array.ptr(), array.size()); - return load_string(ret); + String err_str; + bool ok = load_string(ret, err_str); + ERR_FAIL_COND_V_MSG(!ok, false, "PList: " + err_str); + + return true; } } -bool PList::load_string(const String &p_string) { +bool PList::load_string(const String &p_string, String &r_err_out) { root = Ref<PListNode>(); int pos = 0; @@ -657,14 +663,16 @@ bool PList::load_string(const String &p_string) { while (pos >= 0) { int open_token_s = p_string.find("<", pos); if (open_token_s == -1) { - ERR_FAIL_V_MSG(false, "PList: Unexpected end of data. No tags found."); + r_err_out = "Unexpected end of data. No tags found."; + return false; } int open_token_e = p_string.find(">", open_token_s); pos = open_token_e; String token = p_string.substr(open_token_s + 1, open_token_e - open_token_s - 1); if (token.is_empty()) { - ERR_FAIL_V_MSG(false, "PList: Invalid token name."); + r_err_out = "Invalid token name."; + return false; } String value; if (token[0] == '?' || token[0] == '!') { // Skip <?xml ... ?> and <!DOCTYPE ... > @@ -684,7 +692,8 @@ bool PList::load_string(const String &p_string) { } if (!in_plist) { - ERR_FAIL_V_MSG(false, "PList: Node outside of <plist> tag."); + r_err_out = "Node outside of <plist> tag."; + return false; } if (token == "dict") { @@ -693,13 +702,15 @@ bool PList::load_string(const String &p_string) { Ref<PListNode> dict = PListNode::new_dict(); dict->data_type = PList::PLNodeType::PL_NODE_TYPE_DICT; if (!stack.back()->get()->push_subnode(dict, key)) { - ERR_FAIL_V_MSG(false, "PList: Can't push subnode, invalid parent type."); + r_err_out = "Can't push subnode, invalid parent type."; + return false; } stack.push_back(dict); } else { // Add root node. if (!root.is_null()) { - ERR_FAIL_V_MSG(false, "PList: Root node already set."); + r_err_out = "Root node already set."; + return false; } Ref<PListNode> dict = PListNode::new_dict(); stack.push_back(dict); @@ -711,7 +722,8 @@ bool PList::load_string(const String &p_string) { if (token == "/dict") { // Exit current dict. if (stack.is_empty() || stack.back()->get()->data_type != PList::PLNodeType::PL_NODE_TYPE_DICT) { - ERR_FAIL_V_MSG(false, "PList: Mismatched </dict> tag."); + r_err_out = "Mismatched </dict> tag."; + return false; } stack.pop_back(); continue; @@ -722,13 +734,15 @@ bool PList::load_string(const String &p_string) { // Add subnode end enter it. Ref<PListNode> arr = PListNode::new_array(); if (!stack.back()->get()->push_subnode(arr, key)) { - ERR_FAIL_V_MSG(false, "PList: Can't push subnode, invalid parent type."); + r_err_out = "Can't push subnode, invalid parent type."; + return false; } stack.push_back(arr); } else { // Add root node. if (!root.is_null()) { - ERR_FAIL_V_MSG(false, "PList: Root node already set."); + r_err_out = "Root node already set."; + return false; } Ref<PListNode> arr = PListNode::new_array(); stack.push_back(arr); @@ -740,7 +754,8 @@ bool PList::load_string(const String &p_string) { if (token == "/array") { // Exit current array. if (stack.is_empty() || stack.back()->get()->data_type != PList::PLNodeType::PL_NODE_TYPE_ARRAY) { - ERR_FAIL_V_MSG(false, "PList: Mismatched </array> tag."); + r_err_out = "Mismatched </array> tag."; + return false; } stack.pop_back(); continue; @@ -751,13 +766,15 @@ bool PList::load_string(const String &p_string) { } else { int end_token_s = p_string.find("</", pos); if (end_token_s == -1) { - ERR_FAIL_V_MSG(false, vformat("PList: Mismatched <%s> tag.", token)); + r_err_out = vformat("Mismatched <%s> tag.", token); + return false; } int end_token_e = p_string.find(">", end_token_s); pos = end_token_e; String end_token = p_string.substr(end_token_s + 2, end_token_e - end_token_s - 2); if (end_token != token) { - ERR_FAIL_V_MSG(false, vformat("PList: Mismatched <%s> and <%s> token pair.", token, end_token)); + r_err_out = vformat("Mismatched <%s> and <%s> token pair.", token, end_token); + return false; } value = p_string.substr(open_token_e + 1, end_token_s - open_token_e - 1); } @@ -780,15 +797,18 @@ bool PList::load_string(const String &p_string) { } else if (token == "date") { var = PListNode::new_date(value); } else { - ERR_FAIL_V_MSG(false, "PList: Invalid value type."); + r_err_out = vformat("Invalid value type: %s.", token); + return false; } if (stack.is_empty() || !stack.back()->get()->push_subnode(var, key)) { - ERR_FAIL_V_MSG(false, "PList: Can't push subnode, invalid parent type."); + r_err_out = "Can't push subnode, invalid parent type."; + return false; } } } if (!stack.is_empty() || !done_plist) { - ERR_FAIL_V_MSG(false, "PList: Unexpected end of data. Root node is not closed."); + r_err_out = "Unexpected end of data. Root node is not closed."; + return false; } return true; } diff --git a/platform/macos/export/plist.h b/core/io/plist.h index 28b02e4eb7..7d8b8ef0b4 100644 --- a/platform/macos/export/plist.h +++ b/core/io/plist.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef MACOS_PLIST_H -#define MACOS_PLIST_H +#ifndef PLIST_H +#define PLIST_H // Property list file format (application/x-plist) parser, property list ASN-1 serialization. @@ -75,7 +75,7 @@ public: PList(const String &p_string); bool load_file(const String &p_filename); - bool load_string(const String &p_string); + bool load_string(const String &p_string, String &r_err_out); PackedByteArray save_asn1() const; String save_text() const; @@ -125,4 +125,4 @@ public: ~PListNode() {} }; -#endif // MACOS_PLIST_H +#endif // PLIST_H diff --git a/core/io/resource.cpp b/core/io/resource.cpp index 04ecabaf27..daa57be76f 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -204,7 +204,58 @@ void Resource::reload_from_file() { copy_from(s); } -Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache) { +void Resource::_dupe_sub_resources(Variant &r_variant, Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache) { + switch (r_variant.get_type()) { + case Variant::ARRAY: { + Array a = r_variant; + for (int i = 0; i < a.size(); i++) { + _dupe_sub_resources(a[i], p_for_scene, p_remap_cache); + } + } break; + case Variant::DICTIONARY: { + Dictionary d = r_variant; + List<Variant> keys; + d.get_key_list(&keys); + for (Variant &k : keys) { + if (k.get_type() == Variant::OBJECT) { + // Replace in dictionary key. + Ref<Resource> sr = k; + if (sr.is_valid() && sr->is_local_to_scene()) { + if (p_remap_cache.has(sr)) { + d[p_remap_cache[sr]] = d[k]; + d.erase(k); + } else { + Ref<Resource> dupe = sr->duplicate_for_local_scene(p_for_scene, p_remap_cache); + d[dupe] = d[k]; + d.erase(k); + p_remap_cache[sr] = dupe; + } + } + } else { + _dupe_sub_resources(k, p_for_scene, p_remap_cache); + } + + _dupe_sub_resources(d[k], p_for_scene, p_remap_cache); + } + } break; + case Variant::OBJECT: { + Ref<Resource> sr = r_variant; + if (sr.is_valid() && sr->is_local_to_scene()) { + if (p_remap_cache.has(sr)) { + r_variant = p_remap_cache[sr]; + } else { + Ref<Resource> dupe = sr->duplicate_for_local_scene(p_for_scene, p_remap_cache); + r_variant = dupe; + p_remap_cache[sr] = dupe; + } + } + } break; + default: { + } + } +} + +Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache) { List<PropertyInfo> plist; get_property_list(&plist); @@ -217,21 +268,9 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref if (!(E.usage & PROPERTY_USAGE_STORAGE)) { continue; } - Variant p = get(E.name); - if (p.get_type() == Variant::OBJECT) { - Ref<Resource> sr = p; - if (sr.is_valid()) { - if (sr->is_local_to_scene()) { - if (remap_cache.has(sr)) { - p = remap_cache[sr]; - } else { - Ref<Resource> dupe = sr->duplicate_for_local_scene(p_for_scene, remap_cache); - p = dupe; - remap_cache[sr] = dupe; - } - } - } - } + Variant p = get(E.name).duplicate(true); + + _dupe_sub_resources(p, p_for_scene, p_remap_cache); r->set(E.name, p); } @@ -239,7 +278,35 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref return r; } -void Resource::configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache) { +void Resource::_find_sub_resources(const Variant &p_variant, HashSet<Ref<Resource>> &p_resources_found) { + switch (p_variant.get_type()) { + case Variant::ARRAY: { + Array a = p_variant; + for (int i = 0; i < a.size(); i++) { + _find_sub_resources(a[i], p_resources_found); + } + } break; + case Variant::DICTIONARY: { + Dictionary d = p_variant; + List<Variant> keys; + d.get_key_list(&keys); + for (const Variant &k : keys) { + _find_sub_resources(k, p_resources_found); + _find_sub_resources(d[k], p_resources_found); + } + } break; + case Variant::OBJECT: { + Ref<Resource> r = p_variant; + if (r.is_valid()) { + p_resources_found.insert(r); + } + } break; + default: { + } + } +} + +void Resource::configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache) { List<PropertyInfo> plist; get_property_list(&plist); @@ -251,14 +318,15 @@ void Resource::configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource continue; } Variant p = get(E.name); - if (p.get_type() == Variant::OBJECT) { - Ref<Resource> sr = p; - if (sr.is_valid()) { - if (sr->is_local_to_scene()) { - if (!remap_cache.has(sr)) { - sr->configure_for_local_scene(p_for_scene, remap_cache); - remap_cache[sr] = sr; - } + + HashSet<Ref<Resource>> sub_resources; + _find_sub_resources(p, sub_resources); + + for (Ref<Resource> sr : sub_resources) { + if (sr->is_local_to_scene()) { + if (!p_remap_cache.has(sr)) { + sr->configure_for_local_scene(p_for_scene, p_remap_cache); + p_remap_cache[sr] = sr; } } } diff --git a/core/io/resource.h b/core/io/resource.h index 610c2150db..b885b773ac 100644 --- a/core/io/resource.h +++ b/core/io/resource.h @@ -74,6 +74,9 @@ private: SelfList<Resource> remapped_list; + void _dupe_sub_resources(Variant &r_variant, Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache); + void _find_sub_resources(const Variant &p_variant, HashSet<Ref<Resource>> &p_resources_found); + protected: virtual void _resource_path_changed(); static void _bind_methods(); @@ -111,8 +114,8 @@ public: String get_scene_unique_id() const; virtual Ref<Resource> duplicate(bool p_subresources = false) const; - Ref<Resource> duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache); - void configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache); + Ref<Resource> duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache); + void configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache); void set_local_to_scene(bool p_enable); bool is_local_to_scene() const; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 0c7764392a..ba11d84bce 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -340,7 +340,7 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { if (load_task.resource.is_valid()) { if (load_task.cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { - load_task.resource->set_path(load_task.local_path, load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE); + load_task.resource->set_path(load_task.local_path); } else if (!load_task.local_path.is_resource_file()) { load_task.resource->set_path_cache(load_task.local_path); } @@ -361,17 +361,6 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { if (_loaded_callback) { _loaded_callback(load_task.resource, load_task.local_path); } - } else if (load_task.cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { - Ref<Resource> existing = ResourceCache::get_ref(load_task.local_path); - if (existing.is_valid()) { - load_task.resource = existing; - load_task.status = THREAD_LOAD_LOADED; - load_task.progress = 1.0; - - if (_loaded_callback) { - _loaded_callback(load_task.resource, load_task.local_path); - } - } } thread_load_mutex.unlock(); @@ -474,7 +463,7 @@ Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path, load_task.type_hint = p_type_hint; load_task.cache_mode = p_cache_mode; load_task.use_sub_threads = p_thread_mode == LOAD_THREAD_DISTRIBUTE; - if (p_cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE) { + if (p_cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { Ref<Resource> existing = ResourceCache::get_ref(local_path); if (existing.is_valid()) { //referencing is fine @@ -641,15 +630,16 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro if (load_task.task_id != 0) { // Loading thread is in the worker pool. - load_task.awaited = true; thread_load_mutex.unlock(); Error err = WorkerThreadPool::get_singleton()->wait_for_task_completion(load_task.task_id); if (err == ERR_BUSY) { - // The WorkerThreadPool has scheduled tasks in a way that the current load depends on - // another one in a lower stack frame. Restart such load here. When the stack is eventually - // unrolled, the original load will have been notified to go on. + // The WorkerThreadPool has reported that the current task wants to await on an older one. + // That't not allowed for safety, to avoid deadlocks. Fortunately, though, in the context of + // resource loading that means that the task to wait for can be restarted here to break the + // cycle, with as much recursion into this process as needed. + // When the stack is eventually unrolled, the original load will have been notified to go on. #ifdef DEV_ENABLED - print_verbose("ResourceLoader: Load task happened to wait on another one deep in the call stack. Attempting to avoid deadlock by re-issuing the load now."); + print_verbose("ResourceLoader: Potential for deadlock detected in task dependency. Attempting to avoid it by re-issuing the load now."); #endif // CACHE_MODE_IGNORE is needed because, otherwise, the new request would just see there's // an ongoing load for that resource and wait for it again. This value forces a new load. @@ -663,6 +653,7 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro } else { DEV_ASSERT(err == OK); thread_load_mutex.lock(); + load_task.awaited = true; } } else { // Loading thread is main or user thread. diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index 1c6c18b015..51ebea7f2c 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -120,9 +120,8 @@ Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, String local_path = ProjectSettings::get_singleton()->localize_path(path); - Ref<Resource> rwcopy = p_resource; if (p_flags & FLAG_CHANGE_PATH) { - rwcopy->set_path(local_path); + p_resource->set_path(local_path); } err = saver[i]->save(p_resource, path, p_flags); @@ -139,7 +138,7 @@ Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, #endif if (p_flags & FLAG_CHANGE_PATH) { - rwcopy->set_path(old_path); + p_resource->set_path(old_path); } if (save_callback && path.begins_with("res://")) { diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index f0f160940d..fb54058bd9 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -69,7 +69,7 @@ void AStar3D::add_point(int64_t p_id, const Vector3 &p_pos, real_t p_weight_scal } Vector3 AStar3D::get_point_position(int64_t p_id) const { - Point *p; + Point *p = nullptr; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_V_MSG(!p_exists, Vector3(), vformat("Can't get point's position. Point with id: %d doesn't exist.", p_id)); @@ -77,7 +77,7 @@ Vector3 AStar3D::get_point_position(int64_t p_id) const { } void AStar3D::set_point_position(int64_t p_id, const Vector3 &p_pos) { - Point *p; + Point *p = nullptr; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's position. Point with id: %d doesn't exist.", p_id)); @@ -85,7 +85,7 @@ void AStar3D::set_point_position(int64_t p_id, const Vector3 &p_pos) { } real_t AStar3D::get_point_weight_scale(int64_t p_id) const { - Point *p; + Point *p = nullptr; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_V_MSG(!p_exists, 0, vformat("Can't get point's weight scale. Point with id: %d doesn't exist.", p_id)); @@ -93,7 +93,7 @@ real_t AStar3D::get_point_weight_scale(int64_t p_id) const { } void AStar3D::set_point_weight_scale(int64_t p_id, real_t p_weight_scale) { - Point *p; + Point *p = nullptr; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's weight scale. Point with id: %d doesn't exist.", p_id)); ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't set point's weight scale less than 0.0: %f.", p_weight_scale)); @@ -102,7 +102,7 @@ void AStar3D::set_point_weight_scale(int64_t p_id, real_t p_weight_scale) { } void AStar3D::remove_point(int64_t p_id) { - Point *p; + Point *p = nullptr; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_MSG(!p_exists, vformat("Can't remove point. Point with id: %d doesn't exist.", p_id)); @@ -130,11 +130,11 @@ void AStar3D::remove_point(int64_t p_id) { void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) { ERR_FAIL_COND_MSG(p_id == p_with_id, vformat("Can't connect point with id: %d to itself.", p_id)); - Point *a; + Point *a = nullptr; bool from_exists = points.lookup(p_id, a); ERR_FAIL_COND_MSG(!from_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_id)); - Point *b; + Point *b = nullptr; bool to_exists = points.lookup(p_with_id, b); ERR_FAIL_COND_MSG(!to_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_with_id)); @@ -166,11 +166,11 @@ void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional } void AStar3D::disconnect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) { - Point *a; + Point *a = nullptr; bool a_exists = points.lookup(p_id, a); ERR_FAIL_COND_MSG(!a_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_id)); - Point *b; + Point *b = nullptr; bool b_exists = points.lookup(p_with_id, b); ERR_FAIL_COND_MSG(!b_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_with_id)); @@ -220,7 +220,7 @@ PackedInt64Array AStar3D::get_point_ids() { } Vector<int64_t> AStar3D::get_point_connections(int64_t p_id) { - Point *p; + Point *p = nullptr; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_V_MSG(!p_exists, Vector<int64_t>(), vformat("Can't get point's connections. Point with id: %d doesn't exist.", p_id)); @@ -386,11 +386,11 @@ real_t AStar3D::_estimate_cost(int64_t p_from_id, int64_t p_to_id) { return scost; } - Point *from_point; + Point *from_point = nullptr; bool from_exists = points.lookup(p_from_id, from_point); ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id)); - Point *to_point; + Point *to_point = nullptr; bool to_exists = points.lookup(p_to_id, to_point); ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id)); @@ -403,11 +403,11 @@ real_t AStar3D::_compute_cost(int64_t p_from_id, int64_t p_to_id) { return scost; } - Point *from_point; + Point *from_point = nullptr; bool from_exists = points.lookup(p_from_id, from_point); ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id)); - Point *to_point; + Point *to_point = nullptr; bool to_exists = points.lookup(p_to_id, to_point); ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id)); @@ -415,11 +415,11 @@ real_t AStar3D::_compute_cost(int64_t p_from_id, int64_t p_to_id) { } Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id) { - Point *a; + Point *a = nullptr; bool from_exists = points.lookup(p_from_id, a); ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id)); - Point *b; + Point *b = nullptr; bool to_exists = points.lookup(p_to_id, b); ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id)); @@ -464,11 +464,11 @@ Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id) { } Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id) { - Point *a; + Point *a = nullptr; bool from_exists = points.lookup(p_from_id, a); ERR_FAIL_COND_V_MSG(!from_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id)); - Point *b; + Point *b = nullptr; bool to_exists = points.lookup(p_to_id, b); ERR_FAIL_COND_V_MSG(!to_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id)); @@ -513,7 +513,7 @@ Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id) { } void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) { - Point *p; + Point *p = nullptr; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set if point is disabled. Point with id: %d doesn't exist.", p_id)); @@ -521,7 +521,7 @@ void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) { } bool AStar3D::is_point_disabled(int64_t p_id) const { - Point *p; + Point *p = nullptr; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_V_MSG(!p_exists, false, vformat("Can't get if point is disabled. Point with id: %d doesn't exist.", p_id)); @@ -660,11 +660,11 @@ real_t AStar2D::_estimate_cost(int64_t p_from_id, int64_t p_to_id) { return scost; } - AStar3D::Point *from_point; + AStar3D::Point *from_point = nullptr; bool from_exists = astar.points.lookup(p_from_id, from_point); ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id)); - AStar3D::Point *to_point; + AStar3D::Point *to_point = nullptr; bool to_exists = astar.points.lookup(p_to_id, to_point); ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id)); @@ -677,11 +677,11 @@ real_t AStar2D::_compute_cost(int64_t p_from_id, int64_t p_to_id) { return scost; } - AStar3D::Point *from_point; + AStar3D::Point *from_point = nullptr; bool from_exists = astar.points.lookup(p_from_id, from_point); ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id)); - AStar3D::Point *to_point; + AStar3D::Point *to_point = nullptr; bool to_exists = astar.points.lookup(p_to_id, to_point); ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id)); @@ -689,11 +689,11 @@ real_t AStar2D::_compute_cost(int64_t p_from_id, int64_t p_to_id) { } Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id) { - AStar3D::Point *a; + AStar3D::Point *a = nullptr; bool from_exists = astar.points.lookup(p_from_id, a); ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id)); - AStar3D::Point *b; + AStar3D::Point *b = nullptr; bool to_exists = astar.points.lookup(p_to_id, b); ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id)); @@ -737,11 +737,11 @@ Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id) { } Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id) { - AStar3D::Point *a; + AStar3D::Point *a = nullptr; bool from_exists = astar.points.lookup(p_from_id, a); ERR_FAIL_COND_V_MSG(!from_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id)); - AStar3D::Point *b; + AStar3D::Point *b = nullptr; bool to_exists = astar.points.lookup(p_to_id, b); ERR_FAIL_COND_V_MSG(!to_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id)); diff --git a/core/math/a_star_grid_2d.cpp b/core/math/a_star_grid_2d.cpp index 379d34aa2a..d17f465ab8 100644 --- a/core/math/a_star_grid_2d.cpp +++ b/core/math/a_star_grid_2d.cpp @@ -106,16 +106,45 @@ Size2 AStarGrid2D::get_cell_size() const { return cell_size; } +void AStarGrid2D::set_cell_shape(CellShape p_cell_shape) { + if (cell_shape == p_cell_shape) { + return; + } + + ERR_FAIL_INDEX(p_cell_shape, CellShape::CELL_SHAPE_MAX); + cell_shape = p_cell_shape; + dirty = true; +} + +AStarGrid2D::CellShape AStarGrid2D::get_cell_shape() const { + return cell_shape; +} + void AStarGrid2D::update() { points.clear(); const int32_t end_x = region.get_end().x; const int32_t end_y = region.get_end().y; + const Vector2 half_cell_size = cell_size / 2; for (int32_t y = region.position.y; y < end_y; y++) { LocalVector<Point> line; for (int32_t x = region.position.x; x < end_x; x++) { - line.push_back(Point(Vector2i(x, y), offset + Vector2(x, y) * cell_size)); + Vector2 v = offset; + switch (cell_shape) { + case CELL_SHAPE_ISOMETRIC_RIGHT: + v += half_cell_size + Vector2(x + y, y - x) * half_cell_size; + break; + case CELL_SHAPE_ISOMETRIC_DOWN: + v += half_cell_size + Vector2(x - y, x + y) * half_cell_size; + break; + case CELL_SHAPE_SQUARE: + v += Vector2(x, y) * cell_size; + break; + default: + break; + } + line.push_back(Point(Vector2i(x, y), v)); } points.push_back(line); } @@ -620,6 +649,8 @@ void AStarGrid2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_offset"), &AStarGrid2D::get_offset); ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &AStarGrid2D::set_cell_size); ClassDB::bind_method(D_METHOD("get_cell_size"), &AStarGrid2D::get_cell_size); + ClassDB::bind_method(D_METHOD("set_cell_shape", "cell_shape"), &AStarGrid2D::set_cell_shape); + ClassDB::bind_method(D_METHOD("get_cell_shape"), &AStarGrid2D::get_cell_shape); ClassDB::bind_method(D_METHOD("is_in_bounds", "x", "y"), &AStarGrid2D::is_in_bounds); ClassDB::bind_method(D_METHOD("is_in_boundsv", "id"), &AStarGrid2D::is_in_boundsv); ClassDB::bind_method(D_METHOD("is_dirty"), &AStarGrid2D::is_dirty); @@ -651,6 +682,7 @@ void AStarGrid2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cell_size"), "set_cell_size", "get_cell_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_shape", PROPERTY_HINT_ENUM, "Square,IsometricRight,IsometricDown"), "set_cell_shape", "get_cell_shape"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "jumping_enabled"), "set_jumping_enabled", "is_jumping_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "default_compute_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_compute_heuristic", "get_default_compute_heuristic"); @@ -668,4 +700,9 @@ void AStarGrid2D::_bind_methods() { BIND_ENUM_CONSTANT(DIAGONAL_MODE_AT_LEAST_ONE_WALKABLE); BIND_ENUM_CONSTANT(DIAGONAL_MODE_ONLY_IF_NO_OBSTACLES); BIND_ENUM_CONSTANT(DIAGONAL_MODE_MAX); + + BIND_ENUM_CONSTANT(CELL_SHAPE_SQUARE); + BIND_ENUM_CONSTANT(CELL_SHAPE_ISOMETRIC_RIGHT); + BIND_ENUM_CONSTANT(CELL_SHAPE_ISOMETRIC_DOWN); + BIND_ENUM_CONSTANT(CELL_SHAPE_MAX); } diff --git a/core/math/a_star_grid_2d.h b/core/math/a_star_grid_2d.h index 619551b754..69cb77dd3e 100644 --- a/core/math/a_star_grid_2d.h +++ b/core/math/a_star_grid_2d.h @@ -56,11 +56,19 @@ public: HEURISTIC_MAX, }; + enum CellShape { + CELL_SHAPE_SQUARE, + CELL_SHAPE_ISOMETRIC_RIGHT, + CELL_SHAPE_ISOMETRIC_DOWN, + CELL_SHAPE_MAX, + }; + private: Rect2i region; Vector2 offset; Size2 cell_size = Size2(1, 1); bool dirty = false; + CellShape cell_shape = CELL_SHAPE_SQUARE; bool jumping_enabled = false; DiagonalMode diagonal_mode = DIAGONAL_MODE_ALWAYS; @@ -157,6 +165,9 @@ public: void set_cell_size(const Size2 &p_cell_size); Size2 get_cell_size() const; + void set_cell_shape(CellShape p_cell_shape); + CellShape get_cell_shape() const; + void update(); bool is_in_bounds(int32_t p_x, int32_t p_y) const; @@ -193,5 +204,6 @@ public: VARIANT_ENUM_CAST(AStarGrid2D::DiagonalMode); VARIANT_ENUM_CAST(AStarGrid2D::Heuristic); +VARIANT_ENUM_CAST(AStarGrid2D::CellShape) #endif // A_STAR_GRID_2D_H diff --git a/core/math/aabb.h b/core/math/aabb.h index 859810df37..cea845bf7c 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -200,11 +200,11 @@ inline bool AABB::encloses(const AABB &p_aabb) const { return ( (src_min.x <= dst_min.x) && - (src_max.x > dst_max.x) && + (src_max.x >= dst_max.x) && (src_min.y <= dst_min.y) && - (src_max.y > dst_max.y) && + (src_max.y >= dst_max.y) && (src_min.z <= dst_min.z) && - (src_max.z > dst_max.z)); + (src_max.z >= dst_max.z)); } Vector3 AABB::get_support(const Vector3 &p_normal) const { diff --git a/core/math/basis.h b/core/math/basis.h index b4d971464e..e3094114e8 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -136,6 +136,8 @@ struct _NO_DISCARD_ Basis { _FORCE_INLINE_ Basis operator-(const Basis &p_matrix) const; _FORCE_INLINE_ void operator*=(const real_t p_val); _FORCE_INLINE_ Basis operator*(const real_t p_val) const; + _FORCE_INLINE_ void operator/=(const real_t p_val); + _FORCE_INLINE_ Basis operator/(const real_t p_val) const; bool is_orthogonal() const; bool is_orthonormal() const; @@ -289,6 +291,18 @@ _FORCE_INLINE_ Basis Basis::operator*(const real_t p_val) const { return ret; } +_FORCE_INLINE_ void Basis::operator/=(const real_t p_val) { + rows[0] /= p_val; + rows[1] /= p_val; + rows[2] /= p_val; +} + +_FORCE_INLINE_ Basis Basis::operator/(const real_t p_val) const { + Basis ret(*this); + ret /= p_val; + return ret; +} + Vector3 Basis::xform(const Vector3 &p_vector) const { return Vector3( rows[0].dot(p_vector), diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h index 99c554fe05..305a64e39c 100644 --- a/core/math/geometry_3d.h +++ b/core/math/geometry_3d.h @@ -31,6 +31,7 @@ #ifndef GEOMETRY_3D_H #define GEOMETRY_3D_H +#include "core/math/delaunay_3d.h" #include "core/math/face3.h" #include "core/object/object.h" #include "core/templates/local_vector.h" @@ -532,6 +533,21 @@ public: return clipped; } + static Vector<int32_t> tetrahedralize_delaunay(const Vector<Vector3> &p_points) { + Vector<Delaunay3D::OutputSimplex> tetr = Delaunay3D::tetrahedralize(p_points); + Vector<int32_t> tetrahedrons; + + tetrahedrons.resize(4 * tetr.size()); + int32_t *ptr = tetrahedrons.ptrw(); + for (int i = 0; i < tetr.size(); i++) { + *ptr++ = tetr[i].points[0]; + *ptr++ = tetr[i].points[1]; + *ptr++ = tetr[i].points[2]; + *ptr++ = tetr[i].points[3]; + } + return tetrahedrons; + } + // Create a "wrap" that encloses the given geometry. static Vector<Face3> wrap_geometry(Vector<Face3> p_array, real_t *p_error = nullptr); diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 366ccca4cb..3060f31970 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -198,6 +198,22 @@ public: #endif } + // These methods assume (p_num + p_den) doesn't overflow. + static _ALWAYS_INLINE_ int32_t division_round_up(int32_t p_num, int32_t p_den) { + int32_t offset = (p_num < 0 && p_den < 0) ? 1 : -1; + return (p_num + p_den + offset) / p_den; + } + static _ALWAYS_INLINE_ uint32_t division_round_up(uint32_t p_num, uint32_t p_den) { + return (p_num + p_den - 1) / p_den; + } + static _ALWAYS_INLINE_ int64_t division_round_up(int64_t p_num, int64_t p_den) { + int32_t offset = (p_num < 0 && p_den < 0) ? 1 : -1; + return (p_num + p_den + offset) / p_den; + } + static _ALWAYS_INLINE_ uint64_t division_round_up(uint64_t p_num, uint64_t p_den) { + return (p_num + p_den - 1) / p_den; + } + static _ALWAYS_INLINE_ bool is_finite(double p_val) { return isfinite(p_val); } static _ALWAYS_INLINE_ bool is_finite(float p_val) { return isfinite(p_val); } diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index bc4682fd90..a22d075b64 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -295,6 +295,18 @@ Transform2D Transform2D::operator*(const real_t p_val) const { return ret; } +void Transform2D::operator/=(const real_t p_val) { + columns[0] /= p_val; + columns[1] /= p_val; + columns[2] /= p_val; +} + +Transform2D Transform2D::operator/(const real_t p_val) const { + Transform2D ret(*this); + ret /= p_val; + return ret; +} + Transform2D::operator String() const { return "[X: " + columns[0].operator String() + ", Y: " + columns[1].operator String() + diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index dd1a33c5d5..9ff925f66f 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -109,6 +109,8 @@ struct _NO_DISCARD_ Transform2D { Transform2D operator*(const Transform2D &p_transform) const; void operator*=(const real_t p_val); Transform2D operator*(const real_t p_val) const; + void operator/=(const real_t p_val); + Transform2D operator/(const real_t p_val) const; Transform2D interpolate_with(const Transform2D &p_transform, const real_t p_c) const; diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp index cdc94676c9..20713349d7 100644 --- a/core/math/transform_3d.cpp +++ b/core/math/transform_3d.cpp @@ -208,6 +208,17 @@ Transform3D Transform3D::operator*(const real_t p_val) const { return ret; } +void Transform3D::operator/=(const real_t p_val) { + basis /= p_val; + origin /= p_val; +} + +Transform3D Transform3D::operator/(const real_t p_val) const { + Transform3D ret(*this); + ret /= p_val; + return ret; +} + Transform3D::operator String() const { return "[X: " + basis.get_column(0).operator String() + ", Y: " + basis.get_column(1).operator String() + diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h index 70141a3dbe..d1ec34d53f 100644 --- a/core/math/transform_3d.h +++ b/core/math/transform_3d.h @@ -104,6 +104,8 @@ struct _NO_DISCARD_ Transform3D { Transform3D operator*(const Transform3D &p_transform) const; void operator*=(const real_t p_val); Transform3D operator*(const real_t p_val) const; + void operator/=(const real_t p_val); + Transform3D operator/(const real_t p_val) const; Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const; diff --git a/core/math/vector2i.h b/core/math/vector2i.h index e6850347c3..b2c75beb4d 100644 --- a/core/math/vector2i.h +++ b/core/math/vector2i.h @@ -85,6 +85,14 @@ struct _NO_DISCARD_ Vector2i { return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y)); } + double distance_to(const Vector2i &p_to) const { + return (p_to - *this).length(); + } + + int64_t distance_squared_to(const Vector2i &p_to) const { + return (p_to - *this).length_squared(); + } + Vector2i operator+(const Vector2i &p_v) const; void operator+=(const Vector2i &p_v); Vector2i operator-(const Vector2i &p_v) const; diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 53d3829a99..5a5e9deda8 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -87,6 +87,9 @@ struct _NO_DISCARD_ Vector3i { Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const; Vector3i snapped(const Vector3i &p_step) const; + _FORCE_INLINE_ double distance_to(const Vector3i &p_to) const; + _FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const; + /* Operators */ _FORCE_INLINE_ Vector3i &operator+=(const Vector3i &p_v); @@ -143,6 +146,14 @@ Vector3i Vector3i::sign() const { return Vector3i(SIGN(x), SIGN(y), SIGN(z)); } +double Vector3i::distance_to(const Vector3i &p_to) const { + return (p_to - *this).length(); +} + +int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const { + return (p_to - *this).length_squared(); +} + /* Operators */ Vector3i &Vector3i::operator+=(const Vector3i &p_v) { diff --git a/core/math/vector4i.h b/core/math/vector4i.h index b815aa8e76..7d85d473d9 100644 --- a/core/math/vector4i.h +++ b/core/math/vector4i.h @@ -84,6 +84,9 @@ struct _NO_DISCARD_ Vector4i { _FORCE_INLINE_ void zero(); + _FORCE_INLINE_ double distance_to(const Vector4i &p_to) const; + _FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const; + _FORCE_INLINE_ Vector4i abs() const; _FORCE_INLINE_ Vector4i sign() const; Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const; @@ -139,6 +142,14 @@ double Vector4i::length() const { return Math::sqrt((double)length_squared()); } +double Vector4i::distance_to(const Vector4i &p_to) const { + return (p_to - *this).length(); +} + +int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const { + return (p_to - *this).length_squared(); +} + Vector4i Vector4i::abs() const { return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w)); } diff --git a/core/object/object.h b/core/object/object.h index fdd1c0b267..d697f14b7e 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -235,7 +235,7 @@ struct MethodInfo { return arguments_metadata.size() > p_arg ? arguments_metadata[p_arg] : 0; } - inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; } + inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id && name == p_method.name; } inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); } operator Dictionary() const; diff --git a/core/object/script_language.h b/core/object/script_language.h index 69da50f074..bb714d5bc3 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -243,7 +243,7 @@ public: virtual void get_doc_comment_delimiters(List<String> *p_delimiters) const = 0; virtual void get_string_delimiters(List<String> *p_delimiters) const = 0; virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const { return Ref<Script>(); } - virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) { return Vector<ScriptTemplate>(); } + virtual Vector<ScriptTemplate> get_built_in_templates(const StringName &p_object) { return Vector<ScriptTemplate>(); } virtual bool is_using_templates() { return false; } virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptError> *r_errors = nullptr, List<Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const = 0; virtual String validate_path(const String &p_path) const { return ""; } @@ -371,6 +371,7 @@ public: virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); } virtual void reload_all_scripts() = 0; + virtual void reload_scripts(const Array &p_scripts, bool p_soft_reload) = 0; virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) = 0; /* LOADER FUNCTIONS */ diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp index 79f39cb626..be62cabe25 100644 --- a/core/object/script_language_extension.cpp +++ b/core/object/script_language_extension.cpp @@ -107,7 +107,7 @@ void ScriptLanguageExtension::_bind_methods() { GDVIRTUAL_BIND(_supports_builtin_mode); GDVIRTUAL_BIND(_supports_documentation); GDVIRTUAL_BIND(_can_inherit_from_file); - GDVIRTUAL_BIND(_find_function, "class_name", "function_name"); + GDVIRTUAL_BIND(_find_function, "function", "code"); GDVIRTUAL_BIND(_make_function, "class_name", "function_name", "function_args"); GDVIRTUAL_BIND(_open_in_external_editor, "script", "line", "column"); GDVIRTUAL_BIND(_overrides_external_editor); diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 852b2aebd8..5b10739486 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -265,7 +265,7 @@ public: GDVIRTUAL1RC(TypedArray<Dictionary>, _get_built_in_templates, StringName) - virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override { + virtual Vector<ScriptTemplate> get_built_in_templates(const StringName &p_object) override { TypedArray<Dictionary> ret; GDVIRTUAL_REQUIRED_CALL(_get_built_in_templates, p_object, ret); Vector<ScriptTemplate> stret; @@ -562,6 +562,7 @@ public: } EXBIND0(reload_all_scripts) + EXBIND2(reload_scripts, const Array &, bool) EXBIND2(reload_tool_script, const Ref<Script> &, bool) /* LOADER FUNCTIONS */ diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp index 631767219f..e2ab473b01 100644 --- a/core/object/worker_thread_pool.cpp +++ b/core/object/worker_thread_pool.cpp @@ -33,6 +33,7 @@ #include "core/object/script_language.h" #include "core/os/os.h" #include "core/os/thread_safe.h" +#include "core/templates/command_queue_mt.h" void WorkerThreadPool::Task::free_template_userdata() { ERR_FAIL_NULL(template_userdata); @@ -43,24 +44,18 @@ void WorkerThreadPool::Task::free_template_userdata() { WorkerThreadPool *WorkerThreadPool::singleton = nullptr; -void WorkerThreadPool::_process_task_queue() { - task_mutex.lock(); - Task *task = task_queue.first()->self(); - task_queue.remove(task_queue.first()); - task_mutex.unlock(); - _process_task(task); -} +thread_local CommandQueueMT *WorkerThreadPool::flushing_cmd_queue = nullptr; void WorkerThreadPool::_process_task(Task *p_task) { - bool low_priority = p_task->low_priority; - int pool_thread_index = -1; - Task *prev_low_prio_task = nullptr; // In case this is recursively called. +#ifdef THREADS_ENABLED + int pool_thread_index = thread_ids[Thread::get_caller_id()]; + ThreadData &curr_thread = threads[pool_thread_index]; + Task *prev_task = nullptr; // In case this is recursively called. + bool safe_for_nodes_backup = is_current_thread_safe_for_nodes(); - if (!use_native_low_priority_threads) { + { // Tasks must start with this unset. They are free to set-and-forget otherwise. set_current_thread_safe_for_nodes(false); - pool_thread_index = thread_ids[Thread::get_caller_id()]; - ThreadData &curr_thread = threads[pool_thread_index]; // Since the WorkerThreadPool is started before the script server, // its pre-created threads can't have ScriptServer::thread_enter() called on them early. // Therefore, we do it late at the first opportunity, so in case the task @@ -71,15 +66,11 @@ void WorkerThreadPool::_process_task(Task *p_task) { } task_mutex.lock(); p_task->pool_thread_index = pool_thread_index; - if (low_priority) { - low_priority_tasks_running++; - prev_low_prio_task = curr_thread.current_low_prio_task; - curr_thread.current_low_prio_task = p_task; - } else { - curr_thread.current_low_prio_task = nullptr; - } + prev_task = curr_thread.current_task; + curr_thread.current_task = p_task; task_mutex.unlock(); } +#endif if (p_task->group) { // Handling a group @@ -111,33 +102,24 @@ void WorkerThreadPool::_process_task(Task *p_task) { memdelete(p_task->template_userdata); // This is no longer needed at this point, so get rid of it. } - if (low_priority && use_native_low_priority_threads) { - p_task->completed = true; - p_task->done_semaphore.post(); - if (do_post) { - p_task->group->completed.set_to(true); - } - } else { - if (do_post) { - p_task->group->done_semaphore.post(); - p_task->group->completed.set_to(true); - } - uint32_t max_users = p_task->group->tasks_used + 1; // Add 1 because the thread waiting for it is also user. Read before to avoid another thread freeing task after increment. - uint32_t finished_users = p_task->group->finished.increment(); - - if (finished_users == max_users) { - // Get rid of the group, because nobody else is using it. - task_mutex.lock(); - group_allocator.free(p_task->group); - task_mutex.unlock(); - } - - // For groups, tasks get rid of themselves. + if (do_post) { + p_task->group->done_semaphore.post(); + p_task->group->completed.set_to(true); + } + uint32_t max_users = p_task->group->tasks_used + 1; // Add 1 because the thread waiting for it is also user. Read before to avoid another thread freeing task after increment. + uint32_t finished_users = p_task->group->finished.increment(); + if (finished_users == max_users) { + // Get rid of the group, because nobody else is using it. task_mutex.lock(); - task_allocator.free(p_task); + group_allocator.free(p_task->group); task_mutex.unlock(); } + + // For groups, tasks get rid of themselves. + + task_mutex.lock(); + task_allocator.free(p_task); } else { if (p_task->native_func) { p_task->native_func(p_task->native_func_userdata); @@ -150,88 +132,164 @@ void WorkerThreadPool::_process_task(Task *p_task) { task_mutex.lock(); p_task->completed = true; - for (uint8_t i = 0; i < p_task->waiting; i++) { - p_task->done_semaphore.post(); + p_task->pool_thread_index = -1; + if (p_task->waiting_user) { + p_task->done_semaphore.post(p_task->waiting_user); } - if (!use_native_low_priority_threads) { - p_task->pool_thread_index = -1; + // Let awaiters know. + for (uint32_t i = 0; i < threads.size(); i++) { + if (threads[i].awaited_task == p_task) { + threads[i].cond_var.notify_one(); + threads[i].signaled = true; + } } - task_mutex.unlock(); // Keep mutex down to here since on unlock the task may be freed. } - // Task may have been freed by now (all callers notified). - p_task = nullptr; - - if (!use_native_low_priority_threads) { - bool post = false; - task_mutex.lock(); - ThreadData &curr_thread = threads[pool_thread_index]; - curr_thread.current_low_prio_task = prev_low_prio_task; - if (low_priority) { +#ifdef THREADS_ENABLED + { + curr_thread.current_task = prev_task; + if (p_task->low_priority) { low_priority_threads_used--; - low_priority_tasks_running--; - // A low prioriry task was freed, so see if we can move a pending one to the high priority queue. - if (_try_promote_low_priority_task()) { - post = true; - } - if (low_priority_tasks_awaiting_others == low_priority_tasks_running) { - _prevent_low_prio_saturation_deadlock(); + if (_try_promote_low_priority_task()) { + if (prev_task) { // Otherwise, this thread will catch it. + _notify_threads(&curr_thread, 1, 0); + } } } + task_mutex.unlock(); - if (post) { - task_available_semaphore.post(); - } } + + set_current_thread_safe_for_nodes(safe_for_nodes_backup); +#endif } void WorkerThreadPool::_thread_function(void *p_user) { + ThreadData *thread_data = (ThreadData *)p_user; while (true) { - singleton->task_available_semaphore.wait(); - if (singleton->exit_threads) { - break; + Task *task_to_process = nullptr; + { + MutexLock lock(singleton->task_mutex); + if (singleton->exit_threads) { + return; + } + thread_data->signaled = false; + + if (singleton->task_queue.first()) { + task_to_process = singleton->task_queue.first()->self(); + singleton->task_queue.remove(singleton->task_queue.first()); + } else { + thread_data->cond_var.wait(lock); + DEV_ASSERT(singleton->exit_threads || thread_data->signaled); + } } - singleton->_process_task_queue(); - } -} -void WorkerThreadPool::_native_low_priority_thread_function(void *p_user) { - Task *task = (Task *)p_user; - singleton->_process_task(task); + if (task_to_process) { + singleton->_process_task(task_to_process); + } + } } -void WorkerThreadPool::_post_task(Task *p_task, bool p_high_priority) { +void WorkerThreadPool::_post_tasks_and_unlock(Task **p_tasks, uint32_t p_count, bool p_high_priority) { // Fall back to processing on the calling thread if there are no worker threads. // Separated into its own variable to make it easier to extend this logic // in custom builds. bool process_on_calling_thread = threads.size() == 0; if (process_on_calling_thread) { - _process_task(p_task); + task_mutex.unlock(); + for (uint32_t i = 0; i < p_count; i++) { + _process_task(p_tasks[i]); + } return; } - task_mutex.lock(); - p_task->low_priority = !p_high_priority; - if (!p_high_priority && use_native_low_priority_threads) { - p_task->low_priority_thread = native_thread_allocator.alloc(); - task_mutex.unlock(); + uint32_t to_process = 0; + uint32_t to_promote = 0; + + ThreadData *caller_pool_thread = thread_ids.has(Thread::get_caller_id()) ? &threads[thread_ids[Thread::get_caller_id()]] : nullptr; - if (p_task->group) { - p_task->group->low_priority_native_tasks.push_back(p_task); + for (uint32_t i = 0; i < p_count; i++) { + p_tasks[i]->low_priority = !p_high_priority; + if (p_high_priority || low_priority_threads_used < max_low_priority_threads) { + task_queue.add_last(&p_tasks[i]->task_elem); + if (!p_high_priority) { + low_priority_threads_used++; + } + to_process++; + } else { + // Too many threads using low priority, must go to queue. + low_priority_task_queue.add_last(&p_tasks[i]->task_elem); + to_promote++; } - p_task->low_priority_thread->start(_native_low_priority_thread_function, p_task); // Pask task directly to thread. - } else if (p_high_priority || low_priority_threads_used < max_low_priority_threads) { - task_queue.add_last(&p_task->task_elem); - if (!p_high_priority) { - low_priority_threads_used++; + } + + _notify_threads(caller_pool_thread, to_process, to_promote); + + task_mutex.unlock(); +} + +void WorkerThreadPool::_notify_threads(const ThreadData *p_current_thread_data, uint32_t p_process_count, uint32_t p_promote_count) { + uint32_t to_process = p_process_count; + uint32_t to_promote = p_promote_count; + + // This is where which threads are awaken is decided according to the workload. + // Threads that will anyway have a chance to check the situation and process/promote tasks + // are excluded from being notified. Others will be tried anyway to try to distribute load. + // The current thread, if is a pool thread, is also excluded depending on the promoting/processing + // needs because it will anyway loop again. However, it will contribute to decreasing the count, + // which helps reducing sync traffic. + + uint32_t thread_count = threads.size(); + + // First round: + // 1. For processing: notify threads that are not running tasks, to keep the stacks as shallow as possible. + // 2. For promoting: since it's exclusive with processing, we fin threads able to promote low-prio tasks now. + for (uint32_t i = 0; + i < thread_count && (to_process || to_promote); + i++, notify_index = (notify_index + 1) % thread_count) { + ThreadData &th = threads[notify_index]; + + if (th.signaled) { + continue; + } + if (th.current_task) { + // Good thread for promoting low-prio? + if (to_promote && th.awaited_task && th.current_task->low_priority) { + if (likely(&th != p_current_thread_data)) { + th.cond_var.notify_one(); + } + th.signaled = true; + to_promote--; + } + } else { + if (to_process) { + if (likely(&th != p_current_thread_data)) { + th.cond_var.notify_one(); + } + th.signaled = true; + to_process--; + } + } + } + + // Second round: + // For processing: if the first round wasn't enough, let's try now with threads processing tasks but currently awaiting. + for (uint32_t i = 0; + i < thread_count && to_process; + i++, notify_index = (notify_index + 1) % thread_count) { + ThreadData &th = threads[notify_index]; + + if (th.signaled) { + continue; + } + if (th.awaited_task) { + if (likely(&th != p_current_thread_data)) { + th.cond_var.notify_one(); + } + th.signaled = true; + to_process--; } - task_mutex.unlock(); - task_available_semaphore.post(); - } else { - // Too many threads using low priority, must go to queue. - low_priority_task_queue.add_last(&p_task->task_elem); - task_mutex.unlock(); } } @@ -247,23 +305,6 @@ bool WorkerThreadPool::_try_promote_low_priority_task() { } } -void WorkerThreadPool::_prevent_low_prio_saturation_deadlock() { - if (low_priority_tasks_awaiting_others == low_priority_tasks_running) { -#ifdef DEV_ENABLED - print_verbose("WorkerThreadPool: Low-prio slots saturated with tasks all waiting for other low-prio tasks. Attempting to avoid deadlock by scheduling one extra task."); -#endif - // In order not to create dependency cycles, we can only schedule the next one. - // We'll keep doing the same until the deadlock is broken, - SelfList<Task> *to_promote = low_priority_task_queue.first(); - if (to_promote) { - low_priority_task_queue.remove(to_promote); - task_queue.add_last(to_promote); - low_priority_threads_used++; - task_available_semaphore.post(); - } - } -} - WorkerThreadPool::TaskID WorkerThreadPool::add_native_task(void (*p_func)(void *), void *p_userdata, bool p_high_priority, const String &p_description) { return _add_task(Callable(), p_func, p_userdata, nullptr, p_high_priority, p_description); } @@ -273,15 +314,15 @@ WorkerThreadPool::TaskID WorkerThreadPool::_add_task(const Callable &p_callable, // Get a free task Task *task = task_allocator.alloc(); TaskID id = last_task++; + task->self = id; task->callable = p_callable; task->native_func = p_func; task->native_func_userdata = p_userdata; task->description = p_description; task->template_userdata = p_template_userdata; tasks.insert(id, task); - task_mutex.unlock(); - _post_task(task, p_high_priority); + _post_tasks_and_unlock(&task, 1, p_high_priority); return id; } @@ -313,105 +354,117 @@ Error WorkerThreadPool::wait_for_task_completion(TaskID p_task_id) { } Task *task = *taskp; - if (!task->completed) { - if (!use_native_low_priority_threads && task->pool_thread_index != -1) { // Otherwise, it's not running yet. - int caller_pool_th_index = thread_ids.has(Thread::get_caller_id()) ? thread_ids[Thread::get_caller_id()] : -1; - if (caller_pool_th_index == task->pool_thread_index) { - // Deadlock prevention. - // Waiting for a task run on this same thread? That means the task to be awaited started waiting as well - // and another task was run to make use of the thread in the meantime, with enough bad luck as to - // the need to wait for the original task arose in turn. - // In other words, the task we want to wait for is buried in the stack. - // Let's report the caller about the issue to it handles as it sees fit. - task_mutex.unlock(); - return ERR_BUSY; - } + if (task->completed) { + if (task->waiting_pool == 0 && task->waiting_user == 0) { + tasks.erase(p_task_id); + task_allocator.free(task); } + task_mutex.unlock(); + return OK; + } + + ThreadData *caller_pool_thread = thread_ids.has(Thread::get_caller_id()) ? &threads[thread_ids[Thread::get_caller_id()]] : nullptr; + if (caller_pool_thread && p_task_id <= caller_pool_thread->current_task->self) { + // Deadlock prevention: + // When a pool thread wants to wait for an older task, the following situations can happen: + // 1. Awaited task is deep in the stack of the awaiter. + // 2. A group of awaiter threads end up depending on some tasks buried in the stack + // of their worker threads in such a way that progress can't be made. + // Both would entail a deadlock. Some may be handled here in the WorkerThreadPool + // with some extra logic and bookkeeping. However, there would still be unavoidable + // cases of deadlock because of the way waiting threads process outstanding tasks. + // Taking into account there's no feasible solution for every possible case + // with the current design, we just simply reject attempts to await on older tasks, + // with a specific error code that signals the situation so the caller can handle it. + task_mutex.unlock(); + return ERR_BUSY; + } + + if (caller_pool_thread) { + task->waiting_pool++; + } else { + task->waiting_user++; + } - task->waiting++; - - bool is_low_prio_waiting_for_another = false; - if (!use_native_low_priority_threads) { - // Deadlock prevention: - // If all low-prio tasks are waiting for other low-prio tasks and there are no more free low-prio slots, - // we have a no progressable situation. We can apply a workaround, consisting in promoting an awaited queued - // low-prio task to the schedule queue so it can run and break the "impasse". - // NOTE: A similar reasoning could be made about high priority tasks, but there are usually much more - // than low-prio. Therefore, a deadlock there would only happen when dealing with a very complex task graph - // or when there are too few worker threads (limited platforms or exotic settings). If that turns out to be - // an issue in the real world, a further fix can be applied against that. - if (task->low_priority) { - bool awaiter_is_a_low_prio_task = thread_ids.has(Thread::get_caller_id()) && threads[thread_ids[Thread::get_caller_id()]].current_low_prio_task; - if (awaiter_is_a_low_prio_task) { - is_low_prio_waiting_for_another = true; - low_priority_tasks_awaiting_others++; - if (low_priority_tasks_awaiting_others == low_priority_tasks_running) { - _prevent_low_prio_saturation_deadlock(); + task_mutex.unlock(); + + if (caller_pool_thread) { + while (true) { + Task *task_to_process = nullptr; + { + MutexLock lock(task_mutex); + bool was_signaled = caller_pool_thread->signaled; + caller_pool_thread->signaled = false; + + if (task->completed) { + // This thread was awaken also for some reason, but it's about to exit. + // Let's find out what may be pending and forward the requests. + if (!exit_threads && was_signaled) { + uint32_t to_process = task_queue.first() ? 1 : 0; + uint32_t to_promote = caller_pool_thread->current_task->low_priority && low_priority_task_queue.first() ? 1 : 0; + if (to_process || to_promote) { + // This thread must be left alone since it won't loop again. + caller_pool_thread->signaled = true; + _notify_threads(caller_pool_thread, to_process, to_promote); + } } + + task->waiting_pool--; + if (task->waiting_pool == 0 && task->waiting_user == 0) { + tasks.erase(p_task_id); + task_allocator.free(task); + } + + break; } - } - } - task_mutex.unlock(); + if (!exit_threads) { + // This is a thread from the pool. It shouldn't just idle. + // Let's try to process other tasks while we wait. - if (use_native_low_priority_threads && task->low_priority) { - task->done_semaphore.wait(); - } else { - bool current_is_pool_thread = thread_ids.has(Thread::get_caller_id()); - if (current_is_pool_thread) { - // We are an actual process thread, we must not be blocked so continue processing stuff if available. - bool must_exit = false; - while (true) { - if (task->done_semaphore.try_wait()) { - // If done, exit - break; + if (caller_pool_thread->current_task->low_priority && low_priority_task_queue.first()) { + if (_try_promote_low_priority_task()) { + _notify_threads(caller_pool_thread, 1, 0); + } + } + + if (singleton->task_queue.first()) { + task_to_process = task_queue.first()->self(); + task_queue.remove(task_queue.first()); } - if (!must_exit) { - if (task_available_semaphore.try_wait()) { - if (exit_threads) { - must_exit = true; - } else { - // Solve tasks while they are around. - bool safe_for_nodes_backup = is_current_thread_safe_for_nodes(); - _process_task_queue(); - set_current_thread_safe_for_nodes(safe_for_nodes_backup); - continue; - } - } else if (!use_native_low_priority_threads && task->low_priority) { - // A low prioriry task started waiting, so see if we can move a pending one to the high priority queue. - task_mutex.lock(); - bool post = _try_promote_low_priority_task(); - task_mutex.unlock(); - if (post) { - task_available_semaphore.post(); - } + + if (!task_to_process) { + caller_pool_thread->awaited_task = task; + + if (flushing_cmd_queue) { + flushing_cmd_queue->unlock(); } + caller_pool_thread->cond_var.wait(lock); + if (flushing_cmd_queue) { + flushing_cmd_queue->lock(); + } + + DEV_ASSERT(exit_threads || caller_pool_thread->signaled || task->completed); + caller_pool_thread->awaited_task = nullptr; } - OS::get_singleton()->delay_usec(1); // Microsleep, this could be converted to waiting for multiple objects in supported platforms for a bit more performance. } - } else { - task->done_semaphore.wait(); } - } - task_mutex.lock(); - if (is_low_prio_waiting_for_another) { - low_priority_tasks_awaiting_others--; + if (task_to_process) { + _process_task(task_to_process); + } } - - task->waiting--; - } - - if (task->waiting == 0) { - if (use_native_low_priority_threads && task->low_priority) { - task->low_priority_thread->wait_to_finish(); - native_thread_allocator.free(task->low_priority_thread); + } else { + task->done_semaphore.wait(); + task_mutex.lock(); + task->waiting_user--; + if (task->waiting_pool == 0 && task->waiting_user == 0) { + tasks.erase(p_task_id); + task_allocator.free(task); } - tasks.erase(p_task_id); - task_allocator.free(task); + task_mutex.unlock(); } - task_mutex.unlock(); return OK; } @@ -455,11 +508,8 @@ WorkerThreadPool::GroupID WorkerThreadPool::_add_group_task(const Callable &p_ca } groups[id] = group; - task_mutex.unlock(); - for (int i = 0; i < p_tasks; i++) { - _post_task(tasks_posted[i], p_high_priority); - } + _post_tasks_and_unlock(tasks_posted, p_tasks, p_high_priority); return id; } @@ -496,28 +546,24 @@ bool WorkerThreadPool::is_group_task_completed(GroupID p_group) const { } void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) { +#ifdef THREADS_ENABLED task_mutex.lock(); Group **groupp = groups.getptr(p_group); task_mutex.unlock(); if (!groupp) { ERR_FAIL_MSG("Invalid Group ID"); } - Group *group = *groupp; - if (group->low_priority_native_tasks.size() > 0) { - for (Task *task : group->low_priority_native_tasks) { - task->low_priority_thread->wait_to_finish(); - task_mutex.lock(); - native_thread_allocator.free(task->low_priority_thread); - task_allocator.free(task); - task_mutex.unlock(); - } + { + Group *group = *groupp; - task_mutex.lock(); - group_allocator.free(group); - task_mutex.unlock(); - } else { + if (flushing_cmd_queue) { + flushing_cmd_queue->unlock(); + } group->done_semaphore.wait(); + if (flushing_cmd_queue) { + flushing_cmd_queue->lock(); + } uint32_t max_users = group->tasks_used + 1; // Add 1 because the thread waiting for it is also user. Read before to avoid another thread freeing task after increment. uint32_t finished_users = group->finished.increment(); // fetch happens before inc, so increment later. @@ -533,6 +579,7 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) { task_mutex.lock(); // This mutex is needed when Physics 2D and/or 3D is selected to run on a separate thread. groups.erase(p_group); task_mutex.unlock(); +#endif } int WorkerThreadPool::get_thread_index() { @@ -540,19 +587,23 @@ int WorkerThreadPool::get_thread_index() { return singleton->thread_ids.has(tid) ? singleton->thread_ids[tid] : -1; } -void WorkerThreadPool::init(int p_thread_count, bool p_use_native_threads_low_priority, float p_low_priority_task_ratio) { +void WorkerThreadPool::thread_enter_command_queue_mt_flush(CommandQueueMT *p_queue) { + ERR_FAIL_COND(flushing_cmd_queue != nullptr); + flushing_cmd_queue = p_queue; +} + +void WorkerThreadPool::thread_exit_command_queue_mt_flush() { + ERR_FAIL_NULL(flushing_cmd_queue); + flushing_cmd_queue = nullptr; +} + +void WorkerThreadPool::init(int p_thread_count, float p_low_priority_task_ratio) { ERR_FAIL_COND(threads.size() > 0); if (p_thread_count < 0) { p_thread_count = OS::get_singleton()->get_default_thread_pool_size(); } - if (p_use_native_threads_low_priority) { - max_low_priority_threads = 0; - } else { - max_low_priority_threads = CLAMP(p_thread_count * p_low_priority_task_ratio, 1, p_thread_count - 1); - } - - use_native_low_priority_threads = p_use_native_threads_low_priority; + max_low_priority_threads = CLAMP(p_thread_count * p_low_priority_task_ratio, 1, p_thread_count - 1); threads.resize(p_thread_count); @@ -568,24 +619,33 @@ void WorkerThreadPool::finish() { return; } - task_mutex.lock(); - SelfList<Task> *E = low_priority_task_queue.first(); - while (E) { - print_error("Task waiting was never re-claimed: " + E->self()->description); - E = E->next(); + { + MutexLock lock(task_mutex); + SelfList<Task> *E = low_priority_task_queue.first(); + while (E) { + print_error("Task waiting was never re-claimed: " + E->self()->description); + E = E->next(); + } } - task_mutex.unlock(); - exit_threads = true; - - for (uint32_t i = 0; i < threads.size(); i++) { - task_available_semaphore.post(); + { + MutexLock lock(task_mutex); + exit_threads = true; + } + for (ThreadData &data : threads) { + data.cond_var.notify_one(); } - for (ThreadData &data : threads) { data.thread.wait_to_finish(); } + { + MutexLock lock(task_mutex); + for (KeyValue<TaskID, Task *> &E : tasks) { + task_allocator.free(E.value); + } + } + threads.clear(); } diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h index dd56f95cae..c9921c808d 100644 --- a/core/object/worker_thread_pool.h +++ b/core/object/worker_thread_pool.h @@ -31,6 +31,7 @@ #ifndef WORKER_THREAD_POOL_H #define WORKER_THREAD_POOL_H +#include "core/os/condition_variable.h" #include "core/os/memory.h" #include "core/os/os.h" #include "core/os/semaphore.h" @@ -40,6 +41,8 @@ #include "core/templates/rid.h" #include "core/templates/safe_refcount.h" +class CommandQueueMT; + class WorkerThreadPool : public Object { GDCLASS(WorkerThreadPool, Object) public: @@ -60,7 +63,7 @@ private: }; struct Group { - GroupID self; + GroupID self = -1; SafeNumeric<uint32_t> index; SafeNumeric<uint32_t> completed_index; uint32_t max = 0; @@ -68,23 +71,23 @@ private: SafeFlag completed; SafeNumeric<uint32_t> finished; uint32_t tasks_used = 0; - TightLocalVector<Task *> low_priority_native_tasks; }; struct Task { + TaskID self = -1; Callable callable; void (*native_func)(void *) = nullptr; void (*native_group_func)(void *, uint32_t) = nullptr; void *native_func_userdata = nullptr; String description; - Semaphore done_semaphore; + Semaphore done_semaphore; // For user threads awaiting. bool completed = false; Group *group = nullptr; SelfList<Task> task_elem; - uint32_t waiting = 0; + uint32_t waiting_pool = 0; + uint32_t waiting_user = 0; bool low_priority = false; BaseTemplateUserdata *template_userdata = nullptr; - Thread *low_priority_thread = nullptr; int pool_thread_index = -1; void free_template_userdata(); @@ -92,51 +95,65 @@ private: task_elem(this) {} }; - PagedAllocator<Task> task_allocator; - PagedAllocator<Group> group_allocator; - PagedAllocator<Thread> native_thread_allocator; + static const uint32_t TASKS_PAGE_SIZE = 1024; + static const uint32_t GROUPS_PAGE_SIZE = 256; + + PagedAllocator<Task, false, TASKS_PAGE_SIZE> task_allocator; + PagedAllocator<Group, false, GROUPS_PAGE_SIZE> group_allocator; SelfList<Task>::List low_priority_task_queue; SelfList<Task>::List task_queue; - Mutex task_mutex; - Semaphore task_available_semaphore; + BinaryMutex task_mutex; struct ThreadData { - uint32_t index; + uint32_t index = 0; Thread thread; - Task *current_low_prio_task = nullptr; bool ready_for_scripting = false; + bool signaled = false; + Task *current_task = nullptr; + Task *awaited_task = nullptr; // Null if not awaiting the condition variable. Special value for idle-waiting. + ConditionVariable cond_var; }; TightLocalVector<ThreadData> threads; bool exit_threads = false; HashMap<Thread::ID, int> thread_ids; - HashMap<TaskID, Task *> tasks; - HashMap<GroupID, Group *> groups; + HashMap< + TaskID, + Task *, + HashMapHasherDefault, + HashMapComparatorDefault<TaskID>, + PagedAllocator<HashMapElement<TaskID, Task *>, false, TASKS_PAGE_SIZE>> + tasks; + HashMap< + GroupID, + Group *, + HashMapHasherDefault, + HashMapComparatorDefault<GroupID>, + PagedAllocator<HashMapElement<GroupID, Group *>, false, GROUPS_PAGE_SIZE>> + groups; - bool use_native_low_priority_threads = false; uint32_t max_low_priority_threads = 0; uint32_t low_priority_threads_used = 0; - uint32_t low_priority_tasks_running = 0; - uint32_t low_priority_tasks_awaiting_others = 0; + uint32_t notify_index = 0; // For rotating across threads, no help distributing load. uint64_t last_task = 1; static void _thread_function(void *p_user); - static void _native_low_priority_thread_function(void *p_user); - void _process_task_queue(); void _process_task(Task *task); - void _post_task(Task *p_task, bool p_high_priority); + void _post_tasks_and_unlock(Task **p_tasks, uint32_t p_count, bool p_high_priority); + void _notify_threads(const ThreadData *p_current_thread_data, uint32_t p_process_count, uint32_t p_promote_count); bool _try_promote_low_priority_task(); - void _prevent_low_prio_saturation_deadlock(); static WorkerThreadPool *singleton; + static thread_local CommandQueueMT *flushing_cmd_queue; + TaskID _add_task(const Callable &p_callable, void (*p_func)(void *), void *p_userdata, BaseTemplateUserdata *p_template_userdata, bool p_high_priority, const String &p_description); GroupID _add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description); @@ -199,7 +216,10 @@ public: static WorkerThreadPool *get_singleton() { return singleton; } static int get_thread_index(); - void init(int p_thread_count = -1, bool p_use_native_threads_low_priority = true, float p_low_priority_task_ratio = 0.3); + static void thread_enter_command_queue_mt_flush(CommandQueueMT *p_queue); + static void thread_exit_command_queue_mt_flush(); + + void init(int p_thread_count = -1, float p_low_priority_task_ratio = 0.3); void finish(); WorkerThreadPool(); ~WorkerThreadPool(); diff --git a/core/os/condition_variable.h b/core/os/condition_variable.h index 6a6996019d..2b6b272e18 100644 --- a/core/os/condition_variable.h +++ b/core/os/condition_variable.h @@ -31,6 +31,10 @@ #ifndef CONDITION_VARIABLE_H #define CONDITION_VARIABLE_H +#include "core/os/mutex.h" + +#ifdef THREADS_ENABLED + #ifdef MINGW_ENABLED #define MINGW_STDTHREAD_REDUNDANCY_WARNING #include "thirdparty/mingw-std-threads/mingw.condition_variable.h" @@ -64,4 +68,16 @@ public: } }; +#else // No threads. + +class ConditionVariable { +public: + template <class BinaryMutexT> + void wait(const MutexLock<BinaryMutexT> &p_lock) const {} + void notify_one() const {} + void notify_all() const {} +}; + +#endif // THREADS_ENABLED + #endif // CONDITION_VARIABLE_H diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index 6078882839..973c216d15 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -410,7 +410,7 @@ Key find_keycode(const String &p_codestr) { return keycode; } - String last_part = code_parts[code_parts.size() - 1]; + const String &last_part = code_parts[code_parts.size() - 1]; const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { @@ -422,7 +422,7 @@ Key find_keycode(const String &p_codestr) { } for (int part = 0; part < code_parts.size() - 1; part++) { - String code_part = code_parts[part]; + const String &code_part = code_parts[part]; if (code_part.nocasecmp_to(find_keycode_name(Key::SHIFT)) == 0) { keycode |= KeyModifierMask::SHIFT; } else if (code_part.nocasecmp_to(find_keycode_name(Key::CTRL)) == 0) { diff --git a/core/os/mutex.cpp b/core/os/mutex.cpp index 5d4e457c5f..9a8a2a2961 100644 --- a/core/os/mutex.cpp +++ b/core/os/mutex.cpp @@ -40,7 +40,11 @@ void _global_unlock() { _global_mutex.unlock(); } +#ifdef THREADS_ENABLED + template class MutexImpl<THREADING_NAMESPACE::recursive_mutex>; template class MutexImpl<THREADING_NAMESPACE::mutex>; template class MutexLock<MutexImpl<THREADING_NAMESPACE::recursive_mutex>>; template class MutexLock<MutexImpl<THREADING_NAMESPACE::mutex>>; + +#endif diff --git a/core/os/mutex.h b/core/os/mutex.h index 03af48ca7c..69f494d9cd 100644 --- a/core/os/mutex.h +++ b/core/os/mutex.h @@ -43,6 +43,8 @@ #define THREADING_NAMESPACE std #endif +#ifdef THREADS_ENABLED + template <class MutexT> class MutexLock; @@ -125,8 +127,8 @@ class MutexLock { THREADING_NAMESPACE::unique_lock<typename MutexT::StdMutexType> lock; public: - _ALWAYS_INLINE_ explicit MutexLock(const MutexT &p_mutex) : - lock(p_mutex.mutex){}; + explicit MutexLock(const MutexT &p_mutex) : + lock(p_mutex.mutex) {} }; // This specialization is needed so manual locking and MutexLock can be used @@ -155,4 +157,38 @@ extern template class MutexImpl<THREADING_NAMESPACE::mutex>; extern template class MutexLock<MutexImpl<THREADING_NAMESPACE::recursive_mutex>>; extern template class MutexLock<MutexImpl<THREADING_NAMESPACE::mutex>>; +#else // No threads. + +class MutexImpl { + mutable THREADING_NAMESPACE::mutex mutex; + +public: + void lock() const {} + void unlock() const {} + bool try_lock() const { return true; } +}; + +template <int Tag> +class SafeBinaryMutex : public MutexImpl { + static thread_local uint32_t count; +}; + +template <class MutexT> +class MutexLock { +public: + MutexLock(const MutexT &p_mutex) {} +}; + +template <int Tag> +class MutexLock<SafeBinaryMutex<Tag>> { +public: + MutexLock(const SafeBinaryMutex<Tag> &p_mutex) {} + ~MutexLock() {} +}; + +using Mutex = MutexImpl; +using BinaryMutex = MutexImpl; + +#endif // THREADS_ENABLED + #endif // MUTEX_H diff --git a/core/os/os.cpp b/core/os/os.cpp index 26ae286979..d5d9988cc1 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -504,6 +504,12 @@ bool OS::has_feature(const String &p_feature) { } #endif +#ifdef THREADS_ENABLED + if (p_feature == "threads") { + return true; + } +#endif + if (_check_internal_feature_support(p_feature)) { return true; } diff --git a/core/os/semaphore.h b/core/os/semaphore.h index 8bb1529bbd..19ef1dedc0 100644 --- a/core/os/semaphore.h +++ b/core/os/semaphore.h @@ -31,6 +31,10 @@ #ifndef SEMAPHORE_H #define SEMAPHORE_H +#include <cstdint> + +#ifdef THREADS_ENABLED + #include "core/error/error_list.h" #include "core/typedefs.h" #ifdef DEBUG_ENABLED @@ -58,10 +62,12 @@ private: #endif public: - _ALWAYS_INLINE_ void post() const { + _ALWAYS_INLINE_ void post(uint32_t p_count = 1) const { std::lock_guard lock(mutex); - count++; - condition.notify_one(); + count += p_count; + for (uint32_t i = 0; i < p_count; ++i) { + condition.notify_one(); + } } _ALWAYS_INLINE_ void wait() const { @@ -130,4 +136,17 @@ public: #endif }; +#else // No threads. + +class Semaphore { +public: + void post(uint32_t p_count = 1) const {} + void wait() const {} + bool try_wait() const { + return true; + } +}; + +#endif // THREADS_ENABLED + #endif // SEMAPHORE_H diff --git a/core/os/thread.cpp b/core/os/thread.cpp index 2ba90ba42c..afc74364f6 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -33,19 +33,22 @@ #include "thread.h" +#ifdef THREADS_ENABLED #include "core/object/script_language.h" #include "core/templates/safe_refcount.h" -Thread::PlatformFunctions Thread::platform_functions; - SafeNumeric<uint64_t> Thread::id_counter(1); // The first value after .increment() is 2, hence by default the main thread ID should be 1. thread_local Thread::ID Thread::caller_id = Thread::UNASSIGNED_ID; +#endif + +Thread::PlatformFunctions Thread::platform_functions; void Thread::_set_platform_functions(const PlatformFunctions &p_functions) { platform_functions = p_functions; } +#ifdef THREADS_ENABLED void Thread::callback(ID p_caller_id, const Settings &p_settings, Callback p_callback, void *p_userdata) { Thread::caller_id = p_caller_id; if (platform_functions.set_priority) { @@ -107,4 +110,6 @@ Thread::~Thread() { } } +#endif // THREADS_ENABLED + #endif // PLATFORM_THREAD_OVERRIDE diff --git a/core/os/thread.h b/core/os/thread.h index cc954678f9..a0ecc24c91 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -53,6 +53,8 @@ class String; +#ifdef THREADS_ENABLED + class Thread { public: typedef void (*Callback)(void *p_userdata); @@ -86,6 +88,8 @@ public: private: friend class Main; + static PlatformFunctions platform_functions; + ID id = UNASSIGNED_ID; static SafeNumeric<uint64_t> id_counter; static thread_local ID caller_id; @@ -93,8 +97,6 @@ private: static void callback(ID p_caller_id, const Settings &p_settings, Thread::Callback p_callback, void *p_userdata); - static PlatformFunctions platform_functions; - static void make_main_thread() { caller_id = MAIN_ID; } static void release_main_thread() { caller_id = UNASSIGNED_ID; } @@ -125,6 +127,64 @@ public: ~Thread(); }; +#else // No threads. + +class Thread { +public: + typedef void (*Callback)(void *p_userdata); + + typedef uint64_t ID; + + enum : ID { + UNASSIGNED_ID = 0, + MAIN_ID = 1 + }; + + enum Priority { + PRIORITY_LOW, + PRIORITY_NORMAL, + PRIORITY_HIGH + }; + + struct Settings { + Priority priority; + Settings() { priority = PRIORITY_NORMAL; } + }; + + struct PlatformFunctions { + Error (*set_name)(const String &) = nullptr; + void (*set_priority)(Thread::Priority) = nullptr; + void (*init)() = nullptr; + void (*wrapper)(Thread::Callback, void *) = nullptr; + void (*term)() = nullptr; + }; + +private: + friend class Main; + + static PlatformFunctions platform_functions; + + static void make_main_thread() {} + static void release_main_thread() {} + +public: + static void _set_platform_functions(const PlatformFunctions &p_functions); + + _FORCE_INLINE_ ID get_id() const { return 0; } + _FORCE_INLINE_ static ID get_caller_id() { return MAIN_ID; } + _FORCE_INLINE_ static ID get_main_id() { return MAIN_ID; } + + _FORCE_INLINE_ static bool is_main_thread() { return true; } + + static Error set_name(const String &p_name) { return ERR_UNAVAILABLE; } + + void start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings()) {} + bool is_started() const { return false; } + void wait_to_finish() {} +}; + +#endif // THREADS_ENABLED + #endif // THREAD_H #endif // PLATFORM_THREAD_OVERRIDE diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 2785d1daa5..82b3d27942 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -307,7 +307,6 @@ void register_core_settings() { GLOBAL_DEF(PropertyInfo(Variant::STRING, "network/tls/certificate_bundle_override", PROPERTY_HINT_FILE, "*.crt"), ""); GLOBAL_DEF("threading/worker_pool/max_threads", -1); - GLOBAL_DEF("threading/worker_pool/use_system_threads_for_low_priority_tasks", true); GLOBAL_DEF("threading/worker_pool/low_priority_thread_ratio", 0.3); } diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 8fcf2b24b5..829c9bf777 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -881,7 +881,7 @@ StringName TranslationServer::tool_pseudolocalize(const StringName &p_message) c String TranslationServer::get_override_string(String &p_message) const { String res; - for (int i = 0; i < p_message.size(); i++) { + for (int i = 0; i < p_message.length(); i++) { if (pseudolocalization_skip_placeholders_enabled && is_placeholder(p_message, i)) { res += p_message[i]; res += p_message[i + 1]; @@ -895,7 +895,7 @@ String TranslationServer::get_override_string(String &p_message) const { String TranslationServer::double_vowels(String &p_message) const { String res; - for (int i = 0; i < p_message.size(); i++) { + for (int i = 0; i < p_message.length(); i++) { if (pseudolocalization_skip_placeholders_enabled && is_placeholder(p_message, i)) { res += p_message[i]; res += p_message[i + 1]; @@ -913,7 +913,7 @@ String TranslationServer::double_vowels(String &p_message) const { String TranslationServer::replace_with_accented_string(String &p_message) const { String res; - for (int i = 0; i < p_message.size(); i++) { + for (int i = 0; i < p_message.length(); i++) { if (pseudolocalization_skip_placeholders_enabled && is_placeholder(p_message, i)) { res += p_message[i]; res += p_message[i + 1]; @@ -936,7 +936,7 @@ String TranslationServer::wrap_with_fakebidi_characters(String &p_message) const char32_t fakebidisuffix = U'\u202c'; res += fakebidiprefix; // The fake bidi unicode gets popped at every newline so pushing it back at every newline. - for (int i = 0; i < p_message.size(); i++) { + for (int i = 0; i < p_message.length(); i++) { if (p_message[i] == '\n') { res += fakebidisuffix; res += p_message[i]; @@ -978,7 +978,7 @@ const char32_t *TranslationServer::get_accented_version(char32_t p_character) co } bool TranslationServer::is_placeholder(String &p_message, int p_index) const { - return p_index < p_message.size() - 1 && p_message[p_index] == '%' && + return p_index < p_message.length() - 1 && p_message[p_index] == '%' && (p_message[p_index + 1] == 's' || p_message[p_index + 1] == 'c' || p_message[p_index + 1] == 'd' || p_message[p_index + 1] == 'o' || p_message[p_index + 1] == 'x' || p_message[p_index + 1] == 'X' || p_message[p_index + 1] == 'f'); } diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index a24cff4f11..6afe28a6a7 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1117,7 +1117,7 @@ String String::get_with_code_lines() const { return ret; } -int String::get_slice_count(String p_splitter) const { +int String::get_slice_count(const String &p_splitter) const { if (is_empty()) { return 0; } @@ -1136,7 +1136,7 @@ int String::get_slice_count(String p_splitter) const { return slices; } -String String::get_slice(String p_splitter, int p_slice) const { +String String::get_slice(const String &p_splitter, int p_slice) const { if (is_empty() || p_splitter.is_empty()) { return ""; } @@ -3515,7 +3515,7 @@ bool String::matchn(const String &p_wildcard) const { return _wildcard_match(p_wildcard.get_data(), get_data(), false); } -String String::format(const Variant &values, String placeholder) const { +String String::format(const Variant &values, const String &placeholder) const { String new_string = String(this->ptr()); if (values.get_type() == Variant::ARRAY) { @@ -3961,27 +3961,42 @@ static int _humanize_digits(int p_num) { } String String::humanize_size(uint64_t p_size) { + int magnitude = 0; uint64_t _div = 1; - Vector<String> prefixes; - prefixes.push_back(RTR("B")); - prefixes.push_back(RTR("KiB")); - prefixes.push_back(RTR("MiB")); - prefixes.push_back(RTR("GiB")); - prefixes.push_back(RTR("TiB")); - prefixes.push_back(RTR("PiB")); - prefixes.push_back(RTR("EiB")); - - int prefix_idx = 0; - - while (prefix_idx < prefixes.size() - 1 && p_size > (_div * 1024)) { + while (p_size > _div * 1024 && magnitude < 6) { _div *= 1024; - prefix_idx++; + magnitude++; } - const int digits = prefix_idx > 0 ? _humanize_digits(p_size / _div) : 0; - const double divisor = prefix_idx > 0 ? _div : 1; + if (magnitude == 0) { + return String::num(p_size) + " " + RTR("B"); + } else { + String suffix; + switch (magnitude) { + case 1: + suffix = RTR("KiB"); + break; + case 2: + suffix = RTR("MiB"); + break; + case 3: + suffix = RTR("GiB"); + break; + case 4: + suffix = RTR("TiB"); + break; + case 5: + suffix = RTR("PiB"); + break; + case 6: + suffix = RTR("EiB"); + break; + } - return String::num(p_size / divisor).pad_decimals(digits) + " " + prefixes[prefix_idx]; + const double divisor = _div; + const int digits = _humanize_digits(p_size / _div); + return String::num(p_size / divisor).pad_decimals(digits) + " " + suffix; + } } bool String::is_absolute_path() const { @@ -4569,7 +4584,7 @@ bool String::is_valid_ip_address() const { if (find(":") >= 0) { Vector<String> ip = split(":"); for (int i = 0; i < ip.size(); i++) { - String n = ip[i]; + const String &n = ip[i]; if (n.is_empty()) { continue; } @@ -4591,7 +4606,7 @@ bool String::is_valid_ip_address() const { return false; } for (int i = 0; i < ip.size(); i++) { - String n = ip[i]; + const String &n = ip[i]; if (!n.is_valid_int()) { return false; } @@ -5208,7 +5223,7 @@ String String::sprintf(const Array &values, bool *error) const { return formatted; } -String String::quote(String quotechar) const { +String String::quote(const String "echar) const { return quotechar + *this + quotechar; } diff --git a/core/string/ustring.h b/core/string/ustring.h index 897b06fc6d..5ed20396d6 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -299,7 +299,7 @@ public: bool is_quoted() const; Vector<String> bigrams() const; float similarity(const String &p_string) const; - String format(const Variant &values, String placeholder = "{_}") const; + String format(const Variant &values, const String &placeholder = "{_}") const; String replace_first(const String &p_key, const String &p_with) const; String replace(const String &p_key, const String &p_with) const; String replace(const char *p_key, const char *p_with) const; @@ -315,7 +315,7 @@ public: String lpad(int min_length, const String &character = " ") const; String rpad(int min_length, const String &character = " ") const; String sprintf(const Array &values, bool *error) const; - String quote(String quotechar = "\"") const; + String quote(const String "echar = "\"") const; String unquote() const; static String num(double p_num, int p_decimals = -1); static String num_scientific(double p_num); @@ -349,8 +349,8 @@ public: String to_snake_case() const; String get_with_code_lines() const; - int get_slice_count(String p_splitter) const; - String get_slice(String p_splitter, int p_slice) const; + int get_slice_count(const String &p_splitter) const; + String get_slice(const String &p_splitter, int p_slice) const; String get_slicec(char32_t p_splitter, int p_slice) const; Vector<String> split(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h index 7e480653ac..b1010f7f43 100644 --- a/core/templates/command_queue_mt.h +++ b/core/templates/command_queue_mt.h @@ -31,6 +31,7 @@ #ifndef COMMAND_QUEUE_MT_H #define COMMAND_QUEUE_MT_H +#include "core/object/worker_thread_pool.h" #include "core/os/memory.h" #include "core/os/mutex.h" #include "core/os/semaphore.h" @@ -306,15 +307,15 @@ class CommandQueueMT { struct CommandBase { virtual void call() = 0; - virtual void post() {} - virtual ~CommandBase() {} + virtual SyncSemaphore *get_sync_semaphore() { return nullptr; } + virtual ~CommandBase() = default; // Won't be called. }; struct SyncCommand : public CommandBase { SyncSemaphore *sync_sem = nullptr; - virtual void post() override { - sync_sem->sem.post(); + virtual SyncSemaphore *get_sync_semaphore() override { + return sync_sem; } }; @@ -340,6 +341,7 @@ class CommandQueueMT { SyncSemaphore sync_sems[SYNC_SEMAPHORES]; Mutex mutex; Semaphore *sync = nullptr; + uint64_t flush_read_ptr = 0; template <class T> T *allocate() { @@ -362,31 +364,41 @@ class CommandQueueMT { void _flush() { lock(); - uint64_t read_ptr = 0; - uint64_t limit = command_mem.size(); - - while (read_ptr < limit) { - uint64_t size = *(uint64_t *)&command_mem[read_ptr]; - read_ptr += 8; - CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[read_ptr]); - - cmd->call(); //execute the function - cmd->post(); //release in case it needs sync/ret - cmd->~CommandBase(); //should be done, so erase the command - - read_ptr += size; + WorkerThreadPool::thread_enter_command_queue_mt_flush(this); + while (flush_read_ptr < command_mem.size()) { + uint64_t size = *(uint64_t *)&command_mem[flush_read_ptr]; + flush_read_ptr += 8; + CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[flush_read_ptr]); + + SyncSemaphore *sync_sem = cmd->get_sync_semaphore(); + cmd->call(); + if (sync_sem) { + sync_sem->sem.post(); // Release in case it needs sync/ret. + } + + if (unlikely(flush_read_ptr == 0)) { + // A reentrant call flushed. + DEV_ASSERT(command_mem.is_empty()); + unlock(); + return; + } + + flush_read_ptr += size; } + WorkerThreadPool::thread_exit_command_queue_mt_flush(); command_mem.clear(); + flush_read_ptr = 0; unlock(); } - void lock(); - void unlock(); void wait_for_flush(); SyncSemaphore *_alloc_sync_sem(); public: + void lock(); + void unlock(); + /* NORMAL PUSH COMMANDS */ DECL_PUSH(0) SPACE_SEP_LIST(DECL_PUSH, 15) diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h index 6f3f78d4d2..d880eae0c3 100644 --- a/core/templates/paged_allocator.h +++ b/core/templates/paged_allocator.h @@ -40,7 +40,7 @@ #include <type_traits> #include <typeinfo> -template <class T, bool thread_safe = false> +template <class T, bool thread_safe = false, uint32_t DEFAULT_PAGE_SIZE = 4096> class PagedAllocator { T **page_pool = nullptr; T ***available_pool = nullptr; @@ -53,10 +53,6 @@ class PagedAllocator { SpinLock spin_lock; public: - enum { - DEFAULT_PAGE_SIZE = 4096 - }; - template <class... Args> T *alloc(Args &&...p_args) { if (thread_safe) { diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h index 863e3eef11..69a792958a 100644 --- a/core/templates/paged_array.h +++ b/core/templates/paged_array.h @@ -53,7 +53,12 @@ class PagedArrayPool { SpinLock spin_lock; public: - uint32_t alloc_page() { + struct PageInfo { + T *page = nullptr; + uint32_t page_id = 0; + }; + + PageInfo alloc_page() { spin_lock.lock(); if (unlikely(pages_available == 0)) { uint32_t pages_used = pages_allocated; @@ -69,13 +74,11 @@ public: } pages_available--; - uint32_t page = available_page_pool[pages_available]; + uint32_t page_id = available_page_pool[pages_available]; + T *page = page_pool[page_id]; spin_lock.unlock(); - return page; - } - T *get_page(uint32_t p_page_id) { - return page_pool[p_page_id]; + return PageInfo{ page, page_id }; } void free_page(uint32_t p_page_id) { @@ -190,9 +193,9 @@ public: _grow_page_array(); //keep out of inline } - uint32_t page_id = page_pool->alloc_page(); - page_data[page_count] = page_pool->get_page(page_id); - page_ids[page_count] = page_id; + typename PagedArrayPool<T>::PageInfo page_info = page_pool->alloc_page(); + page_data[page_count] = page_info.page; + page_ids[page_count] = page_info.page_id; } // place the new value diff --git a/core/templates/self_list.h b/core/templates/self_list.h index fdf91beacc..afa0501c75 100644 --- a/core/templates/self_list.h +++ b/core/templates/self_list.h @@ -159,6 +159,9 @@ public: _FORCE_INLINE_ SelfList<T> *first() { return _first; } _FORCE_INLINE_ const SelfList<T> *first() const { return _first; } + // Forbid copying, which has broken behavior. + void operator=(const List &) = delete; + _FORCE_INLINE_ List() {} _FORCE_INLINE_ ~List() { // A self list must be empty on destruction. @@ -185,6 +188,9 @@ public: _FORCE_INLINE_ const SelfList<T> *prev() const { return _prev; } _FORCE_INLINE_ T *self() const { return _self; } + // Forbid copying, which has broken behavior. + void operator=(const SelfList<T> &) = delete; + _FORCE_INLINE_ SelfList(T *p_self) { _self = p_self; } diff --git a/core/typedefs.h b/core/typedefs.h index 803b2e5ae0..8b04960b9a 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -233,6 +233,10 @@ constexpr T get_num_bits(T x) { #define BSWAP16(x) __builtin_bswap16(x) #define BSWAP32(x) __builtin_bswap32(x) #define BSWAP64(x) __builtin_bswap64(x) +#elif defined(_MSC_VER) +#define BSWAP16(x) _byteswap_ushort(x) +#define BSWAP32(x) _byteswap_ulong(x) +#define BSWAP64(x) _byteswap_uint64(x) #else static inline uint16_t BSWAP16(uint16_t x) { return (x >> 8) | (x << 8); diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp index 0b1174c873..55f687bdf9 100644 --- a/core/variant/callable.cpp +++ b/core/variant/callable.cpp @@ -31,13 +31,12 @@ #include "callable.h" #include "callable_bind.h" -#include "core/object/message_queue.h" #include "core/object/object.h" #include "core/object/ref_counted.h" #include "core/object/script_language.h" void Callable::call_deferredp(const Variant **p_arguments, int p_argcount) const { - MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount); + MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount, true); } void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const { diff --git a/core/variant/variant.h b/core/variant/variant.h index 480f21df98..602d287f22 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -572,6 +572,7 @@ public: static ValidatedBuiltInMethod get_validated_builtin_method(Variant::Type p_type, const StringName &p_method); static PTRBuiltInMethod get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method); + static MethodInfo get_builtin_method_info(Variant::Type p_type, const StringName &p_method); static int get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method); static Variant::Type get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument); static String get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument); @@ -707,9 +708,20 @@ public: bool has_key(const Variant &p_key, bool &r_valid) const; /* Generic */ - - void set(const Variant &p_index, const Variant &p_value, bool *r_valid = nullptr); - Variant get(const Variant &p_index, bool *r_valid = nullptr) const; + enum VariantSetError { + SET_OK, + SET_KEYED_ERR, + SET_NAMED_ERR, + SET_INDEXED_ERR + }; + enum VariantGetError { + GET_OK, + GET_KEYED_ERR, + GET_NAMED_ERR, + GET_INDEXED_ERR + }; + void set(const Variant &p_index, const Variant &p_value, bool *r_valid = nullptr, VariantSetError *err_code = nullptr); + Variant get(const Variant &p_index, bool *r_valid = nullptr, VariantGetError *err_code = nullptr) const; bool in(const Variant &p_index, bool *r_valid = nullptr) const; bool iter_init(Variant &r_iter, bool &r_valid) const; @@ -769,8 +781,8 @@ public: static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr); static void get_enums_for_type(Variant::Type p_type, List<StringName> *p_enums); - static void get_enumerations_for_enum(Variant::Type p_type, StringName p_enum_name, List<StringName> *p_enumerations); - static int get_enum_value(Variant::Type p_type, StringName p_enum_name, StringName p_enumeration, bool *r_valid = nullptr); + static void get_enumerations_for_enum(Variant::Type p_type, const StringName &p_enum_name, List<StringName> *p_enumerations); + static int get_enum_value(Variant::Type p_type, const StringName &p_enum_name, const StringName &p_enumeration, bool *r_valid = nullptr); typedef String (*ObjectDeConstruct)(const Variant &p_object, void *ud); typedef void (*ObjectConstruct)(const String &p_text, void *ud, Variant &r_value); diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 7121b4da96..03836985f3 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1071,14 +1071,14 @@ struct _VariantCall { static ConstantData *constant_data; - static void add_constant(int p_type, StringName p_constant_name, int64_t p_constant_value) { + static void add_constant(int p_type, const StringName &p_constant_name, int64_t p_constant_value) { constant_data[p_type].value[p_constant_name] = p_constant_value; #ifdef DEBUG_ENABLED constant_data[p_type].value_ordered.push_back(p_constant_name); #endif } - static void add_variant_constant(int p_type, StringName p_constant_name, const Variant &p_constant_value) { + static void add_variant_constant(int p_type, const StringName &p_constant_name, const Variant &p_constant_value) { constant_data[p_type].variant_value[p_constant_name] = p_constant_value; #ifdef DEBUG_ENABLED constant_data[p_type].variant_value_ordered.push_back(p_constant_name); @@ -1091,7 +1091,7 @@ struct _VariantCall { static EnumData *enum_data; - static void add_enum_constant(int p_type, StringName p_enum_type_name, StringName p_enumeration_name, int p_enum_value) { + static void add_enum_constant(int p_type, const StringName &p_enum_type_name, const StringName &p_enumeration_name, int p_enum_value) { enum_data[p_type].value[p_enum_type_name][p_enumeration_name] = p_enum_value; } }; @@ -1114,6 +1114,46 @@ struct VariantBuiltInMethodInfo { Variant::Type return_type; int argument_count = 0; Variant::Type (*get_argument_type)(int p_arg) = nullptr; + + MethodInfo get_method_info(const StringName &p_name) const { + MethodInfo mi; + mi.name = p_name; + + if (has_return_type) { + mi.return_val.type = return_type; + if (mi.return_val.type == Variant::NIL) { + mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } + } + + if (is_const) { + mi.flags |= METHOD_FLAG_CONST; + } + if (is_vararg) { + mi.flags |= METHOD_FLAG_VARARG; + } + if (is_static) { + mi.flags |= METHOD_FLAG_STATIC; + } + + for (int i = 0; i < argument_count; i++) { + PropertyInfo pi; +#ifdef DEBUG_METHODS_ENABLED + pi.name = argument_names[i]; +#else + pi.name = "arg" + itos(i + 1); +#endif + pi.type = (*get_argument_type)(i); + if (pi.type == Variant::NIL) { + pi.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } + mi.arguments.push_back(pi); + } + + mi.default_arguments = default_arguments; + + return mi; + } }; typedef OAHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap; @@ -1268,6 +1308,13 @@ Variant::PTRBuiltInMethod Variant::get_ptr_builtin_method(Variant::Type p_type, return method->ptrcall; } +MethodInfo Variant::get_builtin_method_info(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, MethodInfo()); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_NULL_V(method, MethodInfo()); + return method->get_method_info(p_method); +} + int Variant::get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method) { ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); @@ -1378,43 +1425,7 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const { for (const StringName &E : builtin_method_names[type]) { const VariantBuiltInMethodInfo *method = builtin_method_info[type].lookup_ptr(E); ERR_CONTINUE(!method); - - MethodInfo mi; - mi.name = E; - - //return type - if (method->has_return_type) { - mi.return_val.type = method->return_type; - if (mi.return_val.type == Variant::NIL) { - mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; - } - } - - if (method->is_const) { - mi.flags |= METHOD_FLAG_CONST; - } - if (method->is_vararg) { - mi.flags |= METHOD_FLAG_VARARG; - } - if (method->is_static) { - mi.flags |= METHOD_FLAG_STATIC; - } - for (int i = 0; i < method->argument_count; i++) { - PropertyInfo pi; -#ifdef DEBUG_METHODS_ENABLED - pi.name = method->argument_names[i]; -#else - pi.name = "arg" + itos(i + 1); -#endif - pi.type = method->get_argument_type(i); - if (pi.type == Variant::NIL) { - pi.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; - } - mi.arguments.push_back(pi); - } - - mi.default_arguments = method->default_arguments; - p_list->push_back(mi); + p_list->push_back(method->get_method_info(E)); } } } @@ -1493,7 +1504,7 @@ void Variant::get_enums_for_type(Variant::Type p_type, List<StringName> *p_enums } } -void Variant::get_enumerations_for_enum(Variant::Type p_type, StringName p_enum_name, List<StringName> *p_enumerations) { +void Variant::get_enumerations_for_enum(Variant::Type p_type, const StringName &p_enum_name, List<StringName> *p_enumerations) { ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); _VariantCall::EnumData &enum_data = _VariantCall::enum_data[p_type]; @@ -1505,7 +1516,7 @@ void Variant::get_enumerations_for_enum(Variant::Type p_type, StringName p_enum_ } } -int Variant::get_enum_value(Variant::Type p_type, StringName p_enum_name, StringName p_enumeration, bool *r_valid) { +int Variant::get_enum_value(Variant::Type p_type, const StringName &p_enum_name, const StringName &p_enumeration, bool *r_valid) { if (r_valid) { *r_valid = false; } @@ -1796,6 +1807,8 @@ static void _register_variant_builtin_methods() { bind_method(Vector2i, aspect, sarray(), varray()); bind_method(Vector2i, max_axis_index, sarray(), varray()); bind_method(Vector2i, min_axis_index, sarray(), varray()); + bind_method(Vector2i, distance_to, sarray("to"), varray()); + bind_method(Vector2i, distance_squared_to, sarray("to"), varray()); bind_method(Vector2i, length, sarray(), varray()); bind_method(Vector2i, length_squared, sarray(), varray()); bind_method(Vector2i, sign, sarray(), varray()); @@ -1886,6 +1899,8 @@ static void _register_variant_builtin_methods() { bind_method(Vector3i, min_axis_index, sarray(), varray()); bind_method(Vector3i, max_axis_index, sarray(), varray()); + bind_method(Vector3i, distance_to, sarray("to"), varray()); + bind_method(Vector3i, distance_squared_to, sarray("to"), varray()); bind_method(Vector3i, length, sarray(), varray()); bind_method(Vector3i, length_squared, sarray(), varray()); bind_method(Vector3i, sign, sarray(), varray()); @@ -1932,6 +1947,8 @@ static void _register_variant_builtin_methods() { bind_method(Vector4i, abs, sarray(), varray()); bind_method(Vector4i, clamp, sarray("min", "max"), varray()); bind_method(Vector4i, snapped, sarray("step"), varray()); + bind_method(Vector4i, distance_to, sarray("to"), varray()); + bind_method(Vector4i, distance_squared_to, sarray("to"), varray()); /* Plane */ diff --git a/core/variant/variant_callable.cpp b/core/variant/variant_callable.cpp new file mode 100644 index 0000000000..dc31b6d1ac --- /dev/null +++ b/core/variant/variant_callable.cpp @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* variant_callable.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "variant_callable.h" + +#include "core/templates/hashfuncs.h" + +bool VariantCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) { + return p_a->hash() == p_b->hash(); +} + +bool VariantCallable::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) { + return p_a->hash() < p_b->hash(); +} + +uint32_t VariantCallable::hash() const { + return h; +} + +String VariantCallable::get_as_text() const { + return vformat("%s::%s (Callable)", Variant::get_type_name(variant.get_type()), method); +} + +CallableCustom::CompareEqualFunc VariantCallable::get_compare_equal_func() const { + return compare_equal; +} + +CallableCustom::CompareLessFunc VariantCallable::get_compare_less_func() const { + return compare_less; +} + +bool VariantCallable::is_valid() const { + return Variant::has_builtin_method(variant.get_type(), method); +} + +StringName VariantCallable::get_method() const { + return method; +} + +ObjectID VariantCallable::get_object() const { + return ObjectID(); +} + +void VariantCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { + Variant v = variant; + v.callp(method, p_arguments, p_argcount, r_return_value, r_call_error); +} + +VariantCallable::VariantCallable(const Variant &p_variant, const StringName &p_method) { + variant = p_variant; + method = p_method; + h = variant.hash(); + h = hash_murmur3_one_64(Variant::get_builtin_method_hash(variant.get_type(), method), h); +} diff --git a/core/variant/variant_callable.h b/core/variant/variant_callable.h new file mode 100644 index 0000000000..3f2b058aaf --- /dev/null +++ b/core/variant/variant_callable.h @@ -0,0 +1,58 @@ +/**************************************************************************/ +/* variant_callable.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef VARIANT_CALLABLE_H +#define VARIANT_CALLABLE_H + +#include "core/variant/callable.h" +#include "core/variant/variant.h" + +class VariantCallable : public CallableCustom { + Variant variant; + StringName method; + uint32_t h = 0; + + static bool compare_equal(const CallableCustom *p_a, const CallableCustom *p_b); + static bool compare_less(const CallableCustom *p_a, const CallableCustom *p_b); + +public: + uint32_t hash() const override; + String get_as_text() const override; + CompareEqualFunc get_compare_equal_func() const override; + CompareLessFunc get_compare_less_func() const override; + bool is_valid() const override; + StringName get_method() const override; + ObjectID get_object() const override; + void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; + + VariantCallable(const Variant &p_variant, const StringName &p_method); +}; + +#endif // VARIANT_CALLABLE_H diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index aed83ac010..4f9c38dc4c 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -412,6 +412,15 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorDivNZ<Vector4, Vector4i, double>>(Variant::OP_DIVIDE, Variant::VECTOR4I, Variant::FLOAT); register_op<OperatorEvaluatorDivNZ<Vector4i, Vector4i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR4I, Variant::INT); + register_op<OperatorEvaluatorDiv<Transform2D, Transform2D, int64_t>>(Variant::OP_DIVIDE, Variant::TRANSFORM2D, Variant::INT); + register_op<OperatorEvaluatorDiv<Transform2D, Transform2D, double>>(Variant::OP_DIVIDE, Variant::TRANSFORM2D, Variant::FLOAT); + + register_op<OperatorEvaluatorDiv<Transform3D, Transform3D, int64_t>>(Variant::OP_DIVIDE, Variant::TRANSFORM3D, Variant::INT); + register_op<OperatorEvaluatorDiv<Transform3D, Transform3D, double>>(Variant::OP_DIVIDE, Variant::TRANSFORM3D, Variant::FLOAT); + + register_op<OperatorEvaluatorDiv<Basis, Basis, int64_t>>(Variant::OP_DIVIDE, Variant::BASIS, Variant::INT); + register_op<OperatorEvaluatorDiv<Basis, Basis, double>>(Variant::OP_DIVIDE, Variant::BASIS, Variant::FLOAT); + register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, double>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::FLOAT); register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, int64_t>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::INT); diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index 05f7abf32c..50c9c10987 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -30,6 +30,8 @@ #include "variant_setget.h" +#include "variant_callable.h" + struct VariantSetterGetterInfo { void (*setter)(Variant *base, const Variant *value, bool &valid); void (*getter)(const Variant *base, Variant *value); @@ -264,42 +266,45 @@ void Variant::set_named(const StringName &p_member, const Variant &p_value, bool } Variant Variant::get_named(const StringName &p_member, bool &r_valid) const { - Variant ret; uint32_t s = variant_setters_getters[type].size(); if (s) { for (uint32_t i = 0; i < s; i++) { if (variant_setters_getters_names[type][i] == p_member) { + Variant ret; variant_setters_getters[type][i].getter(this, &ret); r_valid = true; return ret; } } + } - r_valid = false; - - } else if (type == Variant::OBJECT) { - Object *obj = get_validated_object(); - if (!obj) { - r_valid = false; - return "Instance base is null."; - } else { - return obj->get(p_member, &r_valid); - } - } else if (type == Variant::DICTIONARY) { - const Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member); - if (v) { - r_valid = true; - - return *v; - } else { - r_valid = false; - } - - } else { - r_valid = false; + switch (type) { + case Variant::OBJECT: { + Object *obj = get_validated_object(); + if (!obj) { + r_valid = false; + return "Instance base is null."; + } else { + return obj->get(p_member, &r_valid); + } + } break; + case Variant::DICTIONARY: { + const Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member); + if (v) { + r_valid = true; + return *v; + } + } break; + default: { + if (Variant::has_builtin_method(type, p_member)) { + r_valid = true; + return Callable(memnew(VariantCallable(*this, p_member))); + } + } break; } - return ret; + r_valid = false; + return Variant(); } /**** INDEXED SETTERS AND GETTERS ****/ @@ -1166,30 +1171,48 @@ bool Variant::has_key(const Variant &p_key, bool &r_valid) const { } } -void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) { +void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid, VariantSetError *err_code) { + if (err_code) { + *err_code = VariantSetError::SET_OK; + } if (type == DICTIONARY || type == OBJECT) { bool valid; set_keyed(p_index, p_value, valid); if (r_valid) { *r_valid = valid; + if (!valid && err_code) { + *err_code = VariantSetError::SET_KEYED_ERR; + } } } else { bool valid = false; if (p_index.get_type() == STRING_NAME) { set_named(*VariantGetInternalPtr<StringName>::get_ptr(&p_index), p_value, valid); + if (!valid && err_code) { + *err_code = VariantSetError::SET_NAMED_ERR; + } } else if (p_index.get_type() == INT) { bool obb; set_indexed(*VariantGetInternalPtr<int64_t>::get_ptr(&p_index), p_value, valid, obb); if (obb) { valid = false; + if (err_code) { + *err_code = VariantSetError::SET_INDEXED_ERR; + } } } else if (p_index.get_type() == STRING) { // less efficient version of named set_named(*VariantGetInternalPtr<String>::get_ptr(&p_index), p_value, valid); + if (!valid && err_code) { + *err_code = VariantSetError::SET_NAMED_ERR; + } } else if (p_index.get_type() == FLOAT) { // less efficient version of indexed bool obb; set_indexed(*VariantGetInternalPtr<double>::get_ptr(&p_index), p_value, valid, obb); if (obb) { valid = false; + if (err_code) { + *err_code = VariantSetError::SET_INDEXED_ERR; + } } } if (r_valid) { @@ -1198,31 +1221,49 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } } -Variant Variant::get(const Variant &p_index, bool *r_valid) const { +Variant Variant::get(const Variant &p_index, bool *r_valid, VariantGetError *err_code) const { + if (err_code) { + *err_code = VariantGetError::GET_OK; + } Variant ret; if (type == DICTIONARY || type == OBJECT) { bool valid; ret = get_keyed(p_index, valid); if (r_valid) { *r_valid = valid; + if (!valid && err_code) { + *err_code = VariantGetError::GET_KEYED_ERR; + } } } else { bool valid = false; if (p_index.get_type() == STRING_NAME) { ret = get_named(*VariantGetInternalPtr<StringName>::get_ptr(&p_index), valid); + if (!valid && err_code) { + *err_code = VariantGetError::GET_NAMED_ERR; + } } else if (p_index.get_type() == INT) { bool obb; ret = get_indexed(*VariantGetInternalPtr<int64_t>::get_ptr(&p_index), valid, obb); if (obb) { valid = false; + if (err_code) { + *err_code = VariantGetError::GET_INDEXED_ERR; + } } } else if (p_index.get_type() == STRING) { // less efficient version of named ret = get_named(*VariantGetInternalPtr<String>::get_ptr(&p_index), valid); + if (!valid && err_code) { + *err_code = VariantGetError::GET_NAMED_ERR; + } } else if (p_index.get_type() == FLOAT) { // less efficient version of indexed bool obb; ret = get_indexed(*VariantGetInternalPtr<double>::get_ptr(&p_index), valid, obb); if (obb) { valid = false; + if (err_code) { + *err_code = VariantGetError::GET_INDEXED_ERR; + } } } if (r_valid) { diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 77c5a168f3..d72fc61394 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -234,20 +234,9 @@ var b = clamp(8.1, 0.9, 5.5) # b is 5.5 - - var c = clamp(Vector2(-3.5, -4), Vector2(-3.2, -2), Vector2(2, 6.5)) - # c is (-3.2, -2) - - var d = clamp(Vector2i(7, 8), Vector2i(-3, -2), Vector2i(2, 6)) - # d is (2, 6) - - var e = clamp(Vector3(-7, 8.5, -3.8), Vector3(-3, -2, 5.4), Vector3(-2, 6, -4.1)) - # e is (-3, -2, 5.4) - - var f = clamp(Vector3i(-7, -8, -9), Vector3i(-1, 2, 3), Vector3i(-4, -5, -6)) - # f is (-4, -5, -6) [/codeblock] - [b]Note:[/b] For better type safety, use [method clampf], [method clampi], [method Vector2.clamp], [method Vector2i.clamp], [method Vector3.clamp], [method Vector3i.clamp], [method Vector4.clamp], [method Vector4i.clamp], or [method Color.clamp]. + [b]Note:[/b] For better type safety, use [method clampf], [method clampi], [method Vector2.clamp], [method Vector2i.clamp], [method Vector3.clamp], [method Vector3i.clamp], [method Vector4.clamp], [method Vector4i.clamp], or [method Color.clamp] (not currently supported by this method). + [b]Note:[/b] When using this on vectors it will [i]not[/i] perform component-wise clamping, and will pick [param min] if [code]value < min[/code] or [param max] if [code]value > max[/code]. To perform component-wise clamping use the methods listed above. </description> </method> <method name="clampf"> @@ -888,6 +877,7 @@ [/codeblocks] [b]Note:[/b] Consider using [method push_error] and [method push_warning] to print error and warning messages instead of [method print] or [method print_rich]. This distinguishes them from print messages used for debugging purposes, while also displaying a stack trace when an error or warning is printed. [b]Note:[/b] On Windows, only Windows 10 and later correctly displays ANSI escape codes in standard output. + [b]Note:[/b] Output displayed in the editor supports clickable [code skip-lint][url=address]text[/url][/code] tags. The [code skip-lint][url][/code] tag's [code]address[/code] value is handled by [method OS.shell_open] when clicked. </description> </method> <method name="print_verbose" qualifiers="vararg"> diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index c1c637d2d6..427d38d421 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -4,10 +4,10 @@ A 3D axis-aligned bounding box. </brief_description> <description> - [AABB] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests. - It uses floating-point coordinates. The 2D counterpart to [AABB] is [Rect2]. - Negative values for [member size] are not supported and will not work for most methods. Use [method abs] to get an AABB with a positive size. - [b]Note:[/b] Unlike [Rect2], [AABB] does not have a variant that uses integer coordinates. + The [AABB] built-in [Variant] type represents an axis-aligned bounding box in a 3D space. It is defined by its [member position] and [member size], which are [Vector3]. It is frequently used for fast overlap tests (see [method intersects]). Although [AABB] itself is axis-aligned, it can be combined with [Transform3D] to represent a rotated or skewed bounding box. + It uses floating-point coordinates. The 2D counterpart to [AABB] is [Rect2]. There is no version of [AABB] that uses integer coordinates. + [b]Note:[/b] Negative values for [member size] are not supported. With negative size, most [AABB] methods do not work correctly. Use [method abs] to get an equivalent [AABB] with a non-negative size. + [b]Note:[/b] In a boolean context, a [AABB] evaluates to [code]false[/code] if both [member position] and [member size] are zero (equal to [constant Vector3.ZERO]). Otherwise, it always evaluates to [code]true[/code]. </description> <tutorials> <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> @@ -18,7 +18,7 @@ <constructor name="AABB"> <return type="AABB" /> <description> - Constructs a default-initialized [AABB] with default (zero) values of [member position] and [member size]. + Constructs an [AABB] with its [member position] and [member size] set to [constant Vector3.ZERO]. </description> </constructor> <constructor name="AABB"> @@ -33,7 +33,7 @@ <param index="0" name="position" type="Vector3" /> <param index="1" name="size" type="Vector3" /> <description> - Constructs an [AABB] from a position and size. + Constructs an [AABB] by [param position] and [param size]. </description> </constructor> </constructors> @@ -41,34 +41,78 @@ <method name="abs" qualifiers="const"> <return type="AABB" /> <description> - Returns an AABB with equivalent position and size, modified so that the most-negative corner is the origin and the size is positive. + Returns an [AABB] equivalent to this bounding box, with its width, height, and depth modified to be non-negative values. + [codeblocks] + [gdscript] + var box = AABB(Vector3(5, 0, 5), Vector3(-20, -10, -5)) + var absolute = box.abs() + print(absolute.position) # Prints (-15, -10, 0) + print(absolute.size) # Prints (20, 10, 5) + [/gdscript] + [csharp] + var box = new Aabb(new Vector3(5, 0, 5), new Vector3(-20, -10, -5)); + var absolute = box.Abs(); + GD.Print(absolute.Position); // Prints (-15, -10, 0) + GD.Print(absolute.Size); // Prints (20, 10, 5) + [/csharp] + [/codeblocks] + [b]Note:[/b] It's recommended to use this method when [member size] is negative, as most other methods in Godot assume that the [member size]'s components are greater than [code]0[/code]. </description> </method> <method name="encloses" qualifiers="const"> <return type="bool" /> <param index="0" name="with" type="AABB" /> <description> - Returns [code]true[/code] if this [AABB] completely encloses another one. + Returns [code]true[/code] if this bounding box [i]completely[/i] encloses the [param with] box. The edges of both boxes are included. + [codeblocks] + [gdscript] + var a = AABB(Vector3(0, 0, 0), Vector3(4, 4, 4)) + var b = AABB(Vector3(1, 1, 1), Vector3(3, 3, 3)) + var c = AABB(Vector3(2, 2, 2), Vector3(8, 8, 8)) + + print(a.encloses(a)) # Prints true + print(a.encloses(b)) # Prints true + print(a.encloses(c)) # Prints false + [/gdscript] + [csharp] + var a = new Aabb(new Vector3(0, 0, 0), new Vector3(4, 4, 4)); + var b = new Aabb(new Vector3(1, 1, 1), new Vector3(3, 3, 3)); + var c = new Aabb(new Vector3(2, 2, 2), new Vector3(8, 8, 8)); + + GD.Print(a.Encloses(a)); // Prints True + GD.Print(a.Encloses(b)); // Prints True + GD.Print(a.Encloses(c)); // Prints False + [/csharp] + [/codeblocks] </description> </method> <method name="expand" qualifiers="const"> <return type="AABB" /> <param index="0" name="to_point" type="Vector3" /> <description> - Returns a copy of this [AABB] expanded to include a given point. - [b]Example:[/b] + Returns a copy of this bounding box expanded to align the edges with the given [param to_point], if necessary. [codeblocks] [gdscript] - # position (-3, 2, 0), size (1, 1, 1) - var box = AABB(Vector3(-3, 2, 0), Vector3(1, 1, 1)) - # position (-3, -1, 0), size (3, 4, 2), so we fit both the original AABB and Vector3(0, -1, 2) - var box2 = box.expand(Vector3(0, -1, 2)) + var box = AABB(Vector3(0, 0, 0), Vector3(5, 2, 5)) + + box = box.expand(Vector3(10, 0, 0)) + print(box.position) # Prints (0, 0, 0) + print(box.size) # Prints (10, 2, 5) + + box = box.expand(Vector3(-5, 0, 5)) + print(box.position) # Prints (-5, 0, 0) + print(box.size) # Prints (15, 2, 5) [/gdscript] [csharp] - // position (-3, 2, 0), size (1, 1, 1) - var box = new Aabb(new Vector3(-3, 2, 0), new Vector3(1, 1, 1)); - // position (-3, -1, 0), size (3, 4, 2), so we fit both the original AABB and Vector3(0, -1, 2) - var box2 = box.Expand(new Vector3(0, -1, 2)); + var box = new Aabb(new Vector3(0, 0, 0), new Vector3(5, 2, 5)); + + box = box.Expand(new Vector3(10, 0, 0)); + GD.Print(box.Position); // Prints (0, 0, 0) + GD.Print(box.Size); // Prints (10, 2, 5) + + box = box.Expand(new Vector3(-5, 0, 5)); + GD.Print(box.Position); // Prints (-5, 0, 0) + GD.Print(box.Size); // Prints (15, 2, 5) [/csharp] [/codeblocks] </description> @@ -76,111 +120,188 @@ <method name="get_center" qualifiers="const"> <return type="Vector3" /> <description> - Returns the center of the [AABB], which is equal to [member position] + ([member size] / 2). + Returns the center point of the bounding box. This is the same as [code]position + (size / 2.0)[/code]. </description> </method> <method name="get_endpoint" qualifiers="const"> <return type="Vector3" /> <param index="0" name="idx" type="int" /> <description> - Gets the position of the 8 endpoints of the [AABB] in space. + Returns the position of one of the 8 vertices that compose this bounding box. With a [param idx] of [code]0[/code] this is the same as [member position], and a [param idx] of [code]7[/code] is the same as [member end]. </description> </method> <method name="get_longest_axis" qualifiers="const"> <return type="Vector3" /> <description> - Returns the normalized longest axis of the [AABB]. + Returns the longest normalized axis of this bounding box's [member size], as a [Vector3] ([constant Vector3.RIGHT], [constant Vector3.UP], or [constant Vector3.BACK]). + [codeblocks] + [gdscript] + var box = AABB(Vector3(0, 0, 0), Vector3(2, 4, 8)) + + print(box.get_longest_axis()) # Prints (0, 0, 1) + print(box.get_longest_axis_index()) # Prints 2 + print(box.get_longest_axis_size()) # Prints 8 + [/gdscript] + [csharp] + var box = new Aabb(new Vector3(0, 0, 0), new Vector3(2, 4, 8)); + + GD.Print(box.GetLongestAxis()); // Prints (0, 0, 1) + GD.Print(box.GetLongestAxisIndex()); // Prints 2 + GD.Print(box.GetLongestAxisSize()); // Prints 8 + [/csharp] + [/codeblocks] + See also [method get_longest_axis_index] and [method get_longest_axis_size]. </description> </method> <method name="get_longest_axis_index" qualifiers="const"> <return type="int" /> <description> - Returns the index of the longest axis of the [AABB] (according to [Vector3]'s [code]AXIS_*[/code] constants). + Returns the index to the longest axis of this bounding box's [member size] (see [constant Vector3.AXIS_X], [constant Vector3.AXIS_Y], and [constant Vector3.AXIS_Z]). + For an example, see [method get_longest_axis]. </description> </method> <method name="get_longest_axis_size" qualifiers="const"> <return type="float" /> <description> - Returns the scalar length of the longest axis of the [AABB]. + Returns the longest dimension of this bounding box's [member size]. + For an example, see [method get_longest_axis]. </description> </method> <method name="get_shortest_axis" qualifiers="const"> <return type="Vector3" /> <description> - Returns the normalized shortest axis of the [AABB]. + Returns the shortest normaalized axis of this bounding box's [member size], as a [Vector3] ([constant Vector3.RIGHT], [constant Vector3.UP], or [constant Vector3.BACK]). + [codeblocks] + [gdscript] + var box = AABB(Vector3(0, 0, 0), Vector3(2, 4, 8)) + + print(box.get_shortest_axis()) # Prints (1, 0, 0) + print(box.get_shortest_axis_index()) # Prints 0 + print(box.get_shortest_axis_size()) # Prints 2 + [/gdscript] + [csharp] + var box = new Aabb(new Vector3(0, 0, 0), new Vector3(2, 4, 8)); + + GD.Print(box.GetShortestAxis()); // Prints (1, 0, 0) + GD.Print(box.GetShortestAxisIndex()); // Prints 0 + GD.Print(box.GetShortestAxisSize()); // Prints 2 + [/csharp] + [/codeblocks] + See also [method get_shortest_axis_index] and [method get_shortest_axis_size]. </description> </method> <method name="get_shortest_axis_index" qualifiers="const"> <return type="int" /> <description> - Returns the index of the shortest axis of the [AABB] (according to [Vector3]::AXIS* enum). + Returns the index to the shortest axis of this bounding box's [member size] (see [constant Vector3.AXIS_X], [constant Vector3.AXIS_Y], and [constant Vector3.AXIS_Z]). + For an example, see [method get_shortest_axis]. </description> </method> <method name="get_shortest_axis_size" qualifiers="const"> <return type="float" /> <description> - Returns the scalar length of the shortest axis of the [AABB]. + Returns the shortest dimension of this bounding box's [member size]. + For an example, see [method get_shortest_axis]. </description> </method> <method name="get_support" qualifiers="const"> <return type="Vector3" /> <param index="0" name="dir" type="Vector3" /> <description> - Returns the vertex of the AABB that's the farthest in a given direction. This point is commonly known as the support point in collision detection algorithms. + Returns the vertex's position of this bounding box that's the farthest in the given direction. This point is commonly known as the support point in collision detection algorithms. </description> </method> <method name="get_volume" qualifiers="const"> <return type="float" /> <description> - Returns the volume of the [AABB]. + Returns the bounding box's volume. This is equivalent to [code]size.x * size.y * size.z[/code]. See also [method has_volume]. </description> </method> <method name="grow" qualifiers="const"> <return type="AABB" /> <param index="0" name="by" type="float" /> <description> - Returns a copy of the [AABB] grown a given number of units towards all the sides. + Returns a copy of this bounding box extended on all sides by the given amount [param by]. A negative amount shrinks the box instead. + [codeblocks] + [gdscript] + var a = AABB(Vector3(4, 4, 4), Vector3(8, 8, 8)).grow(4) + print(a.position) # Prints (0, 0, 0) + print(a.size) # Prints (16, 16, 16) + + var b = AABB(Vector3(0, 0, 0), Vector3(8, 4, 2)).grow(2) + print(b.position) # Prints (-2, -2, -2) + print(b.size) # Prints (12, 8, 6) + [/gdscript] + [csharp] + var a = new Aabb(new Vector3(4, 4, 4), new Vector3(8, 8, 8)).Grow(4); + GD.Print(a.Position); // Prints (0, 0, 0) + GD.Print(a.Size); // Prints (16, 16, 16) + + var b = new Aabb(new Vector3(0, 0, 0), new Vector3(8, 4, 2)).Grow(2); + GD.Print(b.Position); // Prints (-2, -2, -2) + GD.Print(b.Size); // Prints (12, 8, 6) + [/csharp] + [/codeblocks] </description> </method> <method name="has_point" qualifiers="const"> <return type="bool" /> <param index="0" name="point" type="Vector3" /> <description> - Returns [code]true[/code] if the [AABB] contains a point. Points on the faces of the AABB are considered included, though float-point precision errors may impact the accuracy of such checks. - [b]Note:[/b] This method is not reliable for [AABB] with a [i]negative size[/i]. Use [method abs] to get a positive sized equivalent [AABB] to check for contained points. + Returns [code]true[/code] if the bounding box contains the given [param point]. By convention, points exactly on the right, top, and front sides are [b]not[/b] included. + [b]Note:[/b] This method is not reliable for [AABB] with a [i]negative[/i] [member size]. Use [method abs] first to get a valid bounding box. </description> </method> <method name="has_surface" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if the [AABB] has a surface or a length, and [code]false[/code] if the [AABB] is empty (all components of [member size] are zero or negative). + Returns [code]true[/code] if this bounding box has a surface or a length, that is, at least one component of [member size] is greater than [code]0[/code]. Otherwise, returns [code]false[/code]. </description> </method> <method name="has_volume" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if the [AABB] has a volume, and [code]false[/code] if the [AABB] is flat, empty, or has a negative [member size]. + Returns [code]true[/code] if this bounding box's width, height, and depth are all positive. See also [method get_volume]. </description> </method> <method name="intersection" qualifiers="const"> <return type="AABB" /> <param index="0" name="with" type="AABB" /> <description> - Returns the intersection between two [AABB]. An empty AABB (size [code](0, 0, 0)[/code]) is returned on failure. + Returns the intersection between this bounding box and [param with]. If the boxes do not intersect, returns an empty [AABB]. If the boxes intersect at the edge, returns a flat [AABB] with no volume (see [method has_surface] and [method has_volume]). + [codeblocks] + [gdscript] + var box1 = AABB(Vector3(0, 0, 0), Vector3(5, 2, 8)) + var box2 = AABB(Vector3(2, 0, 2), Vector3(8, 4, 4)) + + var intersection = box1.intersection(box2) + print(intersection.position) # Prints (2, 0, 2) + print(intersection.size) # Prints (3, 2, 4) + [/gdscript] + [csharp] + var box1 = new Aabb(new Vector3(0, 0, 0), new Vector3(5, 2, 8)); + var box2 = new Aabb(new Vector3(2, 0, 2), new Vector3(8, 4, 4)); + + var intersection = box1.Intersection(box2); + GD.Print(intersection.Position); // Prints (2, 0, 2) + GD.Print(intersection.Size); // Prints (3, 2, 4) + [/csharp] + [/codeblocks] + [b]Note:[/b] If you only need to know whether two bounding boxes are intersecting, use [method intersects], instead. </description> </method> <method name="intersects" qualifiers="const"> <return type="bool" /> <param index="0" name="with" type="AABB" /> <description> - Returns [code]true[/code] if the [AABB] overlaps with another. + Returns [code]true[/code] if this bounding box overlaps with the box [param with]. The edges of both boxes are [i]always[/i] excluded. </description> </method> <method name="intersects_plane" qualifiers="const"> <return type="bool" /> <param index="0" name="plane" type="Plane" /> <description> - Returns [code]true[/code] if the [AABB] is on both sides of a plane. + Returns [code]true[/code] if this bounding box is on both sides of the given [param plane]. </description> </method> <method name="intersects_ray" qualifiers="const"> @@ -188,7 +309,8 @@ <param index="0" name="from" type="Vector3" /> <param index="1" name="dir" type="Vector3" /> <description> - Returns the point of intersection of the given ray with this [AABB] or [code]null[/code] if there is no intersection. Ray length is infinite. + Returns the first point where this bounding box and the given ray intersect, as a [Vector3]. If no intersection occurs, returns [code]null[/code]. + The ray begin at [param from], faces [param dir] and extends towards infinity. </description> </method> <method name="intersects_segment" qualifiers="const"> @@ -196,40 +318,41 @@ <param index="0" name="from" type="Vector3" /> <param index="1" name="to" type="Vector3" /> <description> - Returns the point of intersection between [param from] and [param to] with this [AABB] or [code]null[/code] if there is no intersection. + Returns the first point where this bounding box and the given segment intersect, as a [Vector3]. If no intersection occurs, returns [code]null[/code]. + The segment begins at [param from] and ends at [param to]. </description> </method> <method name="is_equal_approx" qualifiers="const"> <return type="bool" /> <param index="0" name="aabb" type="AABB" /> <description> - Returns [code]true[/code] if this [AABB] and [param aabb] are approximately equal, by calling [method @GlobalScope.is_equal_approx] on each component. + Returns [code]true[/code] if this bounding box and [param aabb] are approximately equal, by calling [method Vector2.is_equal_approx] on the [member position] and the [member size]. </description> </method> <method name="is_finite" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if this [AABB] is finite, by calling [method @GlobalScope.is_finite] on each component. + Returns [code]true[/code] if this bounding box's values are finite, by calling [method Vector2.is_finite] on the [member position] and the [member size]. </description> </method> <method name="merge" qualifiers="const"> <return type="AABB" /> <param index="0" name="with" type="AABB" /> <description> - Returns a larger [AABB] that contains both this [AABB] and [param with]. + Returns an [AABB] that encloses both this bounding box and [param with] around the edges. See also [method encloses]. </description> </method> </methods> <members> <member name="end" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> - Ending corner. This is calculated as [code]position + size[/code]. Setting this value will change the size. + The ending point. This is usually the corner on the top-right and forward of the bounding box, and is equivalent to [code]position + size[/code]. Setting this point affects the [member size]. </member> <member name="position" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> - Beginning corner. Typically has values lower than [member end]. + The origin point. This is usually the corner on the bottom-left and back of the bounding box. </member> <member name="size" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> - Size from [member position] to [member end]. Typically, all components are positive. - If the size is negative, you can use [method abs] to fix it. + The bounding box's width, height, and depth starting from [member position]. Setting this value also affects the [member end] point. + [b]Note:[/b] It's recommended setting the width, height, and depth to non-negative values. This is because most methods in Godot assume that the [member position] is the bottom-left-back corner, and the [member end] is the top-right-forward corner. To get an equivalent bounding box with non-negative size, use [method abs]. </member> </members> <operators> @@ -237,7 +360,7 @@ <return type="bool" /> <param index="0" name="right" type="AABB" /> <description> - Returns [code]true[/code] if the AABBs are not equal. + Returns [code]true[/code] if the [member position] or [member size] of both bounding boxes are not equal. [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> @@ -254,7 +377,7 @@ <return type="bool" /> <param index="0" name="right" type="AABB" /> <description> - Returns [code]true[/code] if the AABBs are exactly equal. + Returns [code]true[/code] if both [member position] and [member size] of the bounding boxes are exactly equal, respectively. [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> diff --git a/doc/classes/AStarGrid2D.xml b/doc/classes/AStarGrid2D.xml index 277630588a..7764233116 100644 --- a/doc/classes/AStarGrid2D.xml +++ b/doc/classes/AStarGrid2D.xml @@ -157,6 +157,9 @@ </method> </methods> <members> + <member name="cell_shape" type="int" setter="set_cell_shape" getter="get_cell_shape" enum="AStarGrid2D.CellShape" default="0"> + The cell shape. Affects how the positions are placed in the grid. If changed, [method update] needs to be called before finding the next path. + </member> <member name="cell_size" type="Vector2" setter="set_cell_size" getter="get_cell_size" default="Vector2(1, 1)"> The size of the point cell which will be applied to calculate the resulting point position returned by [method get_point_path]. If changed, [method update] needs to be called before finding the next path. </member> @@ -238,5 +241,17 @@ <constant name="DIAGONAL_MODE_MAX" value="4" enum="DiagonalMode"> Represents the size of the [enum DiagonalMode] enum. </constant> + <constant name="CELL_SHAPE_SQUARE" value="0" enum="CellShape"> + Rectangular cell shape. + </constant> + <constant name="CELL_SHAPE_ISOMETRIC_RIGHT" value="1" enum="CellShape"> + Diamond cell shape (for isometric look). Cell coordinates layout where the horizontal axis goes up-right, and the vertical one goes down-right. + </constant> + <constant name="CELL_SHAPE_ISOMETRIC_DOWN" value="2" enum="CellShape"> + Diamond cell shape (for isometric look). Cell coordinates layout where the horizontal axis goes down-right, and the vertical one goes down-left. + </constant> + <constant name="CELL_SHAPE_MAX" value="3" enum="CellShape"> + Represents the size of the [enum CellShape] enum. + </constant> </constants> </class> diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index 15f6b16439..2a88e70818 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -8,21 +8,23 @@ [codeblocks] [gdscript] # This creates an animation that makes the node "Enemy" move to the right by - # 100 pixels in 0.5 seconds. + # 100 pixels in 2.0 seconds. var animation = Animation.new() var track_index = animation.add_track(Animation.TYPE_VALUE) animation.track_set_path(track_index, "Enemy:position:x") animation.track_insert_key(track_index, 0.0, 0) - animation.track_insert_key(track_index, 0.5, 100) + animation.track_insert_key(track_index, 2.0, 100) + animation.length = 2.0 [/gdscript] [csharp] // This creates an animation that makes the node "Enemy" move to the right by - // 100 pixels in 0.5 seconds. + // 100 pixels in 2.0 seconds. var animation = new Animation(); int trackIndex = animation.AddTrack(Animation.TrackType.Value); animation.TrackSetPath(trackIndex, "Enemy:position:x"); animation.TrackInsertKey(trackIndex, 0.0f, 0); - animation.TrackInsertKey(trackIndex, 0.5f, 100); + animation.TrackInsertKey(trackIndex, 2.0f, 100); + animation.Length = 2.0f; [/csharp] [/codeblocks] Animations are just data containers, and must be added to nodes such as an [AnimationPlayer] to be played back. Animation tracks have different types, each with its own set of dedicated methods. Check [enum TrackType] to see available types. diff --git a/doc/classes/AnimationMixer.xml b/doc/classes/AnimationMixer.xml index 4a489a3ef2..31308c4e20 100644 --- a/doc/classes/AnimationMixer.xml +++ b/doc/classes/AnimationMixer.xml @@ -15,10 +15,10 @@ <param index="0" name="animation" type="Animation" /> <param index="1" name="track" type="int" /> <param index="2" name="value" type="Variant" /> - <param index="3" name="object" type="Object" /> - <param index="4" name="object_idx" type="int" /> + <param index="3" name="object_id" type="int" /> + <param index="4" name="object_sub_idx" type="int" /> <description> - A virtual function for processing after key getting during playback. + A virtual function for processing after getting a key during playback. </description> </method> <method name="add_animation_library"> diff --git a/doc/classes/AnimationNodeStateMachine.xml b/doc/classes/AnimationNodeStateMachine.xml index 1c96110540..86311542ad 100644 --- a/doc/classes/AnimationNodeStateMachine.xml +++ b/doc/classes/AnimationNodeStateMachine.xml @@ -182,7 +182,7 @@ Seeking to the beginning is treated as seeking to the beginning of the animation in the current state. Transition to the end state, or the absence of transitions in each state, is treated as exiting the state machine. </constant> <constant name="STATE_MACHINE_TYPE_GROUPED" value="2" enum="StateMachineType"> - This is a grouped state machine that can be controlled from a parent state machine. It does not work on standalone. There must be a state machine with [member state_machine_type] of [constant STATE_MACHINE_TYPE_ROOT] or [constant STATE_MACHINE_TYPE_NESTED] in the parent or ancestor. + This is a grouped state machine that can be controlled from a parent state machine. It does not work independently. There must be a state machine with [member state_machine_type] of [constant STATE_MACHINE_TYPE_ROOT] or [constant STATE_MACHINE_TYPE_NESTED] in the parent or ancestor. </constant> </constants> </class> diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index fccf16fcaa..39b9dde043 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -479,7 +479,7 @@ <return type="Variant" /> <param index="0" name="position" type="int" /> <description> - Removes and returns the element of the array at index [param position]. If negative, [param position] is considered relative to the end of the array. Leaves the array untouched and returns [code]null[/code] if the array is empty or if it's accessed out of bounds. An error message is printed when the array is accessed out of bounds, but not when the array is empty. + Removes and returns the element of the array at index [param position]. If negative, [param position] is considered relative to the end of the array. Leaves the array unchanged and returns [code]null[/code] if the array is empty or if it's accessed out of bounds. An error message is printed when the array is accessed out of bounds, but not when the array is empty. [b]Note:[/b] On large arrays, this method can be slower than [method pop_back] as it will reindex the array's elements that are located after the removed element. The larger the array and the lower the index of the removed element, the slower [method pop_at] will be. </description> </method> @@ -544,6 +544,7 @@ <param index="0" name="size" type="int" /> <description> Resizes the array to contain a different number of elements. If the array size is smaller, elements are cleared, if bigger, new elements are [code]null[/code]. Returns [constant OK] on success, or one of the other [enum Error] values if the operation failed. + Calling [method resize] once and assigning the new values is faster than adding new elements one by one. [b]Note:[/b] This method acts in-place and doesn't return a modified array. </description> </method> diff --git a/doc/classes/AudioEffectCapture.xml b/doc/classes/AudioEffectCapture.xml index 275e5ab0b6..e17c510907 100644 --- a/doc/classes/AudioEffectCapture.xml +++ b/doc/classes/AudioEffectCapture.xml @@ -6,11 +6,10 @@ <description> AudioEffectCapture is an AudioEffect which copies all audio frames from the attached audio effect bus into its internal ring buffer. Application code should consume these audio frames from this ring buffer using [method get_buffer] and process it as needed, for example to capture data from an [AudioStreamMicrophone], implement application-defined effects, or to transmit audio over the network. When capturing audio data from a microphone, the format of the samples will be stereo 32-bit floating point PCM. - [b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings. + Unlike [AudioEffectRecord], this effect only returns the raw audio samples instead of encoding them into an [AudioStream]. </description> <tutorials> <link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link> - <link title="Audio Mic Record Demo">https://github.com/godotengine/godot-demo-projects/tree/master/audio/mic_record</link> </tutorials> <methods> <method name="can_get_buffer" qualifiers="const"> diff --git a/doc/classes/AudioEffectPitchShift.xml b/doc/classes/AudioEffectPitchShift.xml index ec60e6a75a..4d4baa34ab 100644 --- a/doc/classes/AudioEffectPitchShift.xml +++ b/doc/classes/AudioEffectPitchShift.xml @@ -18,7 +18,7 @@ The oversampling factor to use. Higher values result in better quality, but are more demanding on the CPU and may cause audio cracking if the CPU can't keep up. </member> <member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale" default="1.0"> - The pitch scale to use. [code]1.0[/code] is the default pitch and plays sounds unaltered. [member pitch_scale] can range from [code]0.0[/code] (infinitely low pitch, inaudible) to [code]16[/code] (16 times higher than the initial pitch). + The pitch scale to use. [code]1.0[/code] is the default pitch and plays sounds unaffected. [member pitch_scale] can range from [code]0.0[/code] (infinitely low pitch, inaudible) to [code]16[/code] (16 times higher than the initial pitch). </member> </members> <constants> diff --git a/doc/classes/AudioEffectRecord.xml b/doc/classes/AudioEffectRecord.xml index e07d66fa7b..5b43c5ebaa 100644 --- a/doc/classes/AudioEffectRecord.xml +++ b/doc/classes/AudioEffectRecord.xml @@ -4,9 +4,10 @@ Audio effect used for recording the sound from an audio bus. </brief_description> <description> - Allows the user to record the sound from an audio bus. This can include all audio output by Godot when used on the "Master" audio bus. + Allows the user to record the sound from an audio bus into an [AudioStreamWAV]. When used on the "Master" audio bus, this includes all audio output by Godot. + Unlike [AudioEffectCapture], this effect encodes the recording with the given format (8-bit, 16-bit, or compressed) instead of giving access to the raw audio samples. Can be used (with an [AudioStreamMicrophone]) to record from a microphone. - It sets and gets the format in which the audio file will be recorded (8-bit, 16-bit, or compressed). It checks whether or not the recording is active, and if it is, records the sound. It then returns the recorded sample. + [b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings. </description> <tutorials> <link title="Recording with microphone">$DOCS_URL/tutorials/audio/recording_with_microphone.html</link> diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml index 12e09b235f..6e30775fee 100644 --- a/doc/classes/AudioStream.xml +++ b/doc/classes/AudioStream.xml @@ -28,6 +28,12 @@ <description> </description> </method> + <method name="_get_parameter_list" qualifiers="virtual const"> + <return type="Dictionary[]" /> + <description> + Return the controllable parameters of this stream. This array contains dictionaries with a property info description format (see [method Object.get_property_list]). Additionally, the default value for this parameter must be added tho each dictionary in "default_value" field. + </description> + </method> <method name="_get_stream_name" qualifiers="virtual const"> <return type="String" /> <description> @@ -62,4 +68,11 @@ </description> </method> </methods> + <signals> + <signal name="parameter_list_changed"> + <description> + Signal to be emitted to notify when the parameter list changed. + </description> + </signal> + </signals> </class> diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml index 7692690b5e..a090989194 100644 --- a/doc/classes/AudioStreamPlayback.xml +++ b/doc/classes/AudioStreamPlayback.xml @@ -15,6 +15,13 @@ <description> </description> </method> + <method name="_get_parameter" qualifiers="virtual const"> + <return type="Variant" /> + <param index="0" name="name" type="StringName" /> + <description> + Return the current value of a playback parameter by name (see [method AudioStream._get_parameter_list]). + </description> + </method> <method name="_get_playback_position" qualifiers="virtual const"> <return type="float" /> <description> @@ -39,6 +46,14 @@ <description> </description> </method> + <method name="_set_parameter" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="name" type="StringName" /> + <param index="1" name="value" type="Variant" /> + <description> + Set the current value of a playback parameter by name (see [method AudioStream._get_parameter_list]). + </description> + </method> <method name="_start" qualifiers="virtual"> <return type="void" /> <param index="0" name="from_pos" type="float" /> diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index 653397ebc3..e3a7eda563 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -383,7 +383,7 @@ If [code]true[/code], enables subsurface scattering transmittance. Only effective if [member subsurf_scatter_enabled] is [code]true[/code]. See also [member backlight_enabled]. </member> <member name="subsurf_scatter_transmittance_texture" type="Texture2D" setter="set_texture" getter="get_texture"> - The texture to use for multiplying the intensity of the subsurface scattering transmitteance intensity. See also [member subsurf_scatter_texture]. Ignored if [member subsurf_scatter_skin_mode] is [code]true[/code]. + The texture to use for multiplying the intensity of the subsurface scattering transmittance intensity. See also [member subsurf_scatter_texture]. Ignored if [member subsurf_scatter_skin_mode] is [code]true[/code]. </member> <member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="BaseMaterial3D.TextureFilter" default="3"> Filter flags for the texture. See [enum TextureFilter] for options. diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index f98c207a6e..c271e23f2e 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -7,7 +7,7 @@ A 3×3 matrix used for representing 3D rotation and scale. Usually used as an orthogonal basis for a [Transform3D]. Contains 3 vector fields X, Y and Z as its columns, which are typically interpreted as the local basis vectors of a transformation. For such use, it is composed of a scaling and a rotation matrix, in that order (M = R.S). Basis can also be accessed as an array of 3D vectors. These vectors are usually orthogonal to each other, but are not necessarily normalized (due to scaling). - For more information, read the "Matrices and transforms" documentation article. + For a general introduction, see the [url=$DOCS_URL/tutorials/math/matrices_and_transforms.html]Matrices and transforms[/url] tutorial. </description> <tutorials> <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> @@ -71,6 +71,20 @@ <param index="1" name="order" type="int" default="2" /> <description> Constructs a pure rotation Basis matrix from Euler angles in the specified Euler rotation order. By default, use YXZ order (most common). See the [enum EulerOrder] enum for possible values. + [codeblocks] + [gdscript] + # Creates a Basis whose z axis points down. + var my_basis = Basis.from_euler(Vector3(TAU / 4, 0, 0)) + + print(my_basis.z) # Prints (0, -1, 0). + [/gdscript] + [csharp] + // Creates a Basis whose z axis points down. + var myBasis = Basis.FromEuler(new Vector3(Mathf.Tau / 4.0f, 0.0f, 0.0f)); + + GD.Print(myBasis.Z); // Prints (0, -1, 0). + [/csharp] + [/codeblocks] </description> </method> <method name="from_scale" qualifiers="static"> @@ -78,6 +92,22 @@ <param index="0" name="scale" type="Vector3" /> <description> Constructs a pure scale basis matrix with no rotation or shearing. The scale values are set as the diagonal of the matrix, and the other parts of the matrix are zero. + [codeblocks] + [gdscript] + var my_basis = Basis.from_scale(Vector3(2, 4, 8)) + + print(my_basis.x) # Prints (2, 0, 0). + print(my_basis.y) # Prints (0, 4, 0). + print(my_basis.z) # Prints (0, 0, 8). + [/gdscript] + [csharp] + var myBasis = Basis.FromScale(new Vector3(2.0f, 4.0f, 8.0f)); + + GD.Print(myBasis.X); // Prints (2, 0, 0). + GD.Print(myBasis.Y); // Prints (0, 4, 0). + GD.Print(myBasis.Z); // Prints (0, 0, 8). + [/csharp] + [/codeblocks] </description> </method> <method name="get_euler" qualifiers="const"> @@ -98,6 +128,32 @@ <return type="Vector3" /> <description> Assuming that the matrix is the combination of a rotation and scaling, return the absolute value of scaling factors along each axis. + [codeblocks] + [gdscript] + var my_basis = Basis( + Vector3(2, 0, 0), + Vector3(0, 4, 0), + Vector3(0, 0, 8) + ) + # Rotating the Basis in any way preserves its scale. + my_basis = my_basis.rotated(Vector3.UP, TAU / 2) + my_basis = my_basis.rotated(Vector3.RIGHT, TAU / 4) + + print(my_basis.get_scale()) # Prints (2, 4, 8). + [/gdscript] + [csharp] + var myBasis = new Basis( + Vector3(2.0f, 0.0f, 0.0f), + Vector3(0.0f, 4.0f, 0.0f), + Vector3(0.0f, 0.0f, 8.0f) + ); + // Rotating the Basis in any way preserves its scale. + myBasis = myBasis.Rotated(Vector3.Up, Mathf.Tau / 2.0f); + myBasis = myBasis.Rotated(Vector3.Right, Mathf.Tau / 4.0f); + + GD.Print(myBasis.Scale); // Prints (2, 4, 8). + [/csharp] + [/codeblocks] </description> </method> <method name="inverse" qualifiers="const"> @@ -140,6 +196,25 @@ <return type="Basis" /> <description> Returns the orthonormalized version of the matrix (useful to call from time to time to avoid rounding error for orthogonal matrices). This performs a Gram-Schmidt orthonormalization on the basis of the matrix. + [codeblocks] + [gdscript] + # Rotate this Node3D every frame. + func _process(delta): + basis = basis.rotated(Vector3.UP, TAU * delta) + basis = basis.rotated(Vector3.RIGHT, TAU * delta) + + basis = basis.orthonormalized() + [/gdscript] + [csharp] + // Rotate this Node3D every frame. + public override void _Process(double delta) + { + Basis = Basis.Rotated(Vector3.Up, Mathf.Tau * (float)delta) + .Rotated(Vector3.Right, Mathf.Tau * (float)delta) + .Orthonormalized(); + } + [/csharp] + [/codeblocks] </description> </method> <method name="rotated" qualifiers="const"> @@ -148,6 +223,24 @@ <param index="1" name="angle" type="float" /> <description> Introduce an additional rotation around the given axis by [param angle] (in radians). The axis must be a normalized vector. + [codeblocks] + [gdscript] + var my_basis = Basis.IDENTITY + var angle = TAU / 2 + + my_basis = my_basis.rotated(Vector3.UP, angle) # Rotate around the up axis (yaw). + my_basis = my_basis.rotated(Vector3.RIGHT, angle) # Rotate around the right axis (pitch). + my_basis = my_basis.rotated(Vector3.BACK, angle) # Rotate around the back axis (roll). + [/gdscript] + [csharp] + var myBasis = Basis.Identity; + var angle = Mathf.Tau / 2.0f; + + myBasis = myBasis.Rotated(Vector3.Up, angle); // Rotate around the up axis (yaw). + myBasis = myBasis.Rotated(Vector3.Right, angle); // Rotate around the right axis (pitch). + myBasis = myBasis.Rotated(Vector3.Back, angle); // Rotate around the back axis (roll). + [/csharp] + [/codeblocks] </description> </method> <method name="scaled" qualifiers="const"> @@ -155,6 +248,32 @@ <param index="0" name="scale" type="Vector3" /> <description> Introduce an additional scaling specified by the given 3D scaling factor. + [codeblocks] + [gdscript] + var my_basis = Basis( + Vector3(1, 1, 1), + Vector3(2, 2, 2), + Vector3(3, 3, 3) + ) + my_basis = my_basis.scaled(Vector3(0, 2, -2)) + + print(my_basis.x) # Prints (0, 2, -2). + print(my_basis.y) # Prints (0, 4, -4). + print(my_basis.z) # Prints (0, 6, -6). + [/gdscript] + [csharp] + var myBasis = new Basis( + new Vector3(1.0f, 1.0f, 1.0f), + new Vector3(2.0f, 2.0f, 2.0f), + new Vector3(3.0f, 3.0f, 3.0f) + ); + myBasis = myBasis.Scaled(new Vector3(0.0f, 2.0f, -2.0f)); + + GD.Print(myBasis.X); // Prints (0, 2, -2). + GD.Print(myBasis.Y); // Prints (0, 4, -4). + GD.Print(myBasis.Z); // Prints (0, 6, -6). + [/csharp] + [/codeblocks] </description> </method> <method name="slerp" qualifiers="const"> @@ -190,6 +309,32 @@ <return type="Basis" /> <description> Returns the transposed version of the matrix. + [codeblocks] + [gdscript] + var my_basis = Basis( + Vector3(1, 2, 3), + Vector3(4, 5, 6), + Vector3(7, 8, 9) + ) + my_basis = my_basis.transposed() + + print(my_basis.x) # Prints (1, 4, 7). + print(my_basis.y) # Prints (2, 5, 8). + print(my_basis.z) # Prints (3, 6, 9). + [/gdscript] + [csharp] + var myBasis = new Basis( + new Vector3(1.0f, 2.0f, 3.0f), + new Vector3(4.0f, 5.0f, 6.0f), + new Vector3(7.0f, 8.0f, 9.0f) + ); + myBasis = myBasis.Transposed(); + + GD.Print(myBasis.X); // Prints (1, 4, 7). + GD.Print(myBasis.Y); // Prints (2, 5, 8). + GD.Print(myBasis.Z); // Prints (3, 6, 9). + [/csharp] + [/codeblocks] </description> </method> </methods> @@ -256,6 +401,20 @@ This operator multiplies all components of the [Basis], which scales it uniformly. </description> </operator> + <operator name="operator /"> + <return type="Basis" /> + <param index="0" name="right" type="float" /> + <description> + This operator divides all components of the [Basis], which inversely scales it uniformly. + </description> + </operator> + <operator name="operator /"> + <return type="Basis" /> + <param index="0" name="right" type="int" /> + <description> + This operator divides all components of the [Basis], which inversely scales it uniformly. + </description> + </operator> <operator name="operator =="> <return type="bool" /> <param index="0" name="right" type="Basis" /> diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml index b903e98319..3550a6b7bd 100644 --- a/doc/classes/Callable.xml +++ b/doc/classes/Callable.xml @@ -46,17 +46,6 @@ # Prints "Attack!", when the button_pressed signal is emitted. button_pressed.connect(func(): print("Attack!")) [/codeblock] - [b]Note:[/b] Methods of native types such as [Signal], [Array], or [Dictionary] are not of type [Callable] in order to avoid unnecessary overhead. If you need to pass those methods as [Callable], use a lambda function as a wrapper. - [codeblock] - func _init(): - var my_dictionary = { "hello": "world" } - - # This will not work, `clear` is not a callable. - create_tween().tween_callback(my_dictionary.clear) - - # This will work, as lambdas are custom callables. - create_tween().tween_callback(func(): my_dictionary.clear()) - [/codeblock] </description> <tutorials> </tutorials> diff --git a/doc/classes/CameraAttributesPractical.xml b/doc/classes/CameraAttributesPractical.xml index 8a5956cc87..893bc27f91 100644 --- a/doc/classes/CameraAttributesPractical.xml +++ b/doc/classes/CameraAttributesPractical.xml @@ -17,7 +17,7 @@ The minimum sensitivity (in ISO) used when calculating auto exposure. When calculating scene average luminance, color values will be clamped to at least this value. This limits the auto-exposure from exposing above a certain brightness, resulting in a cut off point where the scene will remain dark. </member> <member name="dof_blur_amount" type="float" setter="set_dof_blur_amount" getter="get_dof_blur_amount" default="0.1"> - Sets the maximum amount of blur. When using physically-based blur amounts, will instead act as a multiplier. High values lead to an increased amount of bluriness, but can be much more expensive to calculate. It is best to keep this as low as possible for a given art style. + Sets the maximum amount of blur. When using physically-based blur amounts, will instead act as a multiplier. High values lead to an increased amount of blurriness, but can be much more expensive to calculate. It is best to keep this as low as possible for a given art style. </member> <member name="dof_blur_far_distance" type="float" setter="set_dof_blur_far_distance" getter="get_dof_blur_far_distance" default="10.0"> Objects further from the [Camera3D] by this amount will be blurred by the depth of field effect. Measured in meters. diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index 2f76f64cff..6f4dc47fb9 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -501,7 +501,7 @@ <method name="is_visible_in_tree" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if the node is present in the [SceneTree], its [member visible] property is [code]true[/code] and all its ancestors are also visible. If any ancestor is hidden, this node will not be visible in the scene tree, and is consequently not drawn (see [method _draw]). + Returns [code]true[/code] if the node is present in the [SceneTree], its [member visible] property is [code]true[/code] and all its ancestors are also visible. If any ancestor is hidden, this node will not be visible in the scene tree, and is therefore not drawn (see [method _draw]). </description> </method> <method name="make_canvas_position_local" qualifiers="const"> diff --git a/doc/classes/CanvasTexture.xml b/doc/classes/CanvasTexture.xml index 1b22adb723..a14f71cc46 100644 --- a/doc/classes/CanvasTexture.xml +++ b/doc/classes/CanvasTexture.xml @@ -5,7 +5,7 @@ </brief_description> <description> [CanvasTexture] is an alternative to [ImageTexture] for 2D rendering. It allows using normal maps and specular maps in any node that inherits from [CanvasItem]. [CanvasTexture] also allows overriding the texture's filter and repeat mode independently of the node's properties (or the project settings). - [b]Note:[/b] [CanvasTexture] cannot be used in 3D rendering. For physically-based materials in 3D, use [BaseMaterial3D] instead. + [b]Note:[/b] [CanvasTexture] cannot be used in 3D. It will not display correctly when applied to any [VisualInstance3D], such as [Sprite3D] or [Decal]. For physically-based materials in 3D, use [BaseMaterial3D] instead. </description> <tutorials> <link title="2D Lights and Shadows">$DOCS_URL/tutorials/2d/2d_lights_and_shadows.html</link> diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml index d6f3b7cb5d..acb3f66c17 100644 --- a/doc/classes/CollisionPolygon2D.xml +++ b/doc/classes/CollisionPolygon2D.xml @@ -25,6 +25,7 @@ </member> <member name="polygon" type="PackedVector2Array" setter="set_polygon" getter="get_polygon" default="PackedVector2Array()"> The polygon's list of vertices. Each point will be connected to the next, and the final point will be connected to the first. + [b]Note:[/b] The returned vertices are in the local coordinate space of the given [CollisionPolygon2D]. [b]Warning:[/b] The returned value is a clone of the [PackedVector2Array], not a reference. </member> </members> diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml index dfa8d7d840..ce450f6786 100644 --- a/doc/classes/ColorPicker.xml +++ b/doc/classes/ColorPicker.xml @@ -186,6 +186,9 @@ <theme_item name="sample_bg" data_type="icon" type="Texture2D"> Background panel for the color preview box (visible when the color is translucent). </theme_item> + <theme_item name="sample_revert" data_type="icon" type="Texture2D"> + The icon for the revert button (visible on the middle of the "old" color when it differs from the currently selected color). This icon is modulated with a dark color if the "old" color is bright enough, so the icon should be bright to ensure visibility in both scenarios. + </theme_item> <theme_item name="screen_picker" data_type="icon" type="Texture2D"> The icon for the screen color picker button. </theme_item> diff --git a/doc/classes/CompressedCubemap.xml b/doc/classes/CompressedCubemap.xml index 6ab0cc5d88..406ab4909a 100644 --- a/doc/classes/CompressedCubemap.xml +++ b/doc/classes/CompressedCubemap.xml @@ -4,7 +4,7 @@ An optionally compressed [Cubemap]. </brief_description> <description> - A cubemap that is loaded from a [code].ccube[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemap] can use one of 4 compresson methods: + A cubemap that is loaded from a [code].ccube[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemap] can use one of 4 compression methods: - Lossless (WebP or PNG, uncompressed on the GPU) - Lossy (WebP, uncompressed on the GPU) - VRAM Compressed (compressed on the GPU) diff --git a/doc/classes/CompressedCubemapArray.xml b/doc/classes/CompressedCubemapArray.xml index 32687229ed..195449ee99 100644 --- a/doc/classes/CompressedCubemapArray.xml +++ b/doc/classes/CompressedCubemapArray.xml @@ -4,7 +4,7 @@ An optionally compressed [CubemapArray]. </brief_description> <description> - A cubemap array that is loaded from a [code].ccubearray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemapArray] can use one of 4 compresson methods: + A cubemap array that is loaded from a [code].ccubearray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemapArray] can use one of 4 compression methods: - Lossless (WebP or PNG, uncompressed on the GPU) - Lossy (WebP, uncompressed on the GPU) - VRAM Compressed (compressed on the GPU) diff --git a/doc/classes/CompressedTexture2DArray.xml b/doc/classes/CompressedTexture2DArray.xml index ab0684fa06..6570e8f931 100644 --- a/doc/classes/CompressedTexture2DArray.xml +++ b/doc/classes/CompressedTexture2DArray.xml @@ -4,7 +4,7 @@ Array of 2-dimensional textures, optionally compressed. </brief_description> <description> - A texture array that is loaded from a [code].ctexarray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedTexture2DArray] can use one of 4 compresson methods: + A texture array that is loaded from a [code].ctexarray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedTexture2DArray] can use one of 4 compression methods: - Lossless (WebP or PNG, uncompressed on the GPU) - Lossy (WebP, uncompressed on the GPU) - VRAM Compressed (compressed on the GPU) diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml index 197d03f0d8..0e75c65f50 100644 --- a/doc/classes/Curve2D.xml +++ b/doc/classes/Curve2D.xml @@ -107,16 +107,14 @@ <param index="0" name="offset" type="float" default="0.0" /> <param index="1" name="cubic" type="bool" default="false" /> <description> - Similar to [method sample_baked], but returns [Transform2D] that includes a rotation along the curve, with [member Transform2D.origin] as the point position, [member Transform2D.x] as the sideways vector, and [member Transform2D.y] as the forward vector. Returns an empty transform if the length of the curve is [code]0[/code]. + Similar to [method sample_baked], but returns [Transform2D] that includes a rotation along the curve, with [member Transform2D.origin] as the point position and the [member Transform2D.x] vector pointing in the direction of the path at that point. Returns an empty transform if the length of the curve is [code]0[/code]. [codeblock] var baked = curve.sample_baked_with_rotation(offset) - # This will rotate and position the node with the up direction pointing along the curve. + # The returned Transform2D can be set directly. + transform = baked + # You can also read the origin and rotation separately from the returned Transform2D. position = baked.get_origin() rotation = baked.get_rotation() - # Alternatively, not preserving scale. - transform = baked * Transform2D.FLIP_Y - # To match the rotation of PathFollow2D, not preserving scale. - transform = Transform2D(baked.y, baked.x, baked.origin) [/codeblock] </description> </method> diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 8436cbf6ee..2d4c2c9682 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1754,7 +1754,7 @@ The ID of the main window spawned by the engine, which can be passed to methods expecting a [code]window_id[/code]. </constant> <constant name="INVALID_WINDOW_ID" value="-1"> - The ID that refers to a nonexisting window. This is be returned by some [DisplayServer] methods if no window matches the requested result. + The ID that refers to a nonexistent window. This is returned by some [DisplayServer] methods if no window matches the requested result. </constant> <constant name="SCREEN_LANDSCAPE" value="0" enum="ScreenOrientation"> Default landscape orientation. @@ -1955,16 +1955,16 @@ [b]Note:[/b] This flag is implemented only on macOS. </constant> <constant name="VSYNC_DISABLED" value="0" enum="VSyncMode"> - No vertical synchronization, which means the engine will display frames as fast as possible (tearing may be visible). Framerate is unlimited (notwithstanding [member Engine.max_fps]). + No vertical synchronization, which means the engine will display frames as fast as possible (tearing may be visible). Framerate is unlimited (regardless of [member Engine.max_fps]). </constant> <constant name="VSYNC_ENABLED" value="1" enum="VSyncMode"> - Default vertical synchronization mode, the image is displayed only on vertical blanking intervals (no tearing is visible). Framerate is limited by the monitor refresh rate (notwithstanding [member Engine.max_fps]). + Default vertical synchronization mode, the image is displayed only on vertical blanking intervals (no tearing is visible). Framerate is limited by the monitor refresh rate (regardless of [member Engine.max_fps]). </constant> <constant name="VSYNC_ADAPTIVE" value="2" enum="VSyncMode"> - Behaves like [constant VSYNC_DISABLED] when the framerate drops below the screen's refresh rate to reduce stuttering (tearing may be visible). Otherwise, vertical synchronization is enabled to avoid tearing. Framerate is limited by the monitor refresh rate (notwithstanding [member Engine.max_fps]). Behaves like [constant VSYNC_ENABLED] when using the Compatibility rendering method. + Behaves like [constant VSYNC_DISABLED] when the framerate drops below the screen's refresh rate to reduce stuttering (tearing may be visible). Otherwise, vertical synchronization is enabled to avoid tearing. Framerate is limited by the monitor refresh rate (regardless of [member Engine.max_fps]). Behaves like [constant VSYNC_ENABLED] when using the Compatibility rendering method. </constant> <constant name="VSYNC_MAILBOX" value="3" enum="VSyncMode"> - Displays the most recent image in the queue on vertical blanking intervals, while rendering to the other images (no tearing is visible). Framerate is unlimited (notwithstanding [member Engine.max_fps]). + Displays the most recent image in the queue on vertical blanking intervals, while rendering to the other images (no tearing is visible). Framerate is unlimited (regardless of [member Engine.max_fps]). Although not guaranteed, the images can be rendered as fast as possible, which may reduce input lag (also called "Fast" V-Sync mode). [constant VSYNC_MAILBOX] works best when at least twice as many frames as the display refresh rate are rendered. Behaves like [constant VSYNC_ENABLED] when using the Compatibility rendering method. </constant> <constant name="DISPLAY_HANDLE" value="0" enum="HandleType"> diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml index 82ba956151..88a6eeec26 100644 --- a/doc/classes/EditorImportPlugin.xml +++ b/doc/classes/EditorImportPlugin.xml @@ -120,6 +120,13 @@ <link title="Import plugins">$DOCS_URL/tutorials/plugins/editor/import_plugins.html</link> </tutorials> <methods> + <method name="_can_import_threaded" qualifiers="virtual const"> + <return type="bool" /> + <description> + Tells whether this importer can be run in parallel on threads, or, on the contrary, it's only safe for the editor to call it from the main thread, for one file at a time. + If this method is not overridden, it will return [code]true[/code] by default (i.e., safe for parallel importing). + </description> + </method> <method name="_get_import_options" qualifiers="virtual const"> <return type="Dictionary[]" /> <param index="0" name="path" type="String" /> diff --git a/doc/classes/EditorInspector.xml b/doc/classes/EditorInspector.xml index cfdc172fd1..6b25be490e 100644 --- a/doc/classes/EditorInspector.xml +++ b/doc/classes/EditorInspector.xml @@ -28,6 +28,7 @@ </method> </methods> <members> + <member name="follow_focus" type="bool" setter="set_follow_focus" getter="is_following_focus" overrides="ScrollContainer" default="true" /> <member name="horizontal_scroll_mode" type="int" setter="set_horizontal_scroll_mode" getter="get_horizontal_scroll_mode" overrides="ScrollContainer" enum="ScrollContainer.ScrollMode" default="0" /> </members> <signals> diff --git a/doc/classes/EditorNode3DGizmo.xml b/doc/classes/EditorNode3DGizmo.xml index 1680400384..7597489601 100644 --- a/doc/classes/EditorNode3DGizmo.xml +++ b/doc/classes/EditorNode3DGizmo.xml @@ -9,6 +9,13 @@ <tutorials> </tutorials> <methods> + <method name="_begin_handle_action" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="id" type="int" /> + <param index="1" name="secondary" type="bool" /> + <description> + </description> + </method> <method name="_commit_handle" qualifiers="virtual"> <return type="void" /> <param index="0" name="id" type="int" /> diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml index da7ee17335..8fd7c167d9 100644 --- a/doc/classes/EditorNode3DGizmoPlugin.xml +++ b/doc/classes/EditorNode3DGizmoPlugin.xml @@ -11,6 +11,14 @@ <link title="Node3D gizmo plugins">$DOCS_URL/tutorials/plugins/editor/3d_gizmos.html</link> </tutorials> <methods> + <method name="_begin_handle_action" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="gizmo" type="EditorNode3DGizmo" /> + <param index="1" name="handle_id" type="int" /> + <param index="2" name="secondary" type="bool" /> + <description> + </description> + </method> <method name="_can_be_hidden" qualifiers="virtual const"> <return type="bool" /> <description> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 50709f9ef5..148a6541a2 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -327,7 +327,7 @@ <param index="0" name="object" type="Object" /> <description> Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method _edit] and [method _make_visible] called when the editor requests them. If you have declared the methods [method _forward_canvas_gui_input] and [method _forward_3d_gui_input] these will be called too. - [b]Note:[/b] Each plugin should handle only one type of objects at a time. If a plugin handes more types of objects and they are edited at the same time, it will result in errors. + [b]Note:[/b] Each plugin should handle only one type of objects at a time. If a plugin handles more types of objects and they are edited at the same time, it will result in errors. </description> </method> <method name="_has_main_screen" qualifiers="virtual const"> diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 93d2bb8548..b7f3ec9963 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -466,6 +466,21 @@ <member name="filesystem/external_programs/raster_image_editor" type="String" setter="" getter=""> The program that opens raster image files when clicking "Open in External Program" option in Filesystem Dock. If not specified, the file will be opened in the system's default program. </member> + <member name="filesystem/external_programs/terminal_emulator" type="String" setter="" getter=""> + The terminal emulator program to use when using [b]Open in Terminal[/b] context menu action in the FileSystem dock. You can enter an absolute path to a program binary, or a path to a program that is present in the [code]PATH[/code] environment variable. + If left empty, Godot will use the default terminal emulator for the system: + - [b]Windows:[/b] PowerShell + - [b]macOS:[/b] Terminal.app + - [b]Linux:[/b] The first terminal found on the system in this order: gnome-terminal, konsole, xfce4-terminal, lxterminal, kitty, alacritty, urxvt, xterm. + To use Command Prompt (cmd) instead of PowerShell on Windows, enter [code]cmd[/code] in this field and the correct flags will automatically be used. + On macOS, make sure to point to the actual program binary located within the [code]Programs/MacOS[/code] folder of the .app bundle, rather than the .app bundle directory. + If specifying a custom terminal emulator, you may need to override [member filesystem/external_programs/terminal_emulator_flags] so it opens in the correct folder. + </member> + <member name="filesystem/external_programs/terminal_emulator_flags" type="String" setter="" getter=""> + The command-line arguments to pass to the terminal emulator that is run when using [b]Open in Terminal[/b] context menu action in the FileSystem dock. See also [member filesystem/external_programs/terminal_emulator]. + If left empty, the default flags are [code]{directory}[/code], which is replaced by the absolute path to the directory that is being opened in the terminal. + [b]Note:[/b] If the terminal emulator is set to PowerShell, cmd, or Konsole, Godot will automatically prepend arguments to this list, as these terminals require nonstandard arguments to open in the correct folder. + </member> <member name="filesystem/external_programs/vector_image_editor" type="String" setter="" getter=""> The program that opens vector image files when clicking "Open in External Program" option in Filesystem Dock. If not specified, the file will be opened in the system's default program. </member> @@ -647,12 +662,16 @@ <member name="interface/theme/accent_color" type="Color" setter="" getter=""> The color to use for "highlighted" user interface elements in the editor (pressed and hovered items). </member> - <member name="interface/theme/additional_spacing" type="float" setter="" getter=""> - The spacing to add for buttons and list items in the editor (in pixels). Increasing this value is useful to improve usability on touch screens, at the cost of reducing the amount of usable screen real estate. + <member name="interface/theme/additional_spacing" type="int" setter="" getter=""> + The extra spacing to add to various GUI elements in the editor (in pixels). Increasing this value is useful to improve usability on touch screens, at the cost of reducing the amount of usable screen real estate. + See also [member interface/theme/spacing_preset]. </member> <member name="interface/theme/base_color" type="Color" setter="" getter=""> The base color to use for user interface elements in the editor. Secondary colors (such as darker/lighter variants) are derived from this color. </member> + <member name="interface/theme/base_spacing" type="int" setter="" getter=""> + The base spacing used by various GUI elements in the editor (in pixels). See also [member interface/theme/spacing_preset]. + </member> <member name="interface/theme/border_size" type="int" setter="" getter=""> The border size to use for interface elements (in pixels). </member> @@ -684,6 +703,9 @@ <member name="interface/theme/relationship_line_opacity" type="float" setter="" getter=""> The opacity to use when drawing relationship lines in the editor's [Tree]-based GUIs (such as the Scene tree dock). </member> + <member name="interface/theme/spacing_preset" type="String" setter="" getter=""> + The editor theme spacing preset to use. See also [member interface/theme/base_spacing] and [member interface/theme/additional_spacing]. + </member> <member name="interface/touchscreen/enable_long_press_as_right_click" type="bool" setter="" getter=""> If [code]true[/code], long press on touchscreen is treated as right click. [b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices. diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index 0a544077e4..653dc4fd88 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -293,7 +293,7 @@ Controls the maximum number of physics steps that can be simulated each rendered frame. The default value is tuned to avoid "spiral of death" situations where expensive physics simulations trigger more expensive simulations indefinitely. However, the game will appear to slow down if the rendering FPS is less than [code]1 / max_physics_steps_per_frame[/code] of [member physics_ticks_per_second]. This occurs even if [code]delta[/code] is consistently used in physics calculations. To avoid this, increase [member max_physics_steps_per_frame] if you have increased [member physics_ticks_per_second] significantly above its default value. </member> <member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5"> - Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of the in-game clock and real clock but smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended. + Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of the in-game clock and real clock but smooth out framerate jitters. The default value of 0.5 should be good enough for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended. [b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics_jitter_fix] to [code]0[/code]. </member> <member name="physics_ticks_per_second" type="int" setter="set_physics_ticks_per_second" getter="get_physics_ticks_per_second" default="60"> diff --git a/doc/classes/GDExtension.xml b/doc/classes/GDExtension.xml index ee55c89131..533b32218f 100644 --- a/doc/classes/GDExtension.xml +++ b/doc/classes/GDExtension.xml @@ -1,31 +1,42 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GDExtension" inherits="Resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + A native library for GDExtension. </brief_description> <description> + The [GDExtension] resource type represents a [url=https://en.wikipedia.org/wiki/Shared_library]shared library[/url] which can expand the functionality of the engine. The [GDExtensionManager] singleton is responsible for loading, reloading, and unloading [GDExtension] resources. + [b]Note:[/b] GDExtension itself is not a scripting language and has no relation to [GDScript] resources. </description> <tutorials> + <link title="GDExtension overview">$DOCS_URL/tutorials/scripting/gdextension/what_is_gdextension.html</link> + <link title="GDExtension example in C++">$DOCS_URL/tutorials/scripting/gdextension/gdextension_cpp_example.html</link> </tutorials> <methods> <method name="close_library"> <return type="void" /> <description> + Closes the current library. + [b]Note:[/b] You normally should not call this method directly. This is handled automatically by [method GDExtensionManager.unload_extension]. </description> </method> <method name="get_minimum_library_initialization_level" qualifiers="const"> <return type="int" enum="GDExtension.InitializationLevel" /> <description> + Returns the lowest level required for this extension to be properly initialized (see the [enum InitializationLevel] enum). </description> </method> <method name="initialize_library"> <return type="void" /> <param index="0" name="level" type="int" enum="GDExtension.InitializationLevel" /> <description> + Initializes the library bound to this GDextension at the given initialization [param level]. + [b]Note:[/b] You normally should not call this method directly. This is handled automatically by [method GDExtensionManager.load_extension]. </description> </method> <method name="is_library_open" qualifiers="const"> <return type="bool" /> <description> + Returns [code]true[/code] if this extension's library has been opened. </description> </method> <method name="open_library"> @@ -33,17 +44,23 @@ <param index="0" name="path" type="String" /> <param index="1" name="entry_symbol" type="String" /> <description> + Opens the library at the specified [param path]. + [b]Note:[/b] You normally should not call this method directly. This is handled automatically by [method GDExtensionManager.load_extension]. </description> </method> </methods> <constants> <constant name="INITIALIZATION_LEVEL_CORE" value="0" enum="InitializationLevel"> + The library is initialized at the same time as the core features of the engine. </constant> <constant name="INITIALIZATION_LEVEL_SERVERS" value="1" enum="InitializationLevel"> + The library is initialized at the same time as the engine's servers (such as [RenderingServer] or [PhysicsServer3D]). </constant> <constant name="INITIALIZATION_LEVEL_SCENE" value="2" enum="InitializationLevel"> + The library is initialized at the same time as the engine's scene-related classes. </constant> <constant name="INITIALIZATION_LEVEL_EDITOR" value="3" enum="InitializationLevel"> + The library is initialized at the same time as the engine's editor classes. Only happens when loading the GDExtension in the editor. </constant> </constants> </class> diff --git a/doc/classes/GDExtensionManager.xml b/doc/classes/GDExtensionManager.xml index 8d2515dc28..1ecb23a03b 100644 --- a/doc/classes/GDExtensionManager.xml +++ b/doc/classes/GDExtensionManager.xml @@ -1,65 +1,82 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GDExtensionManager" inherits="Object" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Provides access to GDExtension functionality. </brief_description> <description> + The GDExtensionManager loads, initializes, and keeps track of all available [GDExtension] libraries in the project. + [b]Note:[/b] Do not worry about GDExtension unless you know what you are doing. </description> <tutorials> + <link title="GDExtension overview">$DOCS_URL/tutorials/scripting/gdextension/what_is_gdextension.html</link> + <link title="GDExtension example in C++">$DOCS_URL/tutorials/scripting/gdextension/gdextension_cpp_example.html</link> </tutorials> <methods> <method name="get_extension"> <return type="GDExtension" /> <param index="0" name="path" type="String" /> <description> + Returns the [GDExtension] at the given file [param path], or [code]null[/code] if it has not been loaded or does not exist. </description> </method> <method name="get_loaded_extensions" qualifiers="const"> <return type="PackedStringArray" /> <description> + Returns the file paths of all currently loaded extensions. </description> </method> <method name="is_extension_loaded" qualifiers="const"> <return type="bool" /> <param index="0" name="path" type="String" /> <description> + Returns [code]true[/code] if the extension at the given file [param path] has already been loaded successfully. See also [method get_loaded_extensions]. </description> </method> <method name="load_extension"> <return type="int" enum="GDExtensionManager.LoadStatus" /> <param index="0" name="path" type="String" /> <description> + Loads an extension by absolute file path. The [param path] needs to point to a valid [GDExtension]. Returns [constant LOAD_STATUS_OK] if successful. </description> </method> <method name="reload_extension"> <return type="int" enum="GDExtensionManager.LoadStatus" /> <param index="0" name="path" type="String" /> <description> + Reloads the extension at the given file path. The [param path] needs to point to a valid [GDExtension], otherwise this method may return either [constant LOAD_STATUS_NOT_LOADED] or [constant LOAD_STATUS_FAILED]. + [b]Note:[/b] You can only reload extensions in the editor. In release builds, this method always fails and returns [constant LOAD_STATUS_FAILED]. </description> </method> <method name="unload_extension"> <return type="int" enum="GDExtensionManager.LoadStatus" /> <param index="0" name="path" type="String" /> <description> + Unloads an extension by file path. The [param path] needs to point to an already loaded [GDExtension], otherwise this method returns [constant LOAD_STATUS_NOT_LOADED]. </description> </method> </methods> <signals> <signal name="extensions_reloaded"> <description> - Emitted after the editor has automatically reloaded any extensions. + Emitted after the editor has finished reloading one or more extensions. </description> </signal> </signals> <constants> <constant name="LOAD_STATUS_OK" value="0" enum="LoadStatus"> + The extension has loaded successfully. </constant> <constant name="LOAD_STATUS_FAILED" value="1" enum="LoadStatus"> + The extension has failed to load, possibly because it does not exist or has missing dependencies. </constant> <constant name="LOAD_STATUS_ALREADY_LOADED" value="2" enum="LoadStatus"> + The extension has already been loaded. </constant> <constant name="LOAD_STATUS_NOT_LOADED" value="3" enum="LoadStatus"> + The extension has not been loaded. </constant> <constant name="LOAD_STATUS_NEEDS_RESTART" value="4" enum="LoadStatus"> + The extension requires the application to restart to fully load. </constant> </constants> </class> diff --git a/doc/classes/Geometry3D.xml b/doc/classes/Geometry3D.xml index a85d17d925..9f87682983 100644 --- a/doc/classes/Geometry3D.xml +++ b/doc/classes/Geometry3D.xml @@ -142,5 +142,12 @@ Tests if the segment ([param from], [param to]) intersects the triangle [param a], [param b], [param c]. If yes, returns the point of intersection as [Vector3]. If no intersection takes place, returns [code]null[/code]. </description> </method> + <method name="tetrahedralize_delaunay"> + <return type="PackedInt32Array" /> + <param index="0" name="points" type="PackedVector3Array" /> + <description> + Tetrahedralizes the volume specified by a discrete set of [param points] in 3D space, ensuring that no point lies within the circumsphere of any resulting tetrahedron. The method returns a [PackedInt32Array] where each tetrahedron consists of four consecutive point indices into the [param points] array (resulting in an array with [code]n * 4[/code] elements, where [code]n[/code] is the number of tetrahedra found). If the tetrahedralization is unsuccessful, an empty [PackedInt32Array] is returned. + </description> + </method> </methods> </class> diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index 990efbb3a4..6b0d2e4a62 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -34,7 +34,7 @@ The selected shadow casting flag. See [enum ShadowCastingSetting] for possible values. </member> <member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB(0, 0, 0, 0, 0, 0)"> - Overrides the bounding box of this node with a custom one. This can be used to avoid the expensive [AABB] recalculation that happens when a skeleton is used with a [MeshInstance3D] or to have fine control over the [MeshInstance3D]'s bounding box. To use the default AABB, set value to an [AABB] with all fields set to [code]0.0[/code]. To avoid frustum culling, set [member custom_aabb] to a very large AABB that covers your entire game world such as [code]AABB(-10000, -10000, -10000, 20000, 20000, 20000)[/code]. To disable all forms of culling (including occlusion culling), call [method RenderingServer.instance_set_ignore_culling] on the [GeometryInstance3D]'s [RID]. + Overrides the bounding box of this node with a custom one. This can be used to avoid the expensive [AABB] recalculation that happens when a skeleton is used with a [MeshInstance3D] or to have precise control over the [MeshInstance3D]'s bounding box. To use the default AABB, set value to an [AABB] with all fields set to [code]0.0[/code]. To avoid frustum culling, set [member custom_aabb] to a very large AABB that covers your entire game world such as [code]AABB(-10000, -10000, -10000, 20000, 20000, 20000)[/code]. To disable all forms of culling (including occlusion culling), call [method RenderingServer.instance_set_ignore_culling] on the [GeometryInstance3D]'s [RID]. </member> <member name="extra_cull_margin" type="float" setter="set_extra_cull_margin" getter="get_extra_cull_margin" default="0.0"> The extra distance added to the GeometryInstance3D's bounding box ([AABB]) to increase its cull box. diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index 9e1392567a..5bb3a25158 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -116,6 +116,20 @@ Returns the right (output) [Color] of the slot with the given [param slot_index]. </description> </method> + <method name="get_slot_custom_icon_left" qualifiers="const"> + <return type="Texture2D" /> + <param index="0" name="slot_index" type="int" /> + <description> + Returns the left (input) custom [Texture2D] of the slot with the given [param slot_index]. + </description> + </method> + <method name="get_slot_custom_icon_right" qualifiers="const"> + <return type="Texture2D" /> + <param index="0" name="slot_index" type="int" /> + <description> + Returns the right (output) custom [Texture2D] of the slot with the given [param slot_index]. + </description> + </method> <method name="get_slot_type_left" qualifiers="const"> <return type="int" /> <param index="0" name="slot_index" type="int" /> @@ -195,6 +209,22 @@ Sets the [Color] of the right (output) side of the slot with the given [param slot_index] to [param color]. </description> </method> + <method name="set_slot_custom_icon_left"> + <return type="void" /> + <param index="0" name="slot_index" type="int" /> + <param index="1" name="custom_icon" type="Texture2D" /> + <description> + Sets the custom [Texture2D] of the left (input) side of the slot with the given [param slot_index] to [param custom_icon]. + </description> + </method> + <method name="set_slot_custom_icon_right"> + <return type="void" /> + <param index="0" name="slot_index" type="int" /> + <param index="1" name="custom_icon" type="Texture2D" /> + <description> + Sets the custom [Texture2D] of the right (output) side of the slot with the given [param slot_index] to [param custom_icon]. + </description> + </method> <method name="set_slot_draw_stylebox"> <return type="void" /> <param index="0" name="slot_index" type="int" /> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 5677999d5d..6c1ecb3aea 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -19,6 +19,7 @@ <param index="1" name="contrast" type="float" /> <param index="2" name="saturation" type="float" /> <description> + Adjusts this image's [param brightness], [param contrast], and [param saturation] by the given values. Does not work if the image is compressed (see [method is_compressed]). </description> </method> <method name="blend_rect"> @@ -163,6 +164,7 @@ <return type="int" enum="Image.UsedChannels" /> <param index="0" name="source" type="int" enum="Image.CompressSource" default="0" /> <description> + Returns the color channels used by this image, as one of the [enum UsedChannels] constants. If the image is compressed, the original [param source] must be specified. </description> </method> <method name="fill"> @@ -612,6 +614,7 @@ OpenGL texture format [code]RGBA[/code] with four components, each with a bitdepth of 4. </constant> <constant name="FORMAT_RGB565" value="7" enum="Format"> + OpenGL texture format [code]RGB[/code] with three components. Red and blue have a bitdepth of 5, and green has a bitdepth of 6. </constant> <constant name="FORMAT_RF" value="8" enum="Format"> OpenGL texture format [code]GL_R32F[/code] where there's one component, a 32-bit floating-point value. @@ -696,8 +699,10 @@ [b]Note:[/b] When creating an [ImageTexture], an sRGB to linear color space conversion is performed. </constant> <constant name="FORMAT_ETC2_RA_AS_RG" value="33" enum="Format"> + [url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]RGBA8[/code] variant), which compresses RA data and interprets it as two channels (red and green). See also [constant FORMAT_ETC2_RGBA8]. </constant> <constant name="FORMAT_DXT5_RA_AS_RG" value="34" enum="Format"> + The [url=https://en.wikipedia.org/wiki/S3_Texture_Compression]S3TC[/url] texture format also known as Block Compression 3 or BC3, which compresses RA data and interprets it as two channels (red and green). See also [constant FORMAT_DXT5]. </constant> <constant name="FORMAT_ASTC_4x4" value="35" enum="Format"> [url=https://en.wikipedia.org/wiki/Adaptive_scalable_texture_compression]Adaptive Scalable Texture Compression[/url]. This implements the 4x4 (high quality) mode. @@ -731,7 +736,7 @@ On the other hand, if the image already has mipmaps, they will be used, and a new set will be generated for the resulting image. </constant> <constant name="INTERPOLATE_LANCZOS" value="4" enum="Interpolation"> - Performs Lanczos interpolation. This is the slowest image resizing mode, but it typically gives the best results, especially when downscalng images. + Performs Lanczos interpolation. This is the slowest image resizing mode, but it typically gives the best results, especially when downscaling images. </constant> <constant name="ALPHA_NONE" value="0" enum="AlphaMode"> Image does not have alpha. @@ -761,16 +766,22 @@ Represents the size of the [enum CompressMode] enum. </constant> <constant name="USED_CHANNELS_L" value="0" enum="UsedChannels"> + The image only uses one channel for luminance (grayscale). </constant> <constant name="USED_CHANNELS_LA" value="1" enum="UsedChannels"> + The image uses two channels for luminance and alpha, respectively. </constant> <constant name="USED_CHANNELS_R" value="2" enum="UsedChannels"> + The image only uses the red channel. </constant> <constant name="USED_CHANNELS_RG" value="3" enum="UsedChannels"> + The image uses two channels for red and green. </constant> <constant name="USED_CHANNELS_RGB" value="4" enum="UsedChannels"> + The image uses three channels for red, green, and blue. </constant> <constant name="USED_CHANNELS_RGBA" value="5" enum="UsedChannels"> + The image uses four channels for red, green, blue, and alpha. </constant> <constant name="COMPRESS_SOURCE_GENERIC" value="0" enum="CompressSource"> Source texture (before compression) is a regular texture. Default for all textures. diff --git a/doc/classes/InputEventMIDI.xml b/doc/classes/InputEventMIDI.xml index d685fdfa41..8e2ad52801 100644 --- a/doc/classes/InputEventMIDI.xml +++ b/doc/classes/InputEventMIDI.xml @@ -75,7 +75,7 @@ If the message is [constant MIDI_MESSAGE_CONTROL_CHANGE], this indicates the controller value, otherwise this is zero. Controllers include devices such as pedals and levers. </member> <member name="instrument" type="int" setter="set_instrument" getter="get_instrument" default="0"> - The instrument of this input event. This value ranges from 0 to 127. Refer to the instrument list on the General MIDI wikipedia article to see a list of instruments, except that this value is 0-index, so subtract one from every number on that chart. A standard piano will have an instrument number of 0. + The instrument of this input event. This value ranges from 0 to 127. Refer to the instrument list for [url=https://en.wikipedia.org/wiki/General_MIDI#Program_change_events]General MIDI[/url] to see a list of instruments, except that this value is 0-index, so subtract one from every number on that chart. A standard piano will have an instrument number of 0. </member> <member name="message" type="int" setter="set_message" getter="get_message" enum="MIDIMessage" default="0"> Returns a value indicating the type of message for this MIDI signal. This is a member of the [enum MIDIMessage] enum. diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 94b1815dce..77ead8fca0 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -127,6 +127,7 @@ <theme_item name="outline_size" data_type="constant" type="int" default="0"> Text outline size. [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended. + [b]Note:[/b] Using a value that is larger than half the font size is not recommended, as the font outline may fail to be fully closed in this case. </theme_item> <theme_item name="shadow_offset_x" data_type="constant" type="int" default="1"> The horizontal offset of the text's shadow. diff --git a/doc/classes/LightmapGI.xml b/doc/classes/LightmapGI.xml index ec75d85898..fa3bfe513f 100644 --- a/doc/classes/LightmapGI.xml +++ b/doc/classes/LightmapGI.xml @@ -65,6 +65,9 @@ The quality preset to use when baking lightmaps. This affects bake times, but output file sizes remain mostly identical across quality levels. To further speed up bake times, decrease [member bounces], disable [member use_denoiser] and increase the lightmap texel size on 3D scenes in the Import doc. </member> + <member name="texel_scale" type="float" setter="set_texel_scale" getter="get_texel_scale" default="1.0"> + Scales the lightmap texel density of all meshes for the current bake. This is a multiplier that builds upon the existing lightmap texel size defined in each imported 3D scene, along with the per-mesh density multiplier (which is designed to be used when the same mesh is used at different scales). Lower values will result in faster bake times. + </member> <member name="use_denoiser" type="bool" setter="set_use_denoiser" getter="is_using_denoiser" default="true"> If [code]true[/code], uses a GPU-based denoising algorithm on the generated lightmap. This eliminates most noise within the generated lightmap at the cost of longer bake times. File sizes are generally not impacted significantly by the use of a denoiser, although lossless compression may do a better job at compressing a denoised image. </member> diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml index 4c6c9d3524..b01a3f7a0e 100644 --- a/doc/classes/MainLoop.xml +++ b/doc/classes/MainLoop.xml @@ -5,7 +5,7 @@ </brief_description> <description> [MainLoop] is the abstract base class for a Godot project's game loop. It is inherited by [SceneTree], which is the default game loop implementation used in Godot projects, though it is also possible to write and use one's own [MainLoop] subclass instead of the scene tree. - Upon the application start, a [MainLoop] implementation must be provided to the OS; otherwise, the application will exit. This happens automatically (and a [SceneTree] is created) unless a [MainLoop] [Script] is provided from the command line (with e.g. [code]godot -s my_loop.gd[/code] or the "Main Loop Type" project setting is overwritten. + Upon the application start, a [MainLoop] implementation must be provided to the OS; otherwise, the application will exit. This happens automatically (and a [SceneTree] is created) unless a [MainLoop] [Script] is provided from the command line (with e.g. [code]godot -s my_loop.gd[/code]) or the "Main Loop Type" project setting is overwritten. Here is an example script implementing a simple [MainLoop]: [codeblocks] [gdscript] diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index 02631841bf..2bb0090282 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -456,7 +456,7 @@ <description> This function immediately forces synchronization of the specified navigation [param map] [RID]. By default navigation maps are only synchronized at the end of each physics frame. This function can be used to immediately (re)calculate all the navigation meshes and region connections of the navigation map. This makes it possible to query a navigation path for a changed map immediately and in the same frame (multiple times if needed). Due to technical restrictions the current NavigationServer command queue will be flushed. This means all already queued update commands for this physics frame will be executed, even those intended for other maps, regions and agents not part of the specified map. The expensive computation of the navigation meshes and region connections of a map will only be done for the specified map. Other maps will receive the normal synchronization at the end of the physics frame. Should the specified map receive changes after the forced update it will update again as well when the other maps receive their update. - Avoidance processing and dispatch of the [code]safe_velocity[/code] signals is untouched by this function and continues to happen for all maps and agents at the end of the physics frame. + Avoidance processing and dispatch of the [code]safe_velocity[/code] signals is unaffected by this function and continues to happen for all maps and agents at the end of the physics frame. [b]Note:[/b] With great power comes great responsibility. This function should only be used by users that really know what they are doing and have a good reason for it. Forcing an immediate update of a navigation map requires locking the NavigationServer and flushing the entire NavigationServer command queue. Not only can this severely impact the performance of a game but it can also introduce bugs if used inappropriately without much foresight. </description> </method> diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 20af517397..bff5d63a17 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -278,7 +278,7 @@ <param index="1" name="enabled" type="bool" /> <description> Sets if the agent uses the 2D avoidance or the 3D avoidance while avoidance is enabled. - If [code]true[/code] the agent calculates avoidance velocities in 3D for the xyz-axis, e.g. for games that take place in air, unterwater or space. The 3D using agent only avoids other 3D avoidance using agent's. The 3D using agent only reacts to radius based avoidance obstacles. The 3D using agent ignores any vertices based obstacles. The 3D using agent only avoids other 3D using agent's. + If [code]true[/code] the agent calculates avoidance velocities in 3D for the xyz-axis, e.g. for games that take place in air, underwater or space. The 3D using agent only avoids other 3D avoidance using agent's. The 3D using agent only reacts to radius based avoidance obstacles. The 3D using agent ignores any vertices based obstacles. The 3D using agent only avoids other 3D using agent's. If [code]false[/code] the agent calculates avoidance velocities in 2D along the xz-axis ignoring the y-axis. The 2D using agent only avoids other 2D avoidance using agent's. The 2D using agent reacts to radius avoidance obstacles. The 2D using agent reacts to vertices based avoidance obstacles. The 2D using agent only avoids other 2D using agent's. 2D using agents will ignore other 2D using agents or obstacles that are below their current position or above their current position including the agents height in 2D avoidance. </description> </method> @@ -495,7 +495,7 @@ <description> This function immediately forces synchronization of the specified navigation [param map] [RID]. By default navigation maps are only synchronized at the end of each physics frame. This function can be used to immediately (re)calculate all the navigation meshes and region connections of the navigation map. This makes it possible to query a navigation path for a changed map immediately and in the same frame (multiple times if needed). Due to technical restrictions the current NavigationServer command queue will be flushed. This means all already queued update commands for this physics frame will be executed, even those intended for other maps, regions and agents not part of the specified map. The expensive computation of the navigation meshes and region connections of a map will only be done for the specified map. Other maps will receive the normal synchronization at the end of the physics frame. Should the specified map receive changes after the forced update it will update again as well when the other maps receive their update. - Avoidance processing and dispatch of the [code]safe_velocity[/code] signals is untouched by this function and continues to happen for all maps and agents at the end of the physics frame. + Avoidance processing and dispatch of the [code]safe_velocity[/code] signals is unaffected by this function and continues to happen for all maps and agents at the end of the physics frame. [b]Note:[/b] With great power comes great responsibility. This function should only be used by users that really know what they are doing and have a good reason for it. Forcing an immediate update of a navigation map requires locking the NavigationServer and flushing the entire NavigationServer command queue. Not only can this severely impact the performance of a game but it can also introduce bugs if used inappropriately without much foresight. </description> </method> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 0ace4357fa..5dd3d22062 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -11,11 +11,11 @@ This means that when adding a node to the scene tree, the following order will be used for the callbacks: [method _enter_tree] of the parent, [method _enter_tree] of the children, [method _ready] of the children and finally [method _ready] of the parent (recursively for the entire scene tree). [b]Processing:[/b] Nodes can override the "process" state, so that they receive a callback on each frame requesting them to process (do something). Normal processing (callback [method _process], toggled with [method set_process]) happens as fast as possible and is dependent on the frame rate, so the processing time [i]delta[/i] (in seconds) is passed as an argument. Physics processing (callback [method _physics_process], toggled with [method set_physics_process]) happens a fixed number of times per second (60 by default) and is useful for code related to the physics engine. Nodes can also process input events. When present, the [method _input] function will be called for each input that the program receives. In many cases, this can be overkill (unless used for simple projects), and the [method _unhandled_input] function might be preferred; it is called when the input event was not handled by anyone else (typically, GUI [Control] nodes), ensuring that the node only receives the events that were meant for it. - To keep track of the scene hierarchy (especially when instancing scenes into other scenes), an "owner" can be set for the node with the [member owner] property. This keeps track of who instantiated what. This is mostly useful when writing editors and tools, though. + To keep track of the scene hierarchy (especially when instantiating scenes into other scenes), an "owner" can be set for the node with the [member owner] property. This keeps track of who instantiated what. This is mostly useful when writing editors and tools, though. Finally, when a node is freed with [method Object.free] or [method queue_free], it will also free all its children. [b]Groups:[/b] Nodes can be added to as many groups as you want to be easy to manage, you could create groups like "enemies" or "collectables" for example, depending on your game. See [method add_to_group], [method is_in_group] and [method remove_from_group]. You can then retrieve all nodes in these groups, iterate them and even call methods on groups via the methods on [SceneTree]. [b]Networking with nodes:[/b] After connecting to a server (or making one, see [ENetMultiplayerPeer]), it is possible to use the built-in RPC (remote procedure call) system to communicate over the network. By calling [method rpc] with a method name, it will be called locally and in all connected peers (peers = clients and the server that accepts connections). To identify which node receives the RPC call, Godot will use its [NodePath] (make sure node names are the same on all peers). Also, take a look at the high-level networking tutorial and corresponding demos. - [b]Note:[/b] The [code]script[/code] property is part of the [Object] class, not [Node]. It isn't exposed like most properties but does have a setter and getter ([code]set_script()[/code] and [code]get_script()[/code]). + [b]Note:[/b] The [code]script[/code] property is part of the [Object] class, not [Node]. It isn't exposed like most properties but does have a setter and getter (see [method Object.set_script] and [method Object.get_script]). </description> <tutorials> <link title="Nodes and scenes">$DOCS_URL/getting_started/step_by_step/nodes_and_scenes.html</link> @@ -25,7 +25,7 @@ <method name="_enter_tree" qualifiers="virtual"> <return type="void" /> <description> - Called when the node enters the [SceneTree] (e.g. upon instancing, scene changing, or after calling [method add_child] in a script). If the node has children, its [method _enter_tree] callback will be called first, and then that of the children. + Called when the node enters the [SceneTree] (e.g. upon instantiating, scene changing, or after calling [method add_child] in a script). If the node has children, its [method _enter_tree] callback will be called first, and then that of the children. Corresponds to the [constant NOTIFICATION_ENTER_TREE] notification in [method Object._notification]. </description> </method> @@ -93,7 +93,7 @@ Called when the node is "ready", i.e. when both the node and its children have entered the scene tree. If the node has children, their [method _ready] callbacks get triggered first, and the parent node will receive the ready notification afterwards. Corresponds to the [constant NOTIFICATION_READY] notification in [method Object._notification]. See also the [code]@onready[/code] annotation for variables. Usually used for initialization. For even earlier initialization, [method Object._init] may be used. See also [method _enter_tree]. - [b]Note:[/b] [method _ready] may be called only once for each node. After removing a node from the scene tree and adding it again, [method _ready] will not be called a second time. This can be bypassed by requesting another call with [method request_ready], which may be called anywhere before adding the node again. + [b]Note:[/b] This method may be called only once for each node. After removing a node from the scene tree and adding it again, [method _ready] will [b]not[/b] be called a second time. This can be bypassed by requesting another call with [method request_ready], which may be called anywhere before adding the node again. </description> </method> <method name="_shortcut_input" qualifiers="virtual"> @@ -138,8 +138,8 @@ <description> Adds a child [param node]. Nodes can have any number of children, but every child must have a unique name. Child nodes are automatically deleted when the parent node is deleted, so an entire scene can be removed by deleting its topmost node. If [param force_readable_name] is [code]true[/code], improves the readability of the added [param node]. If not named, the [param node] is renamed to its type, and if it shares [member name] with a sibling, a number is suffixed more appropriately. This operation is very slow. As such, it is recommended leaving this to [code]false[/code], which assigns a dummy name featuring [code]@[/code] in both situations. - If [param internal] is different than [constant INTERNAL_MODE_DISABLED], the child will be added as internal node. Such nodes are ignored by methods like [method get_children], unless their parameter [code]include_internal[/code] is [code]true[/code]. The intended usage is to hide the internal nodes from the user, so the user won't accidentally delete or modify them. Used by some GUI nodes, e.g. [ColorPicker]. See [enum InternalMode] for available modes. - [b]Note:[/b] If the child node already has a parent, the function will fail. Use [method remove_child] first to remove the node from its current parent. For example: + If [param internal] is different than [constant INTERNAL_MODE_DISABLED], the child will be added as internal node. These nodes are ignored by methods like [method get_children], unless their parameter [code]include_internal[/code] is [code]true[/code]. The intended usage is to hide the internal nodes from the user, so the user won't accidentally delete or modify them. Used by some GUI nodes, e.g. [ColorPicker]. See [enum InternalMode] for available modes. + [b]Note:[/b] If [param node] already has a parent, this method will fail. Use [method remove_child] first to remove [param node] from its current parent. For example: [codeblocks] [gdscript] var child_node = get_child(0) @@ -165,10 +165,10 @@ <param index="0" name="sibling" type="Node" /> <param index="1" name="force_readable_name" type="bool" default="false" /> <description> - Adds a [param sibling] node to current's node parent, at the same level as that node, right below it. + Adds a [param sibling] node to this node's parent, and moves the added sibling right below this node. If [param force_readable_name] is [code]true[/code], improves the readability of the added [param sibling]. If not named, the [param sibling] is renamed to its type, and if it shares [member name] with a sibling, a number is suffixed more appropriately. This operation is very slow. As such, it is recommended leaving this to [code]false[/code], which assigns a dummy name featuring [code]@[/code] in both situations. Use [method add_child] instead of this method if you don't need the child node to be added below a specific node in the list of children. - [b]Note:[/b] If this node is internal, the new sibling will be internal too (see [code]internal[/code] parameter in [method add_child]). + [b]Note:[/b] If this node is internal, the added sibling will be internal too (see [method add_child]'s [code]internal[/code] parameter). </description> </method> <method name="add_to_group"> @@ -176,9 +176,10 @@ <param index="0" name="group" type="StringName" /> <param index="1" name="persistent" type="bool" default="false" /> <description> - Adds the node to a group. Groups are helpers to name and organize a subset of nodes, for example "enemies" or "collectables". A node can be in any number of groups. Nodes can be assigned a group at any time, but will not be added until they are inside the scene tree (see [method is_inside_tree]). See notes in the description, and the group methods in [SceneTree]. - The [param persistent] option is used when packing node to [PackedScene] and saving to file. Non-persistent groups aren't stored. - [b]Note:[/b] For performance reasons, the order of node groups is [i]not[/i] guaranteed. The order of node groups should not be relied upon as it can vary across project runs. + Adds the node to the [param group]. Groups can be helpful to organize a subset of nodes, for example [code]"enemies"[/code] or [code]"collectables"[/code]. See notes in the description, and the group methods in [SceneTree]. + If [param persistent] is [code]true[/code], the group will be stored when saved inside a [PackedScene]. All groups created and displayed in the Node dock are persistent. + [b]Note:[/b] To improve performance, the order of group names is [i]not[/i] guaranteed and may vary between project runs. Therefore, do not rely on the group order. + [b]Note:[/b] [SceneTree]'s group methods will [i]not[/i] work on this node if not inside the tree (see [method is_inside_tree]). </description> </method> <method name="call_deferred_thread_group" qualifiers="vararg"> @@ -198,13 +199,14 @@ <method name="can_process" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if the node can process while the scene tree is paused (see [member process_mode]). Always returns [code]true[/code] if the scene tree is not paused, and [code]false[/code] if the node is not in the tree. + Returns [code]true[/code] if the node can receive processing notifications and input callbacks ([constant NOTIFICATION_PROCESS], [method _input], etc) from the [SceneTree] and [Viewport]. The value depends on both the current [member process_mode] and [member SceneTree.paused]. Returns [code]false[/code] if the node is not inside the tree. </description> </method> <method name="create_tween"> <return type="Tween" /> <description> - Creates a new [Tween] and binds it to this node. This is equivalent of doing: + Creates a new [Tween] and binds it to this node. Fails if the node is not inside the tree. + This is the equivalent of doing: [codeblocks] [gdscript] get_tree().create_tween().bind_node(self) @@ -220,9 +222,8 @@ <return type="Node" /> <param index="0" name="flags" type="int" default="15" /> <description> - Duplicates the node, returning a new node. - You can fine-tune the behavior using the [param flags] (see [enum DuplicateFlags]). - [b]Note:[/b] It will not work properly if the node contains a script with constructor arguments (i.e. needs to supply arguments to [method Object._init] method). In that case, the node will be duplicated without a script. + Duplicates the node, returning a new node with all of its properties, signals and groups copied from the original. The behavior can be tweaked through the [param flags] (see [enum DuplicateFlags]). + [b]Note:[/b] For nodes with a [Script] attached, if [method Object._init] has been defined with required parameters, the duplicated node will not have a [Script]. </description> </method> <method name="find_child" qualifiers="const"> @@ -231,12 +232,10 @@ <param index="1" name="recursive" type="bool" default="true" /> <param index="2" name="owned" type="bool" default="true" /> <description> - Finds the first descendant of this node whose name matches [param pattern] as in [method String.match]. Internal children are also searched over (see [code]internal[/code] parameter in [method add_child]). - [param pattern] does not match against the full path, just against individual node names. It is case-sensitive, with [code]"*"[/code] matching zero or more characters and [code]"?"[/code] matching any single character except [code]"."[/code]). - If [param recursive] is [code]true[/code], all child nodes are included, even if deeply nested. Nodes are checked in tree order, so this node's first direct child is checked first, then its own direct children, etc., before moving to the second direct child, and so on. If [param recursive] is [code]false[/code], only this node's direct children are matched. - If [param owned] is [code]true[/code], this method only finds nodes who have an assigned [member Node.owner]. This is especially important for scenes instantiated through a script, because those scenes don't have an owner. - Returns [code]null[/code] if no matching [Node] is found. - [b]Note:[/b] As this method walks through all the descendants of the node, it is the slowest way to get a reference to another node. Whenever possible, consider using [method get_node] with unique names instead (see [member unique_name_in_owner]), or caching the node references into variable. + Finds the first descendant of this node whose [member name] matches [param pattern], returning [code]null[/code] if no match is found. The matching is done against node names, [i]not[/i] their paths, through [method String.match]. As such, it is case-sensitive, [code]"*"[/code] matches zero or more characters, and [code]"?"[/code] matches any single character. + If [param recursive] is [code]false[/code], only this node's direct children are checked. Nodes are checked in tree order, so this node's first direct child is checked first, then its own direct children, etc., before moving to the second direct child, and so on. Internal children are also included in the search (see [code]internal[/code] parameter in [method add_child]). + If [param owned] is [code]true[/code], only descendants with a valid [member owner] node are checked. + [b]Note:[/b] This method can be very slow. Consider storing a reference to the found node in a variable. Alternatively, use [method get_node] with unique names (see [member unique_name_in_owner]). [b]Note:[/b] To find all descendant nodes matching a pattern or a class type, see [method find_children]. </description> </method> @@ -247,23 +246,20 @@ <param index="2" name="recursive" type="bool" default="true" /> <param index="3" name="owned" type="bool" default="true" /> <description> - Finds descendants of this node whose name matches [param pattern] as in [method String.match], and/or type matches [param type] as in [method Object.is_class]. Internal children are also searched over (see [code]internal[/code] parameter in [method add_child]). - [param pattern] does not match against the full path, just against individual node names. It is case-sensitive, with [code]"*"[/code] matching zero or more characters and [code]"?"[/code] matching any single character except [code]"."[/code]). - [param type] will check equality or inheritance, and is case-sensitive. [code]"Object"[/code] will match a node whose type is [code]"Node"[/code] but not the other way around. - If [param recursive] is [code]true[/code], all child nodes are included, even if deeply nested. Nodes are checked in tree order, so this node's first direct child is checked first, then its own direct children, etc., before moving to the second direct child, and so on. If [param recursive] is [code]false[/code], only this node's direct children are matched. - If [param owned] is [code]true[/code], this method only finds nodes who have an assigned [member Node.owner]. This is especially important for scenes instantiated through a script, because those scenes don't have an owner. - Returns an empty array if no matching nodes are found. - [b]Note:[/b] As this method walks through all the descendants of the node, it is the slowest way to get references to other nodes. Whenever possible, consider caching the node references into variables. - [b]Note:[/b] If you only want to find the first descendant node that matches a pattern, see [method find_child]. + Finds all descendants of this node whose names match [param pattern], returning an empty [Array] if no match is found. The matching is done against node names, [i]not[/i] their paths, through [method String.match]. As such, it is case-sensitive, [code]"*"[/code] matches zero or more characters, and [code]"?"[/code] matches any single character. + If [param type] is not empty, only ancestors inheriting from [param type] are included (see [method Object.is_class]). + If [param recursive] is [code]false[/code], only this node's direct children are checked. Nodes are checked in tree order, so this node's first direct child is checked first, then its own direct children, etc., before moving to the second direct child, and so on. Internal children are also included in the search (see [code]internal[/code] parameter in [method add_child]). + If [param owned] is [code]true[/code], only descendants with a valid [member owner] node are checked. + [b]Note:[/b] This method can be very slow. Consider storing references to the found nodes in a variable. + [b]Note:[/b] To find a single descendant node matching a pattern, see [method find_child]. </description> </method> <method name="find_parent" qualifiers="const"> <return type="Node" /> <param index="0" name="pattern" type="String" /> <description> - Finds the first parent of the current node whose name matches [param pattern] as in [method String.match]. - [param pattern] does not match against the full path, just against individual node names. It is case-sensitive, with [code]"*"[/code] matching zero or more characters and [code]"?"[/code] matching any single character except [code]"."[/code]). - [b]Note:[/b] As this method walks upwards in the scene tree, it can be slow in large, deeply nested scene trees. Whenever possible, consider using [method get_node] with unique names instead (see [member unique_name_in_owner]), or caching the node references into variable. + Finds the first ancestor of this node whose [member name] matches [param pattern], returning [code]null[/code] if no match is found. The matching is done through [method String.match]. As such, it is case-sensitive, [code]"*"[/code] matches zero or more characters, and [code]"?"[/code] matches any single character. See also [method find_child] and [method find_children]. + [b]Note:[/b] As this method walks upwards in the scene tree, it can be slow in large, deeply nested nodes. Consider storing a reference to the found node in a variable. Alternatively, use [method get_node] with unique names (see [member unique_name_in_owner]). </description> </method> <method name="get_child" qualifiers="const"> @@ -271,44 +267,52 @@ <param index="0" name="idx" type="int" /> <param index="1" name="include_internal" type="bool" default="false" /> <description> - Returns a child node by its index (see [method get_child_count]). This method is often used for iterating all children of a node. - Negative indices access the children from the last one. - If [param include_internal] is [code]false[/code], internal children are skipped (see [code]internal[/code] parameter in [method add_child]). - To access a child node via its name, use [method get_node]. + Fetches a child node by its index. Each child node has an index relative its siblings (see [method get_index]). The first child is at index 0. Negative values can also be used to start from the end of the list. This method can be used in combination with [method get_child_count] to iterate over this node's children. If no child exists at the given index, this method returns [code]null[/code] and an error is generated. + If [param include_internal] is [code]false[/code], internal children are ignored (see [method add_child]'s [code]internal[/code] parameter). + [codeblock] + # Assuming the following are children of this node, in order: + # First, Middle, Last. + + var a = get_child(0).name # a is "First" + var b = get_child(1).name # b is "Middle" + var b = get_child(2).name # b is "Last" + var c = get_child(-1).name # c is "Last" + [/codeblock] + [b]Note:[/b] To fetch a node by [NodePath], use [method get_node]. </description> </method> <method name="get_child_count" qualifiers="const"> <return type="int" /> <param index="0" name="include_internal" type="bool" default="false" /> <description> - Returns the number of child nodes. - If [param include_internal] is [code]false[/code], internal children aren't counted (see [code]internal[/code] parameter in [method add_child]). + Returns the number of children of this node. + If [param include_internal] is [code]false[/code], internal children are not counted (see [method add_child]'s [code]internal[/code] parameter). </description> </method> <method name="get_children" qualifiers="const"> <return type="Node[]" /> <param index="0" name="include_internal" type="bool" default="false" /> <description> - Returns an array of references to node's children. - If [param include_internal] is [code]false[/code], the returned array won't include internal children (see [code]internal[/code] parameter in [method add_child]). + Returns all children of this node inside an [Array]. + If [param include_internal] is [code]false[/code], excludes internal children from the returned array (see [method add_child]'s [code]internal[/code] parameter). </description> </method> <method name="get_groups" qualifiers="const"> <return type="StringName[]" /> <description> - Returns an array listing the groups that the node is a member of. - [b]Note:[/b] For performance reasons, the order of node groups is [i]not[/i] guaranteed. The order of node groups should not be relied upon as it can vary across project runs. - [b]Note:[/b] The engine uses some group names internally (all starting with an underscore). To avoid conflicts with internal groups, do not add custom groups whose name starts with an underscore. To exclude internal groups while looping over [method get_groups], use the following snippet: + Returns an [Array] of group names that the node has been added to. + [b]Note:[/b] To improve performance, the order of group names is [i]not[/i] guaranteed and may vary between project runs. Therefore, do not rely on the group order. + [b]Note:[/b] This method may also return some group names starting with an underscore ([code]_[/code]). These are internally used by the engine. To avoid conflicts, do not use custom groups starting with underscores. To exclude internal groups, see the following code snippet: [codeblocks] [gdscript] - # Stores the node's non-internal groups only (as an array of Strings). + # Stores the node's non-internal groups only (as an array of StringNames). var non_internal_groups = [] for group in get_groups(): - if not group.begins_with("_"): + if not str(group).begins_with("_"): non_internal_groups.push_back(group) [/gdscript] [csharp] - // Stores the node's non-internal groups only (as a List of strings). + // Stores the node's non-internal groups only (as a List of StringNames). List<string> nonInternalGroups = new List<string>(); foreach (string group in GetGroups()) { @@ -323,8 +327,8 @@ <return type="int" /> <param index="0" name="include_internal" type="bool" default="false" /> <description> - Returns the node's order in the scene tree branch. For example, if called on the first child node the position is [code]0[/code]. - If [param include_internal] is [code]false[/code], the index won't take internal children into account, i.e. first non-internal child will have index of 0 (see [code]internal[/code] parameter in [method add_child]). + Returns this node's order among its siblings. The first node's index is [code]0[/code]. See also [method get_child]. + If [param include_internal] is [code]false[/code], returns the index ignoring internal children. The first, non-internal child will have an index of [code]0[/code] (see [method add_child]'s [code]internal[/code] parameter). </description> </method> <method name="get_last_exclusive_window" qualifiers="const"> @@ -343,20 +347,22 @@ <return type="Node" /> <param index="0" name="path" type="NodePath" /> <description> - Fetches a node. The [NodePath] can be either a relative path (from the current node) or an absolute path (in the scene tree) to a node. If the path does not exist, [code]null[/code] is returned and an error is logged. Attempts to access methods on the return value will result in an "Attempt to call <method> on a null instance." error. - [b]Note:[/b] Fetching absolute paths only works when the node is inside the scene tree (see [method is_inside_tree]). - [b]Example:[/b] Assume your current node is Character and the following tree: + Fetches a node. The [NodePath] can either be a relative path (from this node), or an absolute path (from the [member SceneTree.root]) to a node. If [param path] does not point to a valid node, generates an error and returns [code]null[/code]. Attempts to access methods on the return value will result in an [i]"Attempt to call <method> on a null instance."[/i] error. + [b]Note:[/b] Fetching by absolute path only works when the node is inside the scene tree (see [method is_inside_tree]). + [b]Example:[/b] Assume this method is called from the Character node, inside the following tree: [codeblock] - /root - /root/Character - /root/Character/Sword - /root/Character/Backpack/Dagger - /root/MyGame - /root/Swamp/Alligator - /root/Swamp/Mosquito - /root/Swamp/Goblin + ┖╴root + ┠╴Character (you are here!) + ┃ ┠╴Sword + ┃ ┖╴Backpack + ┃ ┖╴Dagger + ┠╴MyGame + ┖╴Swamp + ┠╴Alligator + ┠╴Mosquito + ┖╴Goblin [/codeblock] - Possible paths are: + The following calls will return a valid node: [codeblocks] [gdscript] get_node("Sword") @@ -377,19 +383,43 @@ <return type="Array" /> <param index="0" name="path" type="NodePath" /> <description> - Fetches a node and one of its resources as specified by the [NodePath]'s subname (e.g. [code]Area2D/CollisionShape2D:shape[/code]). If several nested resources are specified in the [NodePath], the last one will be fetched. - The return value is an array of size 3: the first index points to the [Node] (or [code]null[/code] if not found), the second index points to the [Resource] (or [code]null[/code] if not found), and the third index is the remaining [NodePath], if any. - For example, assuming that [code]Area2D/CollisionShape2D[/code] is a valid node and that its [code]shape[/code] property has been assigned a [RectangleShape2D] resource, one could have this kind of output: + Fetches a node and its most nested resource as specified by the [NodePath]'s subname. Returns an [Array] of size [code]3[/code] where: + - Element [code]0[/code] is the [Node], or [code]null[/code] if not found; + - Element [code]1[/code] is the subname's last nested [Resource], or [code]null[/code] if not found; + - Element [code]2[/code] is the remaining [NodePath], referring to an existing, non-[Resource] property (see [method Object.get_indexed]). + [b]Example:[/b] Assume that the child's [member Sprite2D.texture] has been assigned a [AtlasTexture]: [codeblocks] [gdscript] - print(get_node_and_resource("Area2D/CollisionShape2D")) # [[CollisionShape2D:1161], Null, ] - print(get_node_and_resource("Area2D/CollisionShape2D:shape")) # [[CollisionShape2D:1161], [RectangleShape2D:1156], ] - print(get_node_and_resource("Area2D/CollisionShape2D:shape:extents")) # [[CollisionShape2D:1161], [RectangleShape2D:1156], :extents] + var a = get_node_and_resource("Area2D/Sprite2D") + print(a[0].name) # Prints Sprite2D + print(a[1]) # Prints <null> + print(a[2]) # Prints ^"" + + var b = get_node_and_resource("Area2D/Sprite2D:texture:atlas") + print(b[0].name) # Prints Sprite2D + print(b[1].get_class()) # Prints AtlasTexture + print(b[2]) # Prints ^"" + + var c = get_node_and_resource("Area2D/Sprite2D:texture:atlas:region") + print(c[0].name) # Prints Sprite2D + print(c[1].get_class()) # Prints AtlasTexture + print(c[2]) # Prints ^":region" [/gdscript] [csharp] - GD.Print(GetNodeAndResource("Area2D/CollisionShape2D")); // [[CollisionShape2D:1161], Null, ] - GD.Print(GetNodeAndResource("Area2D/CollisionShape2D:shape")); // [[CollisionShape2D:1161], [RectangleShape2D:1156], ] - GD.Print(GetNodeAndResource("Area2D/CollisionShape2D:shape:extents")); // [[CollisionShape2D:1161], [RectangleShape2D:1156], :extents] + var a = GetNodeAndResource(NodePath("Area2D/Sprite2D")); + GD.Print(a[0].Name); // Prints Sprite2D + GD.Print(a[1]); // Prints <null> + GD.Print(a[2]); // Prints ^" + + var b = GetNodeAndResource(NodePath("Area2D/Sprite2D:texture:atlas")); + GD.Print(b[0].name); // Prints Sprite2D + GD.Print(b[1].get_class()); // Prints AtlasTexture + GD.Print(b[2]); // Prints ^"" + + var c = GetNodeAndResource(NodePath("Area2D/Sprite2D:texture:atlas:region")); + GD.Print(c[0].name); // Prints Sprite2D + GD.Print(c[1].get_class()); // Prints AtlasTexture + GD.Print(c[2]); // Prints ^":region" [/csharp] [/codeblocks] </description> @@ -398,19 +428,19 @@ <return type="Node" /> <param index="0" name="path" type="NodePath" /> <description> - Similar to [method get_node], but does not log an error if [param path] does not point to a valid [Node]. + Fetches a node by [NodePath]. Similar to [method get_node], but does not generate an error if [param path] does not point to a valid node. </description> </method> <method name="get_parent" qualifiers="const"> <return type="Node" /> <description> - Returns the parent node of the current node, or [code]null[/code] if the node lacks a parent. + Returns this node's parent node, or [code]null[/code] if the node doesn't have a parent. </description> </method> <method name="get_path" qualifiers="const"> <return type="NodePath" /> <description> - Returns the absolute path of the current node. This only works if the current node is inside the scene tree (see [method is_inside_tree]). + Returns the node's absolute path, relative to the [member SceneTree.root]. If the node is not inside the scene tree, this method fails and returns an empty [NodePath]. </description> </method> <method name="get_path_to" qualifiers="const"> @@ -418,33 +448,33 @@ <param index="0" name="node" type="Node" /> <param index="1" name="use_unique_path" type="bool" default="false" /> <description> - Returns the relative [NodePath] from this node to the specified [param node]. Both nodes must be in the same scene or the function will fail. - If [param use_unique_path] is [code]true[/code], returns the shortest path considering unique node. - [b]Note:[/b] If you get a relative path which starts from a unique node, the path may be longer than a normal relative path due to the addition of the unique node's name. + Returns the relative [NodePath] from this node to the specified [param node]. Both nodes must be in the same [SceneTree], otherwise this method fails and returns an empty [NodePath]. + If [param use_unique_path] is [code]true[/code], returns the shortest path accounting for this node's unique name (see [member unique_name_in_owner]). + [b]Note:[/b] If you get a relative path which starts from a unique node, the path may be longer than a normal relative path, due to the addition of the unique node's name. </description> </method> <method name="get_physics_process_delta_time" qualifiers="const"> <return type="float" /> <description> - Returns the time elapsed (in seconds) since the last physics-bound frame (see [method _physics_process]). This is always a constant value in physics processing unless the frames per second is changed via [member Engine.physics_ticks_per_second]. + Returns the time elapsed (in seconds) since the last physics callback. This value is identical to [method _physics_process]'s [code]delta[/code] parameter, and is often consistent at run-time, unless [member Engine.physics_ticks_per_second] is changed. See also [constant NOTIFICATION_PHYSICS_PROCESS]. </description> </method> <method name="get_process_delta_time" qualifiers="const"> <return type="float" /> <description> - Returns the time elapsed (in seconds) since the last process callback. This value may vary from frame to frame. + Returns the time elapsed (in seconds) since the last process callback. This value is identical to [method _process]'s [code]delta[/code] parameter, and may vary from frame to frame. See also [constant NOTIFICATION_PROCESS]. </description> </method> <method name="get_scene_instance_load_placeholder" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if this is an instance load placeholder. See [InstancePlaceholder]. + Returns [code]true[/code] if this node is an instance load placeholder. See [InstancePlaceholder] and [method set_scene_instance_load_placeholder]. </description> </method> <method name="get_tree" qualifiers="const"> <return type="SceneTree" /> <description> - Returns the [SceneTree] that contains this node. Returns [code]null[/code] and prints an error if this node is not inside the scene tree. See also [method is_inside_tree]. + Returns the [SceneTree] that contains this node. If this node is not inside the tree, generates an error and returns [code]null[/code]. See also [method is_inside_tree]. </description> </method> <method name="get_tree_string"> @@ -480,7 +510,7 @@ <method name="get_viewport" qualifiers="const"> <return type="Viewport" /> <description> - Returns the node's [Viewport]. + Returns the node's closest [Viewport] ancestor, if the node is inside the tree. Otherwise, returns [code]null[/code]. </description> </method> <method name="get_window" qualifiers="const"> @@ -493,54 +523,54 @@ <return type="bool" /> <param index="0" name="path" type="NodePath" /> <description> - Returns [code]true[/code] if the node that the [NodePath] points to exists. + Returns [code]true[/code] if the [param path] points to a valid node. See also [method get_node]. </description> </method> <method name="has_node_and_resource" qualifiers="const"> <return type="bool" /> <param index="0" name="path" type="NodePath" /> <description> - Returns [code]true[/code] if the [NodePath] points to a valid node and its subname points to a valid resource, e.g. [code]Area2D/CollisionShape2D:shape[/code]. Properties with a non-[Resource] type (e.g. nodes or primitive math types) are not considered resources. + Returns [code]true[/code] if [param path] points to a valid node and its subnames point to a valid [Resource], e.g. [code]Area2D/CollisionShape2D:shape[/code]. Properties that are not [Resource] types (such as nodes or other [Variant] types) are not considered. See also [method get_node_and_resource]. </description> </method> <method name="is_ancestor_of" qualifiers="const"> <return type="bool" /> <param index="0" name="node" type="Node" /> <description> - Returns [code]true[/code] if the given node is a direct or indirect child of the current node. + Returns [code]true[/code] if the given [param node] is a direct or indirect child of this node. </description> </method> <method name="is_displayed_folded" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if the node is folded (collapsed) in the Scene dock. This method is only intended for use with editor tooling. + Returns [code]true[/code] if the node is folded (collapsed) in the Scene dock. This method is intended to be used in editor plugins and tools. See also [method set_display_folded]. </description> </method> <method name="is_editable_instance" qualifiers="const"> <return type="bool" /> <param index="0" name="node" type="Node" /> <description> - Returns [code]true[/code] if [param node] has editable children enabled relative to this node. This method is only intended for use with editor tooling. + Returns [code]true[/code] if [param node] has editable children enabled relative to this node. This method is intended to be used in editor plugins and tools. See also [method set_editable_instance]. </description> </method> <method name="is_greater_than" qualifiers="const"> <return type="bool" /> <param index="0" name="node" type="Node" /> <description> - Returns [code]true[/code] if the given node occurs later in the scene hierarchy than the current node. + Returns [code]true[/code] if the given [param node] occurs later in the scene hierarchy than this node. A node occurring later is usually processed last. </description> </method> <method name="is_in_group" qualifiers="const"> <return type="bool" /> <param index="0" name="group" type="StringName" /> <description> - Returns [code]true[/code] if this node is in the specified group. See notes in the description, and the group methods in [SceneTree]. + Returns [code]true[/code] if this node has been added to the given [param group]. See [method add_to_group] and [method remove_from_group]. See also notes in the description, and the [SceneTree]'s group methods. </description> </method> <method name="is_inside_tree" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if this node is currently inside a [SceneTree]. + Returns [code]true[/code] if this node is currently inside a [SceneTree]. See also [method get_tree]. </description> </method> <method name="is_multiplayer_authority" qualifiers="const"> @@ -609,8 +639,8 @@ <param index="0" name="child_node" type="Node" /> <param index="1" name="to_index" type="int" /> <description> - Moves a child node to a different index (order) among the other children. Since calls, signals, etc. are performed by tree order, changing the order of children nodes may be useful. If [param to_index] is negative, the index will be counted from the end. - [b]Note:[/b] Internal children can only be moved within their expected "internal range" (see [code]internal[/code] parameter in [method add_child]). + Moves [param child_node] to the given index. A node's index is the order among its siblings. If [param to_index] is negative, the index is counted from the end of the list. See also [method get_child] and [method get_index]. + [b]Note:[/b] The processing order of several engine callbacks ([method _ready], [method _process], etc.) and notifications sent through [method propagate_notification] is affected by tree order. [CanvasItem] nodes are also rendered in tree order. See also [member process_priority]. </description> </method> <method name="notify_deferred_thread_group"> @@ -630,29 +660,29 @@ <method name="print_orphan_nodes" qualifiers="static"> <return type="void" /> <description> - Prints all orphan nodes (nodes outside the [SceneTree]). Used for debugging. - [b]Note:[/b] [method print_orphan_nodes] only works in debug builds. When called in a project exported in release mode, [method print_orphan_nodes] will not print anything. + Prints all orphan nodes (nodes outside the [SceneTree]). Useful for debugging. + [b]Note:[/b] This method only works in debug builds. Does nothing in a project exported in release mode. </description> </method> <method name="print_tree"> <return type="void" /> <description> - Prints the tree to stdout. Used mainly for debugging purposes. This version displays the path relative to the current node, and is good for copy/pasting into the [method get_node] function. + Prints the node and its children to the console, recursively. The node does not have to be inside the tree. This method outputs [NodePath]s relative to this node, and is good for copy/pasting into [method get_node]. See also [method print_tree_pretty]. [b]Example output:[/b] [codeblock] - TheGame - TheGame/Menu - TheGame/Menu/Label - TheGame/Menu/Camera2D - TheGame/SplashScreen - TheGame/SplashScreen/Camera2D + . + Menu + Menu/Label + Menu/Camera2D + SplashScreen + SplashScreen/Camera2D [/codeblock] </description> </method> <method name="print_tree_pretty"> <return type="void" /> <description> - Similar to [method print_tree], this prints the tree to stdout. This version displays a more graphical representation similar to what is displayed in the Scene Dock. It is useful for inspecting larger trees. + Prints the node and its children to the console, recursively. The node does not have to be inside the tree. Similar to [method print_tree], but the graphical representation looks like what is displayed in the editor's Scene dock. It is useful for inspecting larger trees. [b]Example output:[/b] [codeblock] ┖╴TheGame @@ -670,37 +700,38 @@ <param index="1" name="args" type="Array" default="[]" /> <param index="2" name="parent_first" type="bool" default="false" /> <description> - Calls the given method (if present) with the arguments given in [param args] on this node and recursively on all its children. If the [param parent_first] argument is [code]true[/code], the method will be called on the current node first, then on all its children. If [param parent_first] is [code]false[/code], the children will be called first. + Calls the given [param method] name, passing [param args] as arguments, on this node and all of its children, recursively. + If [param parent_first] is [code]true[/code], the method is called on this node first, then on all of its children. If [code]false[/code], the children's methods are called first. </description> </method> <method name="propagate_notification"> <return type="void" /> <param index="0" name="what" type="int" /> <description> - Notifies the current node and all its children recursively by calling [method Object.notification] on all of them. + Calls [method Object.notification] with [param what] on this node and all of its children, recursively. </description> </method> <method name="queue_free"> <return type="void" /> <description> - Queues a node for deletion at the end of the current frame. When deleted, all of its child nodes will be deleted as well, and all references to the node and its children will become invalid, see [method Object.free]. - It is safe to call [method queue_free] multiple times per frame on a node, and to [method Object.free] a node that is currently queued for deletion. Use [method Object.is_queued_for_deletion] to check whether a node will be deleted at the end of the frame. - The node will only be freed after all other deferred calls are finished, so using [method queue_free] is not always the same as calling [method Object.free] through [method Object.call_deferred]. + Queues this node to be deleted at the end of the current frame. When deleted, all of its children are deleted as well, and all references to the node and its children become invalid. + Unlike with [method Object.free], the node is not deleted instantly, and it can still be accessed before deletion. It is also safe to call [method queue_free] multiple times. Use [method Object.is_queued_for_deletion] to check if the node will be deleted at the end of the frame. + [b]Note:[/b] The node will only be freed after all other deferred calls are finished. Using this method is not always the same as calling [method Object.free] through [method Object.call_deferred]. </description> </method> <method name="remove_child"> <return type="void" /> <param index="0" name="node" type="Node" /> <description> - Removes a child node. The node is NOT deleted and must be deleted manually. - [b]Note:[/b] This function may set the [member owner] of the removed Node (or its descendants) to be [code]null[/code], if that [member owner] is no longer a parent or ancestor. + Removes a child [param node]. The [param node], along with its children, are [b]not[/b] deleted. To delete a node, see [method queue_free]. + [b]Note:[/b] When this node is inside the tree, this method sets the [member owner] of the removed [param node] (or its descendants) to [code]null[/code], if their [member owner] is no longer an ancestor (see [method is_ancestor_of]). </description> </method> <method name="remove_from_group"> <return type="void" /> <param index="0" name="group" type="StringName" /> <description> - Removes a node from the [param group]. Does nothing if the node is not in the [param group]. See notes in the description, and the group methods in [SceneTree]. + Removes the node from the given [param group]. Does nothing if the node is not in the [param group]. See also notes in the description, and the [SceneTree]'s group methods. </description> </method> <method name="reparent"> @@ -708,7 +739,7 @@ <param index="0" name="new_parent" type="Node" /> <param index="1" name="keep_global_transform" type="bool" default="true" /> <description> - Changes the parent of this [Node] to the [param new_parent]. The node needs to already have a parent. + Changes the parent of this [Node] to the [param new_parent]. The node needs to already have a parent. The node's [member owner] is preserved if its owner is still reachable from the new location (i.e., the node is still a descendant of the new parent after the operation). If [param keep_global_transform] is [code]true[/code], the node's global transform will be preserved if supported. [Node2D], [Node3D] and [Control] support this argument (but [Control] keeps only position). </description> </method> @@ -717,24 +748,25 @@ <param index="0" name="node" type="Node" /> <param index="1" name="keep_groups" type="bool" default="false" /> <description> - Replaces a node in a scene by the given one. Subscriptions that pass through this node will be lost. - If [param keep_groups] is [code]true[/code], the [param node] is added to the same groups that the replaced node is in. - [b]Note:[/b] The given node will become the new parent of any child nodes that the replaced node had. - [b]Note:[/b] The replaced node is not automatically freed, so you either need to keep it in a variable for later use or free it using [method Object.free]. + Replaces this node by the given [param node]. All children of this node are moved to [param node]. + If [param keep_groups] is [code]true[/code], the [param node] is added to the same groups that the replaced node is in (see [method add_to_group]). + [b]Warning:[/b] The replaced node is removed from the tree, but it is [b]not[/b] deleted. To prevent memory leaks, store a reference to the node in a variable, or use [method Object.free]. </description> </method> <method name="request_ready"> <return type="void" /> <description> - Requests that [method _ready] be called again. Note that the method won't be called immediately, but is scheduled for when the node is added to the scene tree again. [method _ready] is called only for the node which requested it, which means that you need to request ready for each child if you want them to call [method _ready] too (in which case, [method _ready] will be called in the same order as it would normally). + Requests [method _ready] to be called again the next time the node enters the tree. Does [b]not[/b] immediately call [method _ready]. + [b]Note:[/b] This method only affects the current node. If the node's children also need to request ready, this method needs to be called for each one of them. When the node and its children enter the tree again, the order of [method _ready] callbacks will be the same as normal. </description> </method> <method name="rpc" qualifiers="vararg"> <return type="int" enum="Error" /> <param index="0" name="method" type="StringName" /> <description> - Sends a remote procedure call request for the given [param method] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behavior depends on the RPC configuration for the given method, see [method rpc_config] and [annotation @GDScript.@rpc]. Methods are not exposed to RPCs by default. Returns [code]null[/code]. - [b]Note:[/b] You can only safely use RPCs on clients after you received the [code]connected_to_server[/code] signal from the [MultiplayerAPI]. You also need to keep track of the connection state, either by the [MultiplayerAPI] signals like [code]server_disconnected[/code] or by checking [code]get_multiplayer().peer.get_connection_status() == CONNECTION_CONNECTED[/code]. + Sends a remote procedure call request for the given [param method] to peers on the network (and locally), sending additional arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same [member name]. Behavior depends on the RPC configuration for the given [param method] (see [method rpc_config] and [annotation @GDScript.@rpc]). By default, methods are not exposed to RPCs. + May return [constant OK] if the call is successful, [constant ERR_INVALID_PARAMETER] if the arguments passed in the [param method] do not match, [constant ERR_UNCONFIGURED] if the node's [member multiplayer] cannot be fetched (such as when the node is not inside the tree), [constant ERR_CONNECTION_ERROR] if [member multiplayer]'s connection is not available. + [b]Note:[/b] You can only safely use RPCs on clients after you received the [signal MultiplayerAPI.connected_to_server] signal from the [MultiplayerAPI]. You also need to keep track of the connection state, either by the [MultiplayerAPI] signals like [signal MultiplayerAPI.server_disconnected] or by checking ([code]get_multiplayer().peer.get_connection_status() == CONNECTION_CONNECTED[/code]). </description> </method> <method name="rpc_config"> @@ -742,16 +774,12 @@ <param index="0" name="method" type="StringName" /> <param index="1" name="config" type="Variant" /> <description> - Changes the RPC mode for the given [param method] with the given [param config] which should be [code]null[/code] (to disable) or a [Dictionary] in the form: - [codeblock] - { - rpc_mode = MultiplayerAPI.RPCMode, - transfer_mode = MultiplayerPeer.TransferMode, - call_local = false, - channel = 0, - } - [/codeblock] - See [enum MultiplayerAPI.RPCMode] and [enum MultiplayerPeer.TransferMode]. An alternative is annotating methods and properties with the corresponding [annotation @GDScript.@rpc] annotation ([code]@rpc("any_peer")[/code], [code]@rpc("authority")[/code]). By default, methods are not exposed to networking (and RPCs). + Changes the RPC configuration for the given [param method]. [param config] should either be [code]null[/code] to disable the feature (as by default), or a [Dictionary] containing the following entries: + - [code]rpc_mode[/code]: see [enum MultiplayerAPI.RPCMode]; + - [code]transfer_mode[/code]: see [enum MultiplayerPeer.TransferMode]; + - [code]call_local[/code]: if [code]true[/code], the method will also be called locally; + - [code]channel[/code]: an [int] representing the channel to send the RPC on. + [b]Note:[/b] In GDScript, this method corresponds to the [annotation @GDScript.@rpc] annotation, with various parameters passed ([code]@rpc(any)[/code], [code]@rpc(authority)[/code]...). See also the [url=$DOCS_URL/tutorials/networking/high_level_multiplayer.html]high-level multiplayer[/url] tutorial. </description> </method> <method name="rpc_id" qualifiers="vararg"> @@ -759,7 +787,8 @@ <param index="0" name="peer_id" type="int" /> <param index="1" name="method" type="StringName" /> <description> - Sends a [method rpc] to a specific peer identified by [param peer_id] (see [method MultiplayerPeer.set_target_peer]). Returns [code]null[/code]. + Sends a [method rpc] to a specific peer identified by [param peer_id] (see [method MultiplayerPeer.set_target_peer]). + May return [constant OK] if the call is successful, [constant ERR_INVALID_PARAMETER] if the arguments passed in the [param method] do not match, [constant ERR_UNCONFIGURED] if the node's [member multiplayer] cannot be fetched (such as when the node is not inside the tree), [constant ERR_CONNECTION_ERROR] if [member multiplayer]'s connection is not available. </description> </method> <method name="set_deferred_thread_group"> @@ -774,7 +803,7 @@ <return type="void" /> <param index="0" name="fold" type="bool" /> <description> - Sets the folded state of the node in the Scene dock. This method is only intended for use with editor tooling. + If set to [code]true[/code], the node appears folded in the Scene dock. As a result, all of its children are hidden. This method is intended to be used in editor plugins and tools, but it also works in release builds. See also [method is_displayed_folded]. </description> </method> <method name="set_editable_instance"> @@ -782,7 +811,7 @@ <param index="0" name="node" type="Node" /> <param index="1" name="is_editable" type="bool" /> <description> - Sets the editable children state of [param node] relative to this node. This method is only intended for use with editor tooling. + Set to [code]true[/code] to allow all nodes owned by [param node] to be available, and editable, in the Scene dock, even if their [member owner] is not the scene root. This method is intended to be used in editor plugins and tools, but it also works in release builds. See also [method is_editable_instance]. </description> </method> <method name="set_multiplayer_authority"> @@ -790,73 +819,74 @@ <param index="0" name="id" type="int" /> <param index="1" name="recursive" type="bool" default="true" /> <description> - Sets the node's multiplayer authority to the peer with the given peer ID. The multiplayer authority is the peer that has authority over the node on the network. Useful in conjunction with [method rpc_config] and the [MultiplayerAPI]. Defaults to peer ID 1 (the server). If [param recursive], the given peer is recursively set as the authority for all children of this node. - [b]Warning:[/b] This does [b]not[/b] automatically replicate the new authority to other peers. It is developer's responsibility to do so. You can propagate the information about the new authority using [member MultiplayerSpawner.spawn_function], an RPC, or using a [MultiplayerSynchronizer]. Also, the parent's authority does [b]not[/b] propagate to newly added children. + Sets the node's multiplayer authority to the peer with the given peer [param id]. The multiplayer authority is the peer that has authority over the node on the network. Defaults to peer ID 1 (the server). Useful in conjunction with [method rpc_config] and the [MultiplayerAPI]. + If [param recursive] is [code]true[/code], the given peer is recursively set as the authority for all children of this node. + [b]Warning:[/b] This does [b]not[/b] automatically replicate the new authority to other peers. It is the developer's responsibility to do so. You may replicate the new authority's information using [member MultiplayerSpawner.spawn_function], an RPC, or a [MultiplayerSynchronizer]. Furthermore, the parent's authority does [b]not[/b] propagate to newly added children. </description> </method> <method name="set_physics_process"> <return type="void" /> <param index="0" name="enable" type="bool" /> <description> - Enables or disables physics (i.e. fixed framerate) processing. When a node is being processed, it will receive a [constant NOTIFICATION_PHYSICS_PROCESS] at a fixed (usually 60 FPS, see [member Engine.physics_ticks_per_second] to change) interval (and the [method _physics_process] callback will be called if exists). Enabled automatically if [method _physics_process] is overridden. Any calls to this before [method _ready] will be ignored. + If set to [code]true[/code], enables physics (fixed framerate) processing. When a node is being processed, it will receive a [constant NOTIFICATION_PHYSICS_PROCESS] at a fixed (usually 60 FPS, see [member Engine.physics_ticks_per_second] to change) interval (and the [method _physics_process] callback will be called if exists). Enabled automatically if [method _physics_process] is overridden. </description> </method> <method name="set_physics_process_internal"> <return type="void" /> <param index="0" name="enable" type="bool" /> <description> - Enables or disables internal physics for this node. Internal physics processing happens in isolation from the normal [method _physics_process] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or physics processing is disabled for scripting ([method set_physics_process]). Only useful for advanced uses to manipulate built-in nodes' behavior. - [b]Warning:[/b] Built-in Nodes rely on the internal processing for their own logic, so changing this value from your code may lead to unexpected behavior. Script access to this internal logic is provided for specific advanced uses, but is unsafe and not supported. + If set to [code]true[/code], enables internal physics for this node. Internal physics processing happens in isolation from the normal [method _physics_process] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or physics processing is disabled for scripting ([method set_physics_process]). + [b]Warning:[/b] Built-in nodes rely on internal processing for their internal logic. Disabling it is unsafe and may lead to unexpected behavior. Use this method if you know what you are doing. </description> </method> <method name="set_process"> <return type="void" /> <param index="0" name="enable" type="bool" /> <description> - Enables or disables processing. When a node is being processed, it will receive a [constant NOTIFICATION_PROCESS] on every drawn frame (and the [method _process] callback will be called if exists). Enabled automatically if [method _process] is overridden. Any calls to this before [method _ready] will be ignored. + If set to [code]true[/code], enables processing. When a node is being processed, it will receive a [constant NOTIFICATION_PROCESS] on every drawn frame (and the [method _process] callback will be called if exists). Enabled automatically if [method _process] is overridden. </description> </method> <method name="set_process_input"> <return type="void" /> <param index="0" name="enable" type="bool" /> <description> - Enables or disables input processing. This is not required for GUI controls! Enabled automatically if [method _input] is overridden. Any calls to this before [method _ready] will be ignored. + If set to [code]true[/code], enables input processing. This is not required for GUI controls! Enabled automatically if [method _input] is overridden. </description> </method> <method name="set_process_internal"> <return type="void" /> <param index="0" name="enable" type="bool" /> <description> - Enables or disabled internal processing for this node. Internal processing happens in isolation from the normal [method _process] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or processing is disabled for scripting ([method set_process]). Only useful for advanced uses to manipulate built-in nodes' behavior. - [b]Warning:[/b] Built-in Nodes rely on the internal processing for their own logic, so changing this value from your code may lead to unexpected behavior. Script access to this internal logic is provided for specific advanced uses, but is unsafe and not supported. + If set to [code]true[/code], enables internal processing for this node. Internal processing happens in isolation from the normal [method _process] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or processing is disabled for scripting ([method set_process]). + [b]Warning:[/b] Built-in nodes rely on internal processing for their internal logic. Disabling it is unsafe and may lead to unexpected behavior. Use this method if you know what you are doing. </description> </method> <method name="set_process_shortcut_input"> <return type="void" /> <param index="0" name="enable" type="bool" /> <description> - Enables shortcut processing. Enabled automatically if [method _shortcut_input] is overridden. Any calls to this before [method _ready] will be ignored. + If set to [code]true[/code], enables shortcut processing for this node. Enabled automatically if [method _shortcut_input] is overridden. </description> </method> <method name="set_process_unhandled_input"> <return type="void" /> <param index="0" name="enable" type="bool" /> <description> - Enables unhandled input processing. This is not required for GUI controls! It enables the node to receive all input that was not previously handled (usually by a [Control]). Enabled automatically if [method _unhandled_input] is overridden. Any calls to this before [method _ready] will be ignored. + If set to [code]true[/code], enables unhandled input processing. This is not required for GUI controls! It enables the node to receive all input that was not previously handled (usually by a [Control]). Enabled automatically if [method _unhandled_input] is overridden. </description> </method> <method name="set_process_unhandled_key_input"> <return type="void" /> <param index="0" name="enable" type="bool" /> <description> - Enables unhandled key input processing. Enabled automatically if [method _unhandled_key_input] is overridden. Any calls to this before [method _ready] will be ignored. + If set to [code]true[/code], enables unhandled key input processing. Enabled automatically if [method _unhandled_key_input] is overridden. </description> </method> <method name="set_scene_instance_load_placeholder"> <return type="void" /> <param index="0" name="load_placeholder" type="bool" /> <description> - Sets whether this is an instance load placeholder. See [InstancePlaceholder]. + If set to [code]true[/code], the node becomes a [InstancePlaceholder] when packed and instantiated from a [PackedScene]. See also [method get_scene_instance_load_placeholder]. </description> </method> <method name="set_thread_safe"> @@ -870,35 +900,34 @@ <method name="update_configuration_warnings"> <return type="void" /> <description> - Updates the warning displayed for this node in the Scene Dock. - Use [method _get_configuration_warnings] to setup the warning message to display. + Refreshes the warnings displayed for this node in the Scene dock. Use [method _get_configuration_warnings] to customize the warning messages to display. </description> </method> </methods> <members> <member name="editor_description" type="String" setter="set_editor_description" getter="get_editor_description" default=""""> - Add a custom description to a node. It will be displayed in a tooltip when hovered in editor's scene tree. + An optional description to the node. It will be displayed as a tooltip when hovering over the node in the editor's Scene dock. </member> <member name="multiplayer" type="MultiplayerAPI" setter="" getter="get_multiplayer"> The [MultiplayerAPI] instance associated with this node. See [method SceneTree.get_multiplayer]. [b]Note:[/b] Renaming the node, or moving it in the tree, will not move the [MultiplayerAPI] to the new path, you will have to update this manually. </member> <member name="name" type="StringName" setter="set_name" getter="get_name"> - The name of the node. This name is unique among the siblings (other child nodes from the same parent). When set to an existing name, the node will be automatically renamed. - [b]Note:[/b] Auto-generated names might include the [code]@[/code] character, which is reserved for unique names when using [method add_child]. When setting the name manually, any [code]@[/code] will be removed. + The name of the node. This name must be unique among the siblings (other child nodes from the same parent). When set to an existing sibling's name, the node is automatically renamed. + [b]Note:[/b] When changing the name, the following characters will be removed: ([code].[/code] [code]:[/code] [code]@[/code] [code]/[/code] [code]"[/code] [code]%[/code]). In particular, the [code]@[/code] character is reserved for auto-generated names. See also [method String.validate_node_name]. </member> <member name="owner" type="Node" setter="set_owner" getter="get_owner"> - The node owner. A node can have any ancestor node as owner (i.e. a parent, grandparent, etc. node ascending in the tree). This implies that [method add_child] should be called before setting the owner, so that this relationship of parenting exists. When saving a node (using [PackedScene]), all the nodes it owns will be saved with it. This allows for the creation of complex scene trees, with instancing and subinstancing. - [b]Note:[/b] If you want a child to be persisted to a [PackedScene], you must set [member owner] in addition to calling [method add_child]. This is typically relevant for [url=$DOCS_URL/tutorials/plugins/running_code_in_the_editor.html]tool scripts[/url] and [url=$DOCS_URL/tutorials/plugins/editor/index.html]editor plugins[/url]. If a new node is added to the tree without setting its owner as an ancestor in that tree, it will be visible in the 2D/3D view, but not in the scene tree (and not persisted when packing or saving). + The owner of this node. The owner must be an ancestor of this node. When packing the owner node in a [PackedScene], all the nodes it owns are also saved with it. + [b]Note:[/b] In the editor, nodes not owned by the scene root are usually not displayed in the Scene dock, and will [b]not[/b] be saved. To prevent this, remember to set the owner after calling [method add_child]. See also (see [member unique_name_in_owner]) </member> <member name="process_mode" type="int" setter="set_process_mode" getter="get_process_mode" enum="Node.ProcessMode" default="0"> - Can be used to pause or unpause the node, or make the node paused based on the [SceneTree], or make it inherit the process mode from its parent (default). + The node's processing behavior (see [enum ProcessMode]). To check if the node is able to process, with the current mode and [member SceneTree.paused], use [method can_process]. </member> <member name="process_physics_priority" type="int" setter="set_physics_process_priority" getter="get_physics_process_priority" default="0"> Similar to [member process_priority] but for [constant NOTIFICATION_PHYSICS_PROCESS], [method _physics_process] or the internal version. </member> <member name="process_priority" type="int" setter="set_process_priority" getter="get_process_priority" default="0"> - The node's priority in the execution order of the enabled processing callbacks (i.e. [constant NOTIFICATION_PROCESS], [constant NOTIFICATION_PHYSICS_PROCESS] and their internal counterparts). Nodes whose process priority value is [i]lower[/i] will have their processing callbacks executed first. + The node's execution order of the process callbacks ([method _process], [method _physics_process], and internal processing). Nodes whose priority value is [i]lower[/i] call their process callbacks first, regardless of tree order. </member> <member name="process_thread_group" type="int" setter="set_process_thread_group" getter="get_process_thread_group" enum="Node.ProcessThreadGroup" default="0"> Set the process thread group for this node (basically, whether it receives [constant NOTIFICATION_PROCESS], [constant NOTIFICATION_PHYSICS_PROCESS], [method _process] or [method _physics_process] (and the internal versions) on the main thread or in a sub-thread. @@ -913,26 +942,26 @@ Set whether the current thread group will process messages (calls to [method call_deferred_thread_group] on threads, and whether it wants to receive them during regular process or physics process callbacks. </member> <member name="scene_file_path" type="String" setter="set_scene_file_path" getter="get_scene_file_path"> - If a scene is instantiated from a file, its topmost node contains the absolute file path from which it was loaded in [member scene_file_path] (e.g. [code]res://levels/1.tscn[/code]). Otherwise, [member scene_file_path] is set to an empty string. + The original scene's file path, if the node has been instantiated from a [PackedScene] file. Only scene root nodes contains this. </member> <member name="unique_name_in_owner" type="bool" setter="set_unique_name_in_owner" getter="is_unique_name_in_owner" default="false"> - Sets this node's name as a unique name in its [member owner]. This allows the node to be accessed as [code]%Name[/code] instead of the full path, from any node within that scene. - If another node with the same owner already had that name declared as unique, that other node's name will no longer be set as having a unique name. + If [code]true[/code], the node can be accessed from any node sharing the same [member owner] or from the [member owner] itself, with special [code]%Name[/code] syntax in [method get_node]. + [b]Note:[/b] If another node with the same [member owner] shares the same [member name] as this node, the other node will no longer be accessible as unique. </member> </members> <signals> <signal name="child_entered_tree"> <param index="0" name="node" type="Node" /> <description> - Emitted when a child node enters the scene tree, either because it entered on its own or because this node entered with it. + Emitted when the child [param node] enters the [SceneTree], usually because this node entered the tree (see [signal tree_entered]), or [method add_child] has been called. This signal is emitted [i]after[/i] the child node's own [constant NOTIFICATION_ENTER_TREE] and [signal tree_entered]. </description> </signal> <signal name="child_exiting_tree"> <param index="0" name="node" type="Node" /> <description> - Emitted when a child node is about to exit the scene tree, either because it is being removed or freed directly, or because this node is exiting the tree. - When this signal is received, the child [param node] is still in the tree and valid. This signal is emitted [i]after[/i] the child node's own [signal tree_exiting] and [constant NOTIFICATION_EXIT_TREE]. + Emitted when the child [param node] is about to exit the [SceneTree], usually because this node is exiting the tree (see [signal tree_exiting]), or because the child [param node] is being removed or freed. + When this signal is received, the child [param node] is still accessible inside the tree. This signal is emitted [i]after[/i] the child node's own [signal tree_exiting] and [constant NOTIFICATION_EXIT_TREE]. </description> </signal> <signal name="child_order_changed"> @@ -940,14 +969,20 @@ Emitted when the list of children is changed. This happens when child nodes are added, moved or removed. </description> </signal> + <signal name="editor_description_changed"> + <param index="0" name="node" type="Node" /> + <description> + Emitted when the node's editor description field changed. + </description> + </signal> <signal name="ready"> <description> - Emitted when the node is ready. Comes after [method _ready] callback and follows the same rules. + Emitted when the node is considered ready, after [method _ready] is called. </description> </signal> <signal name="renamed"> <description> - Emitted when the node is renamed. + Emitted when the node's [member name] is changed, if the node is inside the tree. </description> </signal> <signal name="replacing_by"> @@ -966,23 +1001,24 @@ <signal name="tree_exited"> <description> Emitted after the node exits the tree and is no longer active. + This signal is emitted [i]after[/i] the related [constant NOTIFICATION_EXIT_TREE] notification. </description> </signal> <signal name="tree_exiting"> <description> - Emitted when the node is still active but about to exit the tree. This is the right place for de-initialization (or a "destructor", if you will). - This signal is emitted [i]before[/i] the related [constant NOTIFICATION_EXIT_TREE] notification. + Emitted when the node is just about to exit the tree. The node is still valid. As such, this is the right place for de-initialization (or a "destructor", if you will). + This signal is emitted [i]after[/i] the node's [method _exit_tree], and [i]before[/i] the related [constant NOTIFICATION_EXIT_TREE]. </description> </signal> </signals> <constants> <constant name="NOTIFICATION_ENTER_TREE" value="10"> - Notification received when the node enters a [SceneTree]. - This notification is emitted [i]before[/i] the related [signal tree_entered]. + Notification received when the node enters a [SceneTree]. See [method _enter_tree]. + This notification is received [i]before[/i] the related [signal tree_entered] signal. </constant> <constant name="NOTIFICATION_EXIT_TREE" value="11"> - Notification received when the node is about to exit a [SceneTree]. - This notification is emitted [i]after[/i] the related [signal tree_exiting]. + Notification received when the node is about to exit a [SceneTree]. See [method _exit_tree]. + This notification is received [i]after[/i] the related [signal tree_exiting] signal. </constant> <constant name="NOTIFICATION_MOVED_IN_PARENT" value="12" is_deprecated="true"> [i]Deprecated.[/i] This notification is no longer emitted. Use [constant NOTIFICATION_CHILD_ORDER_CHANGED] instead. @@ -991,26 +1027,27 @@ Notification received when the node is ready. See [method _ready]. </constant> <constant name="NOTIFICATION_PAUSED" value="14"> - Notification received when the node is paused. + Notification received when the node is paused. See [member process_mode]. </constant> <constant name="NOTIFICATION_UNPAUSED" value="15"> - Notification received when the node is unpaused. + Notification received when the node is unpaused. See [member process_mode]. </constant> <constant name="NOTIFICATION_PHYSICS_PROCESS" value="16"> - Notification received every frame when the physics process flag is set (see [method set_physics_process]). + Notification received from the tree every physics frame when [method is_physics_processing] returns [code]true[/code]. See [method _physics_process]. </constant> <constant name="NOTIFICATION_PROCESS" value="17"> - Notification received every frame when the process flag is set (see [method set_process]). + Notification received from the tree every rendered frame when [method is_processing] returns [code]true[/code]. See [method _process]. </constant> <constant name="NOTIFICATION_PARENTED" value="18"> - Notification received when a node is set as a child of another node. - [b]Note:[/b] This doesn't mean that a node entered the [SceneTree]. + Notification received when the node is set as a child of another node (see [method add_child] and [method add_sibling]). + [b]Note:[/b] This does [i]not[/i] mean that the node entered the [SceneTree]. </constant> <constant name="NOTIFICATION_UNPARENTED" value="19"> - Notification received when a node is unparented (parent removed it from the list of children). + Notification received when the parent node calls [method remove_child] on this node. + [b]Note:[/b] This does [i]not[/i] mean that the node exited the [SceneTree]. </constant> <constant name="NOTIFICATION_SCENE_INSTANTIATED" value="20"> - Notification received by scene owner when its scene is instantiated. + Notification received [i]only[/i] by the newly instantiated scene root node, when [method PackedScene.instantiate] is completed. </constant> <constant name="NOTIFICATION_DRAG_BEGIN" value="21"> Notification received when a drag operation begins. All nodes receive this notification, not only the dragged one. @@ -1022,19 +1059,19 @@ Use [method Viewport.gui_is_drag_successful] to check if the drag succeeded. </constant> <constant name="NOTIFICATION_PATH_RENAMED" value="23"> - Notification received when the node's name or one of its parents' name is changed. This notification is [i]not[/i] received when the node is removed from the scene tree to be added to another parent later on. + Notification received when the node's [member name] or one of its ancestors' [member name] is changed. This notification is [i]not[/i] received when the node is removed from the [SceneTree]. </constant> <constant name="NOTIFICATION_CHILD_ORDER_CHANGED" value="24"> Notification received when the list of children is changed. This happens when child nodes are added, moved or removed. </constant> <constant name="NOTIFICATION_INTERNAL_PROCESS" value="25"> - Notification received every frame when the internal process flag is set (see [method set_process_internal]). + Notification received from the tree every rendered frame when [method is_processing_internal] returns [code]true[/code]. </constant> <constant name="NOTIFICATION_INTERNAL_PHYSICS_PROCESS" value="26"> - Notification received every frame when the internal physics process flag is set (see [method set_physics_process_internal]). + Notification received from the tree every physics frame when [method is_physics_processing_internal] returns [code]true[/code]. </constant> <constant name="NOTIFICATION_POST_ENTER_TREE" value="27"> - Notification received when the node is ready, just before [constant NOTIFICATION_READY] is received. Unlike the latter, it's sent every time the node enters the tree, instead of only once. + Notification received when the node enters the tree, just before [constant NOTIFICATION_READY] may be received. Unlike the latter, it is sent every time the node enters tree, not just once. </constant> <constant name="NOTIFICATION_DISABLED" value="28"> Notification received when the node is disabled. See [constant PROCESS_MODE_DISABLED]. @@ -1057,11 +1094,11 @@ Implemented for embedded windows and on desktop and web platforms. </constant> <constant name="NOTIFICATION_WM_WINDOW_FOCUS_IN" value="1004"> - Notification received when the node's parent [Window] is focused. This may be a change of focus between two windows of the same engine instance, or from the OS desktop or a third-party application to a window of the game (in which case [constant NOTIFICATION_APPLICATION_FOCUS_IN] is also emitted). + Notification received from the OS when the node's [Window] ancestor is focused. This may be a change of focus between two windows of the same engine instance, or from the OS desktop or a third-party application to a window of the game (in which case [constant NOTIFICATION_APPLICATION_FOCUS_IN] is also received). A [Window] node receives this notification when it is focused. </constant> <constant name="NOTIFICATION_WM_WINDOW_FOCUS_OUT" value="1005"> - Notification received when the node's parent [Window] is defocused. This may be a change of focus between two windows of the same engine instance, or from a window of the game to the OS desktop or a third-party application (in which case [constant NOTIFICATION_APPLICATION_FOCUS_OUT] is also emitted). + Notification received from the OS when the node's [Window] ancestor is defocused. This may be a change of focus between two windows of the same engine instance, or from a window of the game to the OS desktop or a third-party application (in which case [constant NOTIFICATION_APPLICATION_FOCUS_OUT] is also received). A [Window] node receives this notification when it is defocused. </constant> <constant name="NOTIFICATION_WM_CLOSE_REQUEST" value="1006"> @@ -1070,13 +1107,14 @@ </constant> <constant name="NOTIFICATION_WM_GO_BACK_REQUEST" value="1007"> Notification received from the OS when a go back request is sent (e.g. pressing the "Back" button on Android). - Specific to the Android platform. + Implemented only on iOS. </constant> <constant name="NOTIFICATION_WM_SIZE_CHANGED" value="1008"> - Notification received from the OS when the window is resized. + Notification received when the window is resized. + [b]Note:[/b] Only the resized [Window] node receives this notification, and it's not propagated to the child nodes. </constant> <constant name="NOTIFICATION_WM_DPI_CHANGE" value="1009"> - Notification received from the OS when the screen's DPI has been changed. Only implemented on macOS. + Notification received from the OS when the screen's dots per inch (DPI) scale is changed. Only implemented on macOS. </constant> <constant name="NOTIFICATION_VP_MOUSE_ENTER" value="1010"> Notification received when the mouse cursor enters the [Viewport]'s visible area, that is not occluded behind other [Control]s or [Window]s, provided its [member Viewport.gui_disable_input] is [code]false[/code] and regardless if it's currently focused or not. @@ -1086,56 +1124,56 @@ </constant> <constant name="NOTIFICATION_OS_MEMORY_WARNING" value="2009"> Notification received from the OS when the application is exceeding its allocated memory. - Specific to the iOS platform. + Implemented only on iOS. </constant> <constant name="NOTIFICATION_TRANSLATION_CHANGED" value="2010"> Notification received when translations may have changed. Can be triggered by the user changing the locale. Can be used to respond to language changes, for example to change the UI strings on the fly. Useful when working with the built-in translation support, like [method Object.tr]. </constant> <constant name="NOTIFICATION_WM_ABOUT" value="2011"> Notification received from the OS when a request for "About" information is sent. - Specific to the macOS platform. + Implemented only on macOS. </constant> <constant name="NOTIFICATION_CRASH" value="2012"> Notification received from Godot's crash handler when the engine is about to crash. - Implemented on desktop platforms if the crash handler is enabled. + Implemented on desktop platforms, if the crash handler is enabled. </constant> <constant name="NOTIFICATION_OS_IME_UPDATE" value="2013"> Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string). - Specific to the macOS platform. + Implemented only on macOS. </constant> <constant name="NOTIFICATION_APPLICATION_RESUMED" value="2014"> Notification received from the OS when the application is resumed. - Specific to the Android platform. + Implemented only on Android. </constant> <constant name="NOTIFICATION_APPLICATION_PAUSED" value="2015"> Notification received from the OS when the application is paused. - Specific to the Android platform. + Implemented only on Android. </constant> <constant name="NOTIFICATION_APPLICATION_FOCUS_IN" value="2016"> - Notification received from the OS when the application is focused, i.e. when changing the focus from the OS desktop or a thirdparty application to any open window of the Godot instance. + Notification received from the OS when the application is focused, i.e. when changing the focus from the OS desktop or a third-party application to any open window of the Godot instance. Implemented on desktop platforms. </constant> <constant name="NOTIFICATION_APPLICATION_FOCUS_OUT" value="2017"> - Notification received from the OS when the application is defocused, i.e. when changing the focus from any open window of the Godot instance to the OS desktop or a thirdparty application. + Notification received from the OS when the application is defocused, i.e. when changing the focus from any open window of the Godot instance to the OS desktop or a third-party application. Implemented on desktop platforms. </constant> <constant name="NOTIFICATION_TEXT_SERVER_CHANGED" value="2018"> - Notification received when text server is changed. + Notification received when the [TextServer] is changed. </constant> <constant name="PROCESS_MODE_INHERIT" value="0" enum="ProcessMode"> - Inherits process mode from the node's parent. For the root node, it is equivalent to [constant PROCESS_MODE_PAUSABLE]. Default. + Inherits [member process_mode] from the node's parent. For the root node, it is equivalent to [constant PROCESS_MODE_PAUSABLE]. This is the default for any newly created node. </constant> <constant name="PROCESS_MODE_PAUSABLE" value="1" enum="ProcessMode"> - Stops processing when the [SceneTree] is paused (process when unpaused). This is the inverse of [constant PROCESS_MODE_WHEN_PAUSED]. + Stops processing when [member SceneTree.paused] is [code]true[/code]. This is the inverse of [constant PROCESS_MODE_WHEN_PAUSED]. </constant> <constant name="PROCESS_MODE_WHEN_PAUSED" value="2" enum="ProcessMode"> - Only process when the [SceneTree] is paused (don't process when unpaused). This is the inverse of [constant PROCESS_MODE_PAUSABLE]. + Process [b]only[/b] when [member SceneTree.paused] is [code]true[/code]. This is the inverse of [constant PROCESS_MODE_PAUSABLE]. </constant> <constant name="PROCESS_MODE_ALWAYS" value="3" enum="ProcessMode"> - Always process. Continue processing always, ignoring the [SceneTree]'s paused property. This is the inverse of [constant PROCESS_MODE_DISABLED]. + Always process. Keeps processing, ignoring [member SceneTree.paused]. This is the inverse of [constant PROCESS_MODE_DISABLED]. </constant> <constant name="PROCESS_MODE_DISABLED" value="4" enum="ProcessMode"> - Never process. Completely disables processing, ignoring the [SceneTree]'s paused property. This is the inverse of [constant PROCESS_MODE_ALWAYS]. + Never process. Completely disables processing, ignoring [member SceneTree.paused]. This is the inverse of [constant PROCESS_MODE_ALWAYS]. </constant> <constant name="PROCESS_THREAD_GROUP_INHERIT" value="0" enum="ProcessThreadGroup"> If the [member process_thread_group] property is sent to this, the node will belong to any parent (or grandparent) node that has a thread group mode that is not inherit. See [member process_thread_group] for more information. @@ -1153,26 +1191,25 @@ <constant name="FLAG_PROCESS_THREAD_MESSAGES_ALL" value="3" enum="ProcessThreadMessages" is_bitfield="true"> </constant> <constant name="DUPLICATE_SIGNALS" value="1" enum="DuplicateFlags"> - Duplicate the node's signals. + Duplicate the node's signal connections. </constant> <constant name="DUPLICATE_GROUPS" value="2" enum="DuplicateFlags"> Duplicate the node's groups. </constant> <constant name="DUPLICATE_SCRIPTS" value="4" enum="DuplicateFlags"> - Duplicate the node's scripts. + Duplicate the node's script (including the ancestor's script, if combined with [constant DUPLICATE_USE_INSTANTIATION]). </constant> <constant name="DUPLICATE_USE_INSTANTIATION" value="8" enum="DuplicateFlags"> - Duplicate using instancing. - An instance stays linked to the original so when the original changes, the instance changes too. + Duplicate using [method PackedScene.instantiate]. If the node comes from a scene saved on disk, re-uses [method PackedScene.instantiate] as the base for the duplicated node and its children. </constant> <constant name="INTERNAL_MODE_DISABLED" value="0" enum="InternalMode"> - Node will not be internal. + The node will not be internal. </constant> <constant name="INTERNAL_MODE_FRONT" value="1" enum="InternalMode"> - Node will be placed at the front of parent's node list, before any non-internal sibling. + The node will be placed at the beginning of the parent's children list, before any non-internal sibling. </constant> <constant name="INTERNAL_MODE_BACK" value="2" enum="InternalMode"> - Node will be placed at the back of parent's node list, after any non-internal sibling. + The node will be placed at the end of the parent's children list, after any non-internal sibling. </constant> </constants> </class> diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml index 553a3913d8..328e572c13 100644 --- a/doc/classes/NodePath.xml +++ b/doc/classes/NodePath.xml @@ -121,13 +121,13 @@ var node_path = NodePath("Path2D/PathFollow2D/Sprite2D") print(node_path.get_name(0)) # Path2D print(node_path.get_name(1)) # PathFollow2D - print(node_path.get_name(2)) # Sprite + print(node_path.get_name(2)) # Sprite2D [/gdscript] [csharp] var nodePath = new NodePath("Path2D/PathFollow2D/Sprite2D"); GD.Print(nodePath.GetName(0)); // Path2D GD.Print(nodePath.GetName(1)); // PathFollow2D - GD.Print(nodePath.GetName(2)); // Sprite + GD.Print(nodePath.GetName(2)); // Sprite2D [/csharp] [/codeblocks] </description> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 44197dbd0c..188e846f5e 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -4,8 +4,8 @@ Provides access to common operating system functionalities. </brief_description> <description> - This class wraps the most common functionalities for communicating with the host operating system, such as the video driver, delays, environment variables, execution of binaries, command line, etc. - [b]Note:[/b] In Godot 4, [OS] functions related to window management were moved to the [DisplayServer] singleton. + The [OS] class wraps the most common functionalities for communicating with the host operating system, such as the video driver, delays, environment variables, execution of binaries, command line, etc. + [b]Note:[/b] In Godot 4, [OS] functions related to window management, clipboard, and TTS were moved to the [DisplayServer] singleton (and the [Window] class). Functions related to time were removed and are only available in the [Time] class. </description> <tutorials> <link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link> @@ -16,13 +16,13 @@ <param index="0" name="text" type="String" /> <param index="1" name="title" type="String" default=""Alert!"" /> <description> - Displays a modal dialog box using the host OS' facilities. Execution is blocked until the dialog is closed. + Displays a modal dialog box using the host platform's implementation. The engine execution is blocked until the dialog is closed. </description> </method> <method name="close_midi_inputs"> <return type="void" /> <description> - Shuts down system MIDI driver. + Shuts down the system MIDI driver. Godot will no longer receive [InputEventMIDI]. See also [method open_midi_inputs] and [method get_connected_midi_inputs]. [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> @@ -30,7 +30,8 @@ <return type="void" /> <param index="0" name="message" type="String" /> <description> - Crashes the engine (or the editor if called within a [code]@tool[/code] script). This should [i]only[/i] be used for testing the system's crash handler, not for any other purpose. For general error reporting, use (in order of preference) [method @GDScript.assert], [method @GlobalScope.push_error] or [method alert]. See also [method kill]. + Crashes the engine (or the editor if called within a [code]@tool[/code] script). See also [method kill]. + [b]Note:[/b] This method should [i]only[/i] be used for testing the system's crash handler, not for any other purpose. For general error reporting, use (in order of preference) [method @GDScript.assert], [method @GlobalScope.push_error], or [method alert]. </description> </method> <method name="create_instance"> @@ -38,8 +39,9 @@ <param index="0" name="arguments" type="PackedStringArray" /> <description> Creates a new instance of Godot that runs independently. The [param arguments] are used in the given order and separated by a space. - If the process creation succeeds, the method will return the new process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process creation fails, the method will return [code]-1[/code]. - [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. + If the process is successfully created, the method will return the new process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process cannot be created, the method will return [code]-1[/code]. + See [method create_process] if you wish to run a different process. + [b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows. </description> </method> <method name="create_process"> @@ -48,9 +50,9 @@ <param index="1" name="arguments" type="PackedStringArray" /> <param index="2" name="open_console" type="bool" default="false" /> <description> - Creates a new process that runs independently of Godot. It will not terminate if Godot terminates. The path specified in [param path] must exist and be executable file or macOS .app bundle. Platform path resolution will be used. The [param arguments] are used in the given order and separated by a space. - On Windows, if [param open_console] is [code]true[/code] and the process is a console app, a new terminal window will be opened. This is ignored on other platforms. - If the process creation succeeds, the method will return the new process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process creation fails, the method will return [code]-1[/code]. + Creates a new process that runs independently of Godot. It will not terminate when Godot terminates. The path specified in [param path] must exist and be executable file or macOS .app bundle. Platform path resolution will be used. The [param arguments] are used in the given order and separated by a space. + On Windows, if [param open_console] is [code]true[/code] and the process is a console app, a new terminal window will be opened. + If the process is successfully created, this method returns its process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). Otherwise this method returns [code]-1[/code]. For example, running another instance of the project: [codeblocks] [gdscript] @@ -69,8 +71,8 @@ <return type="void" /> <param index="0" name="msec" type="int" /> <description> - Delays execution of the current thread by [param msec] milliseconds. [param msec] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_msec] will do nothing and will print an error message. - [b]Note:[/b] [method delay_msec] is a [i]blocking[/i] way to delay code execution. To delay code execution in a non-blocking way, see [method SceneTree.create_timer]. Awaiting with [method SceneTree.create_timer] will delay the execution of code placed below the [code]await[/code] without affecting the rest of the project (or editor, for [EditorPlugin]s and [EditorScript]s). + Delays execution of the current thread by [param msec] milliseconds. [param msec] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_msec] does nothing and prints an error message. + [b]Note:[/b] [method delay_msec] is a [i]blocking[/i] way to delay code execution. To delay code execution in a non-blocking way, you may use [method SceneTree.create_timer]. Awaiting with [SceneTreeTimer] delays the execution of code placed below the [code]await[/code] without affecting the rest of the project (or editor, for [EditorPlugin]s and [EditorScript]s). [b]Note:[/b] When [method delay_msec] is called on the main thread, it will freeze the project and will prevent it from redrawing and registering input until the delay has passed. When using [method delay_msec] as part of an [EditorPlugin] or [EditorScript], it will freeze the editor but won't freeze the project if it is currently running (since the project is an independent child process). </description> </method> @@ -78,8 +80,8 @@ <return type="void" /> <param index="0" name="usec" type="int" /> <description> - Delays execution of the current thread by [param usec] microseconds. [param usec] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_usec] will do nothing and will print an error message. - [b]Note:[/b] [method delay_usec] is a [i]blocking[/i] way to delay code execution. To delay code execution in a non-blocking way, see [method SceneTree.create_timer]. Awaiting with [method SceneTree.create_timer] will delay the execution of code placed below the [code]await[/code] without affecting the rest of the project (or editor, for [EditorPlugin]s and [EditorScript]s). + Delays execution of the current thread by [param usec] microseconds. [param usec] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_usec] does nothing and prints an error message. + [b]Note:[/b] [method delay_usec] is a [i]blocking[/i] way to delay code execution. To delay code execution in a non-blocking way, you may use [method SceneTree.create_timer]. Awaiting with a [SceneTreeTimer] delays the execution of code placed below the [code]await[/code] without affecting the rest of the project (or editor, for [EditorPlugin]s and [EditorScript]s). [b]Note:[/b] When [method delay_usec] is called on the main thread, it will freeze the project and will prevent it from redrawing and registering input until the delay has passed. When using [method delay_usec] as part of an [EditorPlugin] or [EditorScript], it will freeze the editor but won't freeze the project if it is currently running (since the project is an independent child process). </description> </method> @@ -91,10 +93,11 @@ <param index="3" name="read_stderr" type="bool" default="false" /> <param index="4" name="open_console" type="bool" default="false" /> <description> - Executes a command. The file specified in [param path] must exist and be executable. Platform path resolution will be used. The [param arguments] are used in the given order, separated by spaces, and wrapped in quotes. If an [param output] [Array] is provided, the complete shell output of the process will be appended as a single [String] element in [param output]. If [param read_stderr] is [code]true[/code], the output to the standard error stream will be included too. - On Windows, if [param open_console] is [code]true[/code] and the process is a console app, a new terminal window will be opened. This is ignored on other platforms. - If the command is successfully executed, the method will return the exit code of the command, or [code]-1[/code] if it fails. - [b]Note:[/b] The Godot thread will pause its execution until the executed command terminates. Use [Thread] to create a separate thread that will not pause the Godot thread, or use [method create_process] to create a completely independent process. + Executes the given process in a [i]blocking[/i] way. The file specified in [param path] must exist and be executable. The system path resolution will be used. The [param arguments] are used in the given order, separated by spaces, and wrapped in quotes. + If an [param output] array is provided, the complete shell output of the process is appended to [param output] as a single [String] element. If [param read_stderr] is [code]true[/code], the output to the standard error stream is also appended to the array. + On Windows, if [param open_console] is [code]true[/code] and the process is a console app, a new terminal window is opened. + This method returns the exit code of the command, or [code]-1[/code] if the process fails to execute. + [b]Note:[/b] The main thread will be blocked until the executed command terminates. Use [Thread] to create a separate thread that will not block the main thread, or use [method create_process] to create a completely independent process. For example, to retrieve a list of the working directory's contents: [codeblocks] [gdscript] @@ -128,13 +131,29 @@ <return type="int" enum="Key" /> <param index="0" name="string" type="String" /> <description> - Returns the keycode of the given string (e.g. "Escape"). + Finds the keycode for the given string. The returned values are equivalent to the [enum Key] constants. + [codeblocks] + [gdscript] + print(OS.find_keycode_from_string("C")) # Prints 67 (KEY_C) + print(OS.find_keycode_from_string("Escape")) # Prints 4194305 (KEY_ESCAPE) + print(OS.find_keycode_from_string("Shift+Tab")) # Prints 37748738 (KEY_MASK_SHIFT | KEY_TAB) + print(OS.find_keycode_from_string("Unknown")) # Prints 0 (KEY_NONE) + [/gdscript] + [csharp] + GD.Print(OS.FindKeycodeFromString("C")); // Prints C (Key.C) + GD.Print(OS.FindKeycodeFromString("Escape")); // Prints Escape (Key.Escape) + GD.Print(OS.FindKeycodeFromString("Shift+Tab")); // Prints 37748738 (KeyModifierMask.MaskShift | Key.Tab) + GD.Print(OS.FindKeycodeFromString("Unknown")); // Prints None (Key.None) + [/csharp] + [/codeblocks] + See also [method get_keycode_string]. </description> </method> <method name="get_cache_dir" qualifiers="const"> <return type="String" /> <description> - Returns the [i]global[/i] cache data directory according to the operating system's standards. On the Linux/BSD platform, this path can be overridden by setting the [code]XDG_CACHE_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_config_dir] and [method get_data_dir]. + Returns the [i]global[/i] cache data directory according to the operating system's standards. + On the Linux/BSD platform, this path can be overridden by setting the [code]XDG_CACHE_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_config_dir] and [method get_data_dir]. Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path. </description> </method> @@ -145,12 +164,12 @@ Command-line arguments can be written in any form, including both [code]--key value[/code] and [code]--key=value[/code] forms so they can be properly parsed, as long as custom command-line arguments do not conflict with engine arguments. You can also incorporate environment variables using the [method get_environment] method. You can set [member ProjectSettings.editor/run/main_run_args] to define command-line arguments to be passed by the editor when running the project. - Here's a minimal example on how to parse command-line arguments into a dictionary using the [code]--key=value[/code] form for arguments: + Here's a minimal example on how to parse command-line arguments into a [Dictionary] using the [code]--key=value[/code] form for arguments: [codeblocks] [gdscript] var arguments = {} for argument in OS.get_cmdline_args(): - if argument.find("=") > -1: + if argument.contains("="): var key_value = argument.split("=") arguments[key_value[0].lstrip("--")] = key_value[1] else: @@ -162,7 +181,7 @@ var arguments = new Godot.Collections.Dictionary(); foreach (var argument in OS.GetCmdlineArgs()) { - if (argument.Find("=") > -1) + if (argument.Contains('=')) { string[] keyValue = argument.Split("="); arguments[keyValue[0].LStrip("--")] = keyValue[1]; @@ -176,91 +195,108 @@ } [/csharp] [/codeblocks] - [b]Note:[/b] Passing custom user arguments directly is not recommended, as the engine may discard or modify them. Instead, the best way is to use the standard UNIX double dash ([code]--[/code]) and then pass custom arguments, which the engine itself will ignore. These can be read via [method get_cmdline_user_args]. + [b]Note:[/b] Passing custom user arguments directly is not recommended, as the engine may discard or modify them. Instead, pass the standard UNIX double dash ([code]--[/code]) and then the custom arguments, which the engine will ignore by design. These can be read via [method get_cmdline_user_args]. </description> </method> <method name="get_cmdline_user_args"> <return type="PackedStringArray" /> <description> - Similar to [method get_cmdline_args], but this returns the user arguments (any argument passed after the double dash [code]--[/code] or double plus [code]++[/code] argument). These are left untouched by Godot for the user. [code]++[/code] can be used in situations where [code]--[/code] is intercepted by another program (such as [code]startx[/code]). - For example, in the command line below, [code]--fullscreen[/code] will not be returned in [method get_cmdline_user_args] and [code]--level 1[/code] will only be returned in [method get_cmdline_user_args]: + Returns the command-line user arguments passed to the engine. User arguments are ignored by the engine and reserved for the user. They are passed after the double dash [code]--[/code] argument. [code]++[/code] may be used when [code]--[/code] is intercepted by another program (such as [code]startx[/code]). [codeblock] - godot --fullscreen -- --level 1 - # Or: - godot --fullscreen ++ --level 1 + # Godot has been executed with the following command: + # godot --fullscreen -- --level=2 --hardcore + + OS.get_cmdline_args() # Returns ["--fullscreen", "--level=2", "--hardcore"] + OS.get_cmdline_user_args() # Returns ["--level=2", "--hardcore"] [/codeblock] + To get all passed arguments, use [method get_cmdline_args]. </description> </method> <method name="get_config_dir" qualifiers="const"> <return type="String" /> <description> - Returns the [i]global[/i] user configuration directory according to the operating system's standards. On the Linux/BSD platform, this path can be overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_cache_dir] and [method get_data_dir]. + Returns the [i]global[/i] user configuration directory according to the operating system's standards. + On the Linux/BSD platform, this path can be overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_cache_dir] and [method get_data_dir]. Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path. </description> </method> <method name="get_connected_midi_inputs"> <return type="PackedStringArray" /> <description> - Returns an array of MIDI device names. - The returned array will be empty if the system MIDI driver has not previously been initialized with [method open_midi_inputs]. + Returns an array of connected MIDI device names, if they exist. Returns an empty array if the system MIDI driver has not previously been initialized with [method open_midi_inputs]. See also [method close_midi_inputs]. [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="get_data_dir" qualifiers="const"> <return type="String" /> <description> - Returns the [i]global[/i] user data directory according to the operating system's standards. On the Linux/BSD platform, this path can be overridden by setting the [code]XDG_DATA_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_cache_dir] and [method get_config_dir]. + Returns the [i]global[/i] user data directory according to the operating system's standards. + On the Linux/BSD platform, this path can be overridden by setting the [code]XDG_DATA_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_cache_dir] and [method get_config_dir]. Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path. </description> </method> <method name="get_distribution_name" qualifiers="const"> <return type="String" /> <description> - Returns the name of the distribution for Linux and BSD platforms (e.g. Ubuntu, Manjaro, OpenBSD, etc.). - Returns the same value as [method get_name] for stock Android ROMs, but attempts to return the custom ROM name for popular Android derivatives such as LineageOS. + Returns the name of the distribution for Linux and BSD platforms (e.g. "Ubuntu", "Manjaro", "OpenBSD", etc.). + Returns the same value as [method get_name] for stock Android ROMs, but attempts to return the custom ROM name for popular Android derivatives such as "LineageOS". Returns the same value as [method get_name] for other platforms. - [b]Note:[/b] This method is not supported on the web platform. It returns an empty string. + [b]Note:[/b] This method is not supported on the Web platform. It returns an empty string. </description> </method> <method name="get_environment" qualifiers="const"> <return type="String" /> <param index="0" name="variable" type="String" /> <description> - Returns the value of an environment variable. Returns an empty string if the environment variable doesn't exist. + Returns the value of the given environment variable, or an empty string if [param variable] doesn't exist. [b]Note:[/b] Double-check the casing of [param variable]. Environment variable names are case-sensitive on all platforms except Windows. + [b]Note:[/b] On macOS, applications do not have access to shell environment variables. </description> </method> <method name="get_executable_path" qualifiers="const"> <return type="String" /> <description> - Returns the path to the current engine executable. + Returns the file path to the current engine executable. [b]Note:[/b] On macOS, always use [method create_instance] instead of relying on executable path. </description> </method> <method name="get_granted_permissions" qualifiers="const"> <return type="PackedStringArray" /> <description> - On Android devices: With this function, you can get the list of dangerous permissions that have been granted. - On macOS (sandboxed applications only): This function returns the list of user selected folders accessible to the application. Use native file dialog to request folder access permission. + On Android devices: Returns the list of dangerous permissions that have been granted. + On macOS: Returns the list of user selected folders accessible to the application (sandboxed applications only). Use the native file dialog to request folder access permission. </description> </method> <method name="get_keycode_string" qualifiers="const"> <return type="String" /> <param index="0" name="code" type="int" enum="Key" /> <description> - Returns the given keycode as a string (e.g. Return values: [code]"Escape"[/code], [code]"Shift+Escape"[/code]). - See also [member InputEventKey.keycode] and [method InputEventKey.get_keycode_with_modifiers]. + Returns the given keycode as a [String]. + [codeblocks] + [gdscript] + print(OS.get_keycode_string(KEY_C)) # Prints "C" + print(OS.get_keycode_string(KEY_ESCAPE)) # Prints "Escape" + print(OS.get_keycode_string(KEY_MASK_SHIFT | KEY_TAB)) # Prints "Shift+Tab" + [/gdscript] + [csharp] + GD.Print(OS.GetKeycodeString(Key.C)); // Prints "C" + GD.Print(OS.GetKeycodeString(Key.Escape)); // Prints "Escape" + GD.Print(OS.GetKeycodeString((Key)KeyModifierMask.MaskShift | Key.Tab)); // Prints "Shift+Tab" + [/csharp] + [/codeblocks] + See also [method find_keycode_from_string], [member InputEventKey.keycode], and [method InputEventKey.get_keycode_with_modifiers]. </description> </method> <method name="get_locale" qualifiers="const"> <return type="String" /> <description> - Returns the host OS locale as a string of the form [code]language_Script_COUNTRY_VARIANT@extra[/code]. If you want only the language code and not the fully specified locale from the OS, you can use [method get_locale_language]. - [code]language[/code] - 2 or 3-letter [url=https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes]language code[/url], in lower case. - [code skip-lint]Script[/code] - optional, 4-letter [url=https://en.wikipedia.org/wiki/ISO_15924]script code[/url], in title case. - [code]COUNTRY[/code] - optional, 2 or 3-letter [url=https://en.wikipedia.org/wiki/ISO_3166-1]country code[/url], in upper case. - [code]VARIANT[/code] - optional, language variant, region and sort order. Variant can have any number of underscored keywords. - [code]extra[/code] - optional, semicolon separated list of additional key words. Currency, calendar, sort order and numbering system information. + Returns the host OS locale as a [String] of the form [code]language_Script_COUNTRY_VARIANT@extra[/code]. Every substring after [code]language[/code] is optional and may not exist. + - [code]language[/code] - 2 or 3-letter [url=https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes]language code[/url], in lower case. + - [code skip-lint]Script[/code] - 4-letter [url=https://en.wikipedia.org/wiki/ISO_15924]script code[/url], in title case. + - [code]COUNTRY[/code] - 2 or 3-letter [url=https://en.wikipedia.org/wiki/ISO_3166-1]country code[/url], in upper case. + - [code]VARIANT[/code] - language variant, region and sort order. The variant can have any number of underscored keywords. + - [code]extra[/code] - semicolon separated list of additional key words. This may include currency, calendar, sort order and numbering system information. + If you want only the language code and not the fully specified locale from the OS, you can use [method get_locale_language]. </description> </method> <method name="get_locale_language" qualifiers="const"> @@ -280,11 +316,12 @@ <method name="get_memory_info" qualifiers="const"> <return type="Dictionary" /> <description> - Returns the [Dictionary] with the following keys: - [code]"physical"[/code] - total amount of usable physical memory, in bytes or [code]-1[/code] if unknown. This value can be slightly less than the actual physical memory amount, since it does not include memory reserved by kernel and devices. - [code]"free"[/code] - amount of physical memory, that can be immediately allocated without disk access or other costly operation, in bytes or [code]-1[/code] if unknown. The process might be able to allocate more physical memory, but such allocation will require moving inactive pages to disk and can take some time. - [code]"available"[/code] - amount of memory, that can be allocated without extending the swap file(s), in bytes or [code]-1[/code] if unknown. This value include both physical memory and swap. - [code]"stack"[/code] - size of the current thread stack, in bytes or [code]-1[/code] if unknown. + Returns a [Dictionary] containing information about the current memory with the following entries: + - [code]"physical"[/code] - total amount of usable physical memory in bytes. This value can be slightly less than the actual physical memory amount, since it does not include memory reserved by the kernel and devices. + - [code]"free"[/code] - amount of physical memory, that can be immediately allocated without disk access or other costly operations, in bytes. The process might be able to allocate more physical memory, but this action will require moving inactive pages to disk, which can be expensive. + - [code]"available"[/code] - amount of memory that can be allocated without extending the swap file(s), in bytes. This value includes both physical memory and swap. + - [code]"stack"[/code] - size of the current thread stack in bytes. + [b]Note:[/b] Each entry's value may be [code]-1[/code] if it is unknown. </description> </method> <method name="get_model_name" qualifiers="const"> @@ -297,65 +334,66 @@ <method name="get_name" qualifiers="const"> <return type="String" /> <description> - Returns the name of the host OS. - On Windows, this is [code]"Windows"[/code]. - On macOS, this is [code]"macOS"[/code]. - On Linux-based operating systems, this is [code]"Linux"[/code]. - On BSD-based operating systems, this is [code]"FreeBSD"[/code], [code]"NetBSD"[/code], [code]"OpenBSD"[/code], or [code]"BSD"[/code] as a fallback. - On Android, this is [code]"Android"[/code]. - On iOS, this is [code]"iOS"[/code]. - On the web, this is [code]"Web"[/code]. - [b]Note:[/b] Custom builds of the engine may support additional platforms, such as consoles, yielding other return values. + Returns the name of the host platform. + - On Windows, this is [code]"Windows"[/code]. + - On macOS, this is [code]"macOS"[/code]. + - On Linux-based operating systems, this is [code]"Linux"[/code]. + - On BSD-based operating systems, this is [code]"FreeBSD"[/code], [code]"NetBSD"[/code], [code]"OpenBSD"[/code], or [code]"BSD"[/code] as a fallback. + - On Android, this is [code]"Android"[/code]. + - On iOS, this is [code]"iOS"[/code]. + - On the web, this is [code]"Web"[/code]. + [b]Note:[/b] Custom builds of the engine may support additional platforms, such as consoles, possibly returning other names. [codeblocks] [gdscript] match OS.get_name(): "Windows": - print("Windows") + print("Welcome to Windows!") "macOS": - print("macOS") + print("Welcome to macOS!") "Linux", "FreeBSD", "NetBSD", "OpenBSD", "BSD": - print("Linux/BSD") + print("Welcome to Linux/BSD!") "Android": - print("Android") + print("Welcome to Android!") "iOS": - print("iOS") + print("Welcome to iOS!") "Web": - print("Web") + print("Welcome to the Web!") [/gdscript] [csharp] switch (OS.GetName()) { case "Windows": - GD.Print("Windows"); + GD.Print("Welcome to Windows"); break; case "macOS": - GD.Print("macOS"); + GD.Print("Welcome to macOS!"); break; case "Linux": case "FreeBSD": case "NetBSD": case "OpenBSD": case "BSD": - GD.Print("Linux/BSD"); + GD.Print("Welcome to Linux/BSD!"); break; case "Android": - GD.Print("Android"); + GD.Print("Welcome to Android!"); break; case "iOS": - GD.Print("iOS"); + GD.Print("Welcome to iOS!"); break; case "Web": - GD.Print("Web"); + GD.Print("Welcome to the Web!"); break; } [/csharp] [/codeblocks] + [b]Note:[/b] On Web platforms, it is still possible to determine the host platform's OS with feature tags. See [method has_feature]. </description> </method> <method name="get_process_id" qualifiers="const"> <return type="int" /> <description> - Returns the project's process ID. + Returns the number used by the host machine to uniquely identify this application. [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> @@ -368,7 +406,7 @@ <method name="get_processor_name" qualifiers="const"> <return type="String" /> <description> - Returns the name of the CPU model on the host machine (e.g. "Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz"). + Returns the full name of the CPU model on the host machine (e.g. [code]"Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz"[/code]). [b]Note:[/b] This method is only implemented on Windows, macOS, Linux and iOS. On Android and Web, [method get_processor_name] returns an empty string. </description> </method> @@ -381,13 +419,13 @@ <method name="get_static_memory_peak_usage" qualifiers="const"> <return type="int" /> <description> - Returns the maximum amount of static memory used (only works in debug). + Returns the maximum amount of static memory used. Only works in debug builds. </description> </method> <method name="get_static_memory_usage" qualifiers="const"> <return type="int" /> <description> - Returns the amount of static memory being used by the program in bytes (only works in debug). + Returns the amount of static memory being used by the program in bytes. Only works in debug builds. </description> </method> <method name="get_system_dir" qualifiers="const"> @@ -395,9 +433,9 @@ <param index="0" name="dir" type="int" enum="OS.SystemDir" /> <param index="1" name="shared_storage" type="bool" default="true" /> <description> - Returns the actual path to commonly used folders across different platforms. Available locations are specified in [enum SystemDir]. + Returns the path to commonly used folders across different platforms, as defined by [param dir]. See the [enum SystemDir] constants for available locations. [b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows. - [b]Note:[/b] Shared storage is implemented on Android and allows to differentiate between app specific and shared directories. Shared directories have additional restrictions on Android. + [b]Note:[/b] Shared storage is implemented on Android and allows to differentiate between app specific and shared directories, if [param shared_storage] is [code]true[/code]. Shared directories have additional restrictions on Android. </description> </method> <method name="get_system_font_path" qualifiers="const"> @@ -407,7 +445,7 @@ <param index="2" name="stretch" type="int" default="100" /> <param index="3" name="italic" type="bool" default="false" /> <description> - Returns path to the system font file with [param font_name] and style. Returns empty string if no matching fonts found. + Returns the path to the system font file with [param font_name] and style. Returns an empty string if no matching fonts found. The following aliases can be used to request default fonts: "sans-serif", "serif", "monospace", "cursive", and "fantasy". [b]Note:[/b] Returned font might have different style if the requested style is not available. [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. @@ -423,7 +461,7 @@ <param index="5" name="stretch" type="int" default="100" /> <param index="6" name="italic" type="bool" default="false" /> <description> - Returns an array of the system substitute font file paths, which are similar to the font with [param font_name] and style for the specified text, locale and script. Returns empty array if no matching fonts found. + Returns an array of the system substitute font file paths, which are similar to the font with [param font_name] and style for the specified text, locale, and script. Returns an empty array if no matching fonts found. The following aliases can be used to request default fonts: "sans-serif", "serif", "monospace", "cursive", and "fantasy". [b]Note:[/b] Depending on OS, it's not guaranteed that any of the returned fonts will be suitable for rendering specified text. Fonts should be loaded and checked in the order they are returned, and the first suitable one used. [b]Note:[/b] Returned fonts might have different style if the requested style is not available or belong to a different font family. @@ -433,7 +471,7 @@ <method name="get_system_fonts" qualifiers="const"> <return type="PackedStringArray" /> <description> - Returns list of font family names available. + Returns the list of font family names available. [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> @@ -448,19 +486,19 @@ <return type="String" /> <description> Returns a string that is unique to the device. - [b]Note:[/b] This string may change without notice if the user reinstalls/upgrades their operating system or changes their hardware. This means it should generally not be used to encrypt persistent data as the data saved before an unexpected ID change would become inaccessible. The returned string may also be falsified using external programs, so do not rely on the string returned by [method get_unique_id] for security purposes. - [b]Note:[/b] Returns an empty string and prints an error on Web, as this method cannot be implemented on this platform. + [b]Note:[/b] This string may change without notice if the user reinstalls their operating system, upgrades it, or modifies their hardware. This means it should generally not be used to encrypt persistent data, as the data saved before an unexpected ID change would become inaccessible. The returned string may also be falsified using external programs, so do not rely on the string returned by this method for security purposes. + [b]Note:[/b] On Web, returns an empty string and generates an error, as this method cannot be implemented for security concerns. </description> </method> <method name="get_user_data_dir" qualifiers="const"> <return type="String" /> <description> - Returns the absolute directory path where user data is written ([code]user://[/code]). - On Windows, this is [code]%AppData%\Godot\app_userdata\[project_name][/code], or [code]%AppData%\[custom_name][/code] if [code]use_custom_user_dir[/code] is set. [code]%AppData%[/code] expands to [code]%UserProfile%\AppData\Roaming[/code]. - On macOS, this is [code]~/Library/Application Support/Godot/app_userdata/[project_name][/code], or [code]~/Library/Application Support/[custom_name][/code] if [code]use_custom_user_dir[/code] is set. - On Linux and BSD, this is [code]~/.local/share/godot/app_userdata/[project_name][/code], or [code]~/.local/share/[custom_name][/code] if [code]use_custom_user_dir[/code] is set. - On Android and iOS, this is a sandboxed directory in either internal or external storage, depending on the user's configuration. - On the web, this is a virtual directory managed by the browser. + Returns the absolute directory path where user data is written (the [code]user://[/code] directory in Godot). The path depends on the project name and [member ProjectSettings.application/config/use_custom_user_dir]. + - On Windows, this is [code]%AppData%\Godot\app_userdata\[project_name][/code], or [code]%AppData%\[custom_name][/code] if [code]use_custom_user_dir[/code] is set. [code]%AppData%[/code] expands to [code]%UserProfile%\AppData\Roaming[/code]. + - On macOS, this is [code]~/Library/Application Support/Godot/app_userdata/[project_name][/code], or [code]~/Library/Application Support/[custom_name][/code] if [code]use_custom_user_dir[/code] is set. + - On Linux and BSD, this is [code]~/.local/share/godot/app_userdata/[project_name][/code], or [code]~/.local/share/[custom_name][/code] if [code]use_custom_user_dir[/code] is set. + - On Android and iOS, this is a sandboxed directory in either internal or external storage, depending on the user's configuration. + - On Web, this is a virtual directory managed by the browser. If the project name is empty, [code][project_name][/code] falls back to [code][unnamed project][/code]. Not to be confused with [method get_data_dir], which returns the [i]global[/i] (non-project-specific) user home directory. </description> @@ -469,20 +507,20 @@ <return type="String" /> <description> Returns the exact production and build version of the operating system. This is different from the branded version used in marketing. This helps to distinguish between different releases of operating systems, including minor versions, and insider and custom builds. - For Windows, the major and minor version are returned, as well as the build number. For example, the returned string can look like [code]10.0.9926[/code] for a build of Windows 10, and it can look like [code]6.1.7601[/code] for a build of Windows 7 SP1. - For rolling distributions, such as Arch Linux, an empty string is returned. - For macOS and iOS, the major and minor version are returned, as well as the patch number. - For Android, the SDK version and the incremental build number are returned. If it's a custom ROM, it attempts to return its version instead. - [b]Note:[/b] This method is not supported on the web platform. It returns an empty string. + - For Windows, the major and minor version are returned, as well as the build number. For example, the returned string may look like [code]10.0.9926[/code] for a build of Windows 10, and it may look like [code]6.1.7601[/code] for a build of Windows 7 SP1. + - For rolling distributions, such as Arch Linux, an empty string is returned. + - For macOS and iOS, the major and minor version are returned, as well as the patch number. + - For Android, the SDK version and the incremental build number are returned. If it's a custom ROM, it attempts to return its version instead. + [b]Note:[/b] This method is not supported on the Web platform. It returns an empty string. </description> </method> <method name="get_video_adapter_driver_info" qualifiers="const"> <return type="PackedStringArray" /> <description> - Returns the video adapter driver name and version for the user's currently active graphics card. See also [method RenderingServer.get_video_adapter_api_version]. + Returns the video adapter driver name and version for the user's currently active graphics card, as a [PackedStringArray]. See also [method RenderingServer.get_video_adapter_api_version]. The first element holds the driver name, such as [code]nvidia[/code], [code]amdgpu[/code], etc. - The second element holds the driver version. For e.g. the [code]nvidia[/code] driver on a Linux/BSD platform, the version is in the format [code]510.85.02[/code]. For Windows, the driver's format is [code]31.0.15.1659[/code]. - [b]Note:[/b] This method is only supported on the platforms Linux/BSD and Windows when not running in headless mode. It returns an empty array on other platforms. + The second element holds the driver version. For example, on the [code]nvidia[/code] driver on a Linux/BSD platform, the version is in the format [code]510.85.02[/code]. For Windows, the driver's format is [code]31.0.15.1659[/code]. + [b]Note:[/b] This method is only supported on Linux/BSD and Windows when not running in headless mode. On other platforms, it returns an empty array. </description> </method> <method name="has_environment" qualifiers="const"> @@ -499,8 +537,7 @@ <description> Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on the platform, build, etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=$DOCS_URL/tutorials/export/feature_tags.html]Feature Tags[/url] documentation for more details. [b]Note:[/b] Tag names are case-sensitive. - [b]Note:[/b] On the web platform, one of the following additional tags is defined to indicate host platform: [code]web_android[/code], [code]web_ios[/code], [code]web_linuxbsd[/code], [code]web_macos[/code], or [code]web_windows[/code]. - [b]Note:[/b] On the iOS simulator, the additional [code]simulator[/code] tag is defined. + [b]Note:[/b] On the Web platform, one of the following additional tags is defined to indicate host platform: [code]web_android[/code], [code]web_ios[/code], [code]web_linuxbsd[/code], [code]web_macos[/code], or [code]web_windows[/code]. </description> </method> <method name="is_debug_build" qualifiers="const"> @@ -508,22 +545,35 @@ <description> Returns [code]true[/code] if the Godot binary used to run the project is a [i]debug[/i] export template, or when running in the editor. Returns [code]false[/code] if the Godot binary used to run the project is a [i]release[/i] export template. - To check whether the Godot binary used to run the project is an export template (debug or release), use [code]OS.has_feature("template")[/code] instead. + [b]Note:[/b] To check whether the Godot binary used to run the project is an export template (debug or release), use [code]OS.has_feature("template")[/code] instead. </description> </method> <method name="is_keycode_unicode" qualifiers="const"> <return type="bool" /> <param index="0" name="code" type="int" /> <description> - Returns [code]true[/code] if the input keycode corresponds to a Unicode character. + Returns [code]true[/code] if the input keycode corresponds to a Unicode character. For a list of codes, see the [enum Key] constants. + [codeblocks] + [gdscript] + print(OS.is_keycode_unicode(KEY_G)) # Prints true + print(OS.is_keycode_unicode(KEY_KP_4)) # Prints true + print(OS.is_keycode_unicode(KEY_TAB)) # Prints false + print(OS.is_keycode_unicode(KEY_ESCAPE)) # Prints false + [/gdscript] + [csharp] + GD.Print(OS.IsKeycodeUnicode((long)Key.G)); // Prints true + GD.Print(OS.IsKeycodeUnicode((long)Key.Kp4)); // Prints true + GD.Print(OS.IsKeycodeUnicode((long)Key.Tab)); // Prints false + GD.Print(OS.IsKeycodeUnicode((long)Key.Escape)); // Prints false + [/csharp] + [/codeblocks] </description> </method> <method name="is_process_running" qualifiers="const"> <return type="bool" /> <param index="0" name="pid" type="int" /> <description> - Returns [code]true[/code] if the child process ID ([param pid]) is still running or [code]false[/code] if it has terminated. - Must be a valid ID generated from [method create_process]. + Returns [code]true[/code] if the child process ID ([param pid]) is still running or [code]false[/code] if it has terminated. [param pid] must be a valid ID generated from [method create_process]. [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> @@ -536,8 +586,8 @@ <method name="is_sandboxed" qualifiers="const"> <return type="bool" /> <description> - Returns [code]true[/code] if application is running in the sandbox. - [b]Note:[/b] This method is implemented on macOS and Linux. + Returns [code]true[/code] if the application is running in the sandbox. + [b]Note:[/b] This method is only implemented on macOS and Linux. </description> </method> <method name="is_stdout_verbose" qualifiers="const"> @@ -549,15 +599,15 @@ <method name="is_userfs_persistent" qualifiers="const"> <return type="bool" /> <description> - If [code]true[/code], the [code]user://[/code] file system is persistent, so that its state is the same after a player quits and starts the game again. Relevant to the Web platform, where this persistence may be unavailable. + Returns [code]true[/code] if the [code]user://[/code] file system is persistent, that is, its state is the same after a player quits and starts the game again. Relevant to the Web platform, where this persistence may be unavailable. </description> </method> <method name="kill"> <return type="int" enum="Error" /> <param index="0" name="pid" type="int" /> <description> - Kill (terminate) the process identified by the given process ID ([param pid]), e.g. the one returned by [method execute] in non-blocking mode. See also [method crash]. - [b]Note:[/b] This method can also be used to kill processes that were not spawned by the game. + Kill (terminate) the process identified by the given process ID ([param pid]), such as the ID returned by [method execute] in non-blocking mode. See also [method crash]. + [b]Note:[/b] This method can also be used to kill processes that were not spawned by the engine. [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> @@ -565,9 +615,9 @@ <return type="int" enum="Error" /> <param index="0" name="path" type="String" /> <description> - Moves the file or directory to the system's recycle bin. See also [method DirAccess.remove]. + Moves the file or directory at the given [param path] to the system's recycle bin. See also [method DirAccess.remove]. The method takes only global paths, so you may need to use [method ProjectSettings.globalize_path]. Do not use it for files in [code]res://[/code] as it will not work in exported projects. - [b]Note:[/b] If the user has disabled the recycle bin on their system, the file will be permanently deleted instead. + Returns [constant FAILED] if the file or directory cannot be found, or the system does not support this method. [codeblocks] [gdscript] var file_to_remove = "user://slot1.save" @@ -578,12 +628,14 @@ OS.MoveToTrash(ProjectSettings.GlobalizePath(fileToRemove)); [/csharp] [/codeblocks] + [b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows. + [b]Note:[/b] If the user has disabled the recycle bin on their system, the file will be permanently deleted instead. </description> </method> <method name="open_midi_inputs"> <return type="void" /> <description> - Initializes the singleton for the system MIDI driver. + Initializes the singleton for the system MIDI driver, allowing Godot to receive [InputEventMIDI]. See also [method get_connected_midi_inputs] and [method close_midi_inputs]. [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> @@ -598,14 +650,15 @@ <return type="bool" /> <param index="0" name="name" type="String" /> <description> - At the moment this function is only used by [code]AudioDriverOpenSL[/code] to request permission for [code]RECORD_AUDIO[/code] on Android. + Requests permission from the OS for the given [param name]. Returns [code]true[/code] if the permission has been successfully granted. + [b]Note:[/b] This method is currently only implemented on Android, to specifically request permission for [code]"RECORD_AUDIO"[/code] by [code]AudioDriverOpenSL[/code]. </description> </method> <method name="request_permissions"> <return type="bool" /> <description> - With this function, you can request dangerous permissions since normal permissions are automatically granted at install time in Android applications. - [b]Note:[/b] This method is implemented only on Android. + Requests [i]dangerous[/i] permissions from the OS. Returns [code]true[/code] if permissions have been successfully granted. + [b]Note:[/b] This method is only implemented on Android. Normal permissions are automatically granted at install time in Android applications. </description> </method> <method name="revoke_granted_permissions"> @@ -628,8 +681,8 @@ <param index="0" name="restart" type="bool" /> <param index="1" name="arguments" type="PackedStringArray" default="PackedStringArray()" /> <description> - If [param restart] is [code]true[/code], restarts the project automatically when it is exited with [method SceneTree.quit] or [constant Node.NOTIFICATION_WM_CLOSE_REQUEST]. Command line [param arguments] can be supplied. To restart the project with the same command line arguments as originally used to run the project, pass [method get_cmdline_args] as the value for [param arguments]. - [method set_restart_on_exit] can be used to apply setting changes that require a restart. See also [method is_restart_on_exit_set] and [method get_restart_on_exit_arguments]. + If [param restart] is [code]true[/code], restarts the project automatically when it is exited with [method SceneTree.quit] or [constant Node.NOTIFICATION_WM_CLOSE_REQUEST]. Command-line [param arguments] can be supplied. To restart the project with the same command line arguments as originally used to run the project, pass [method get_cmdline_args] as the value for [param arguments]. + This method can be used to apply setting changes that require a restart. See also [method is_restart_on_exit_set] and [method get_restart_on_exit_arguments]. [b]Note:[/b] This method is only effective on desktop platforms, and only when the project isn't started from the editor. It will have no effect on mobile and Web platforms, or when the project is started from the editor. [b]Note:[/b] If the project process crashes or is [i]killed[/i] by the user (by sending [code]SIGKILL[/code] instead of the usual [code]SIGTERM[/code]), the project won't restart automatically. </description> @@ -638,25 +691,26 @@ <return type="int" enum="Error" /> <param index="0" name="name" type="String" /> <description> - Sets the name of the current thread. + Assigns the given name to the current thread. Returns [constant ERR_UNAVAILABLE] if unavailable on the current platform. </description> </method> <method name="set_use_file_access_save_and_swap"> <return type="void" /> <param index="0" name="enabled" type="bool" /> <description> - Enables backup saves if [param enabled] is [code]true[/code]. + If [param enabled] is [code]true[/code], when opening a file for writing, a temporary file is used in its place. When closed, it is automatically applied to the target file. + This can useful when files may be opened by other applications, such as antiviruses, text editors, or even the Godot editor itself. </description> </method> <method name="shell_open"> <return type="int" enum="Error" /> <param index="0" name="uri" type="String" /> <description> - Requests the OS to open a resource with the most appropriate program. For example: + Requests the OS to open a resource identified by [param uri] with the most appropriate program. For example: - [code]OS.shell_open("C:\\Users\name\Downloads")[/code] on Windows opens the file explorer at the user's Downloads folder. - [code]OS.shell_open("https://godotengine.org")[/code] opens the default web browser on the official Godot website. - [code]OS.shell_open("mailto:example@example.com")[/code] opens the default email client with the "To" field set to [code]example@example.com[/code]. See [url=https://datatracker.ietf.org/doc/html/rfc2368]RFC 2368 - The [code]mailto[/code] URL scheme[/url] for a list of fields that can be added. - Use [method ProjectSettings.globalize_path] to convert a [code]res://[/code] or [code]user://[/code] path into a system path for use with this method. + Use [method ProjectSettings.globalize_path] to convert a [code]res://[/code] or [code]user://[/code] project path into a system path for use with this method. [b]Note:[/b] Use [method String.uri_encode] to encode characters within URLs in a URL-safe, portable way. This is especially required for line breaks. Otherwise, [method shell_open] may not work correctly in a project exported to the Web platform. [b]Note:[/b] This method is implemented on Android, iOS, Web, Linux, macOS and Windows. </description> @@ -666,30 +720,33 @@ <param index="0" name="file_or_dir_path" type="String" /> <param index="1" name="open_folder" type="bool" default="true" /> <description> - Requests the OS to open the file manager, then navigate to the given [param file_or_dir_path] and select the target file or folder. - If [param file_or_dir_path] is a valid directory path, and [param open_folder] is [code]true[/code], the method will open the file manager and enter the target folder without selecting anything. - Use [method ProjectSettings.globalize_path] to convert a [code]res://[/code] or [code]user://[/code] path into a system path for use with this method. - [b]Note:[/b] Currently this method is only implemented on Windows and macOS. On other platforms, it will fallback to [method shell_open] with a directory path of [param file_or_dir_path] with prefix [code]file://[/code]. + Requests the OS to open the file manager, navigate to the given [param file_or_dir_path] and select the target file or folder. + If [param open_folder] is [code]true[/code] and [param file_or_dir_path] is a valid directory path, the OS will open the file manager and navigate to the target folder without selecting anything. + Use [method ProjectSettings.globalize_path] to convert a [code]res://[/code] or [code]user://[/code] project path into a system path to use with this method. + [b]Note:[/b] This method is currently only implemented on Windows and macOS. On other platforms, it will fallback to [method shell_open] with a directory path of [param file_or_dir_path] prefixed with [code]file://[/code]. </description> </method> <method name="unset_environment" qualifiers="const"> <return type="void" /> <param index="0" name="variable" type="String" /> <description> - Removes the environment [param variable] from the current environment, if it exists. The environment variable will be removed for the Godot process and any process executed with [method execute] after running [method unset_environment]. The removal of the environment variable will [i]not[/i] persist to processes run after the Godot process was terminated. - [b]Note:[/b] Environment variable names are case-sensitive on all platforms except Windows. The [param variable] name cannot be empty or include the [code]=[/code] character. + Removes the given environment variable from the current environment, if it exists. The [param variable] name cannot be empty or include the [code]=[/code] character. The environment variable will be removed for the Godot process and any process executed with [method execute] after running [method unset_environment]. The removal of the environment variable will [i]not[/i] persist to processes run after the Godot process was terminated. + [b]Note:[/b] Environment variable names are case-sensitive on all platforms except Windows. </description> </method> </methods> <members> <member name="delta_smoothing" type="bool" setter="set_delta_smoothing" getter="is_delta_smoothing_enabled" default="true"> - If [code]true[/code], the engine filters the time delta measured between each frame, and attempts to compensate for random variation. This will only operate on systems where V-Sync is active. + If [code]true[/code], the engine filters the time delta measured between each frame, and attempts to compensate for random variation. This only works on systems where V-Sync is active. + [b]Note:[/b] On start-up, this is the same as [member ProjectSettings.application/run/delta_smoothing]. </member> <member name="low_processor_usage_mode" type="bool" setter="set_low_processor_usage_mode" getter="is_in_low_processor_usage_mode" default="false"> If [code]true[/code], the engine optimizes for low processor usage by only refreshing the screen if needed. Can improve battery consumption on mobile. + [b]Note:[/b] On start-up, this is the same as [member ProjectSettings.application/run/low_processor_mode]. </member> <member name="low_processor_usage_mode_sleep_usec" type="int" setter="set_low_processor_usage_mode_sleep_usec" getter="get_low_processor_usage_mode_sleep_usec" default="6900"> - The amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU usage. + The amount of sleeping between frames when the low-processor usage mode is enabled, in microseconds. Higher values will result in lower CPU usage. See also [member low_processor_usage_mode]. + [b]Note:[/b] On start-up, this is the same as [member ProjectSettings.application/run/low_processor_mode_sleep_usec]. </member> </members> <constants> @@ -703,28 +760,28 @@ The Direct3D 12 rendering driver. </constant> <constant name="SYSTEM_DIR_DESKTOP" value="0" enum="SystemDir"> - Desktop directory path. + Refers to the Desktop directory path. </constant> <constant name="SYSTEM_DIR_DCIM" value="1" enum="SystemDir"> - DCIM (Digital Camera Images) directory path. + Refers to the DCIM (Digital Camera Images) directory path. </constant> <constant name="SYSTEM_DIR_DOCUMENTS" value="2" enum="SystemDir"> - Documents directory path. + Refers to the Documents directory path. </constant> <constant name="SYSTEM_DIR_DOWNLOADS" value="3" enum="SystemDir"> - Downloads directory path. + Refers to the Downloads directory path. </constant> <constant name="SYSTEM_DIR_MOVIES" value="4" enum="SystemDir"> - Movies directory path. + Refers to the Movies (or Videos) directory path. </constant> <constant name="SYSTEM_DIR_MUSIC" value="5" enum="SystemDir"> - Music directory path. + Refers to the Music directory path. </constant> <constant name="SYSTEM_DIR_PICTURES" value="6" enum="SystemDir"> - Pictures directory path. + Refers to the Pictures directory path. </constant> <constant name="SYSTEM_DIR_RINGTONES" value="7" enum="SystemDir"> - Ringtones directory path. + Refers to the Ringtones directory path. </constant> </constants> </class> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 2ffb02096d..e4f4d7682b 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -314,7 +314,7 @@ { if (property["name"].AsStringName() == PropertyName.Number && IsNumberEditable) { - var usage = property["usage"].As>PropertyUsageFlags<() | PropertyUsageFlags.ReadOnly; + var usage = property["usage"].As<PropertyUsageFlags>() | PropertyUsageFlags.ReadOnly; property["usage"] = (int)usage; } } diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index 516cc9f020..a934d32a6d 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -397,7 +397,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml index 4908a861b3..ad96ba2490 100644 --- a/doc/classes/PackedColorArray.xml +++ b/doc/classes/PackedColorArray.xml @@ -131,7 +131,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml index 56f9633533..6f1ecacca4 100644 --- a/doc/classes/PackedFloat32Array.xml +++ b/doc/classes/PackedFloat32Array.xml @@ -132,7 +132,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml index b08bdafc83..aef5ab90ac 100644 --- a/doc/classes/PackedFloat64Array.xml +++ b/doc/classes/PackedFloat64Array.xml @@ -132,7 +132,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml index c70cadc2fe..e6396e2a93 100644 --- a/doc/classes/PackedInt32Array.xml +++ b/doc/classes/PackedInt32Array.xml @@ -128,7 +128,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml index 339ab26a68..55024341c1 100644 --- a/doc/classes/PackedInt64Array.xml +++ b/doc/classes/PackedInt64Array.xml @@ -128,7 +128,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml index c2ae3cf3d3..f1b02272f3 100644 --- a/doc/classes/PackedStringArray.xml +++ b/doc/classes/PackedStringArray.xml @@ -134,7 +134,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml index 0e5bb12d02..c73fea9114 100644 --- a/doc/classes/PackedVector2Array.xml +++ b/doc/classes/PackedVector2Array.xml @@ -136,7 +136,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml index ce7ae4f396..89f258eaea 100644 --- a/doc/classes/PackedVector3Array.xml +++ b/doc/classes/PackedVector3Array.xml @@ -135,7 +135,7 @@ <return type="int" /> <param index="0" name="new_size" type="int" /> <description> - Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. + Sets the size of the array. If the array is grown, reserves elements at the end of the array. If the array is shrunk, truncates the array to the new size. Calling [method resize] once and assigning the new values is faster than adding new elements one by one. </description> </method> <method name="reverse"> diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml index d04d8eea52..2b47cd2deb 100644 --- a/doc/classes/PrimitiveMesh.xml +++ b/doc/classes/PrimitiveMesh.xml @@ -12,6 +12,7 @@ <method name="_create_mesh_array" qualifiers="virtual const"> <return type="Array" /> <description> + Override this method to customize how this primitive mesh should be generated. Should return an [Array] where each element is another Array of values required for the mesh (see the [enum Mesh.ArrayType] constants). </description> </method> <method name="get_mesh_arrays" qualifiers="const"> diff --git a/doc/classes/ProceduralSkyMaterial.xml b/doc/classes/ProceduralSkyMaterial.xml index 3fb9f9059c..1503bb2e78 100644 --- a/doc/classes/ProceduralSkyMaterial.xml +++ b/doc/classes/ProceduralSkyMaterial.xml @@ -6,7 +6,7 @@ <description> [ProceduralSkyMaterial] provides a way to create an effective background quickly by defining procedural parameters for the sun, the sky and the ground. The sky and ground are defined by a main color, a color at the horizon, and an easing curve to interpolate between them. Suns are described by a position in the sky, a color, and a max angle from the sun at which the easing curve ends. The max angle therefore defines the size of the sun in the sky. [ProceduralSkyMaterial] supports up to 4 suns, using the color, and energy, direction, and angular distance of the first four [DirectionalLight3D] nodes in the scene. This means that the suns are defined individually by the properties of their corresponding [DirectionalLight3D]s and globally by [member sun_angle_max] and [member sun_curve]. - [ProceduralSkyMaterial] uses a lightweight shader to draw the sky and is therefore suited for real time updates. This makes it a great option for a sky that is simple and computationally cheap, but unrealistic. If you need a more realistic procedural option, use [PhysicalSkyMaterial]. + [ProceduralSkyMaterial] uses a lightweight shader to draw the sky and is therefore suited for real-time updates. This makes it a great option for a sky that is simple and computationally cheap, but unrealistic. If you need a more realistic procedural option, use [PhysicalSkyMaterial]. </description> <tutorials> </tutorials> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index ab92916320..e0d41ab90a 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -406,7 +406,7 @@ [b]Note:[/b] Enabling TTS can cause addition idle CPU usage and interfere with the sleep mode, so consider disabling it if TTS is not used. </member> <member name="audio/video/video_delay_compensation_ms" type="int" setter="" getter="" default="0"> - Setting to hardcode audio delay when playing video. Best to leave this untouched unless you know what you are doing. + Setting to hardcode audio delay when playing video. Best to leave this unchanged unless you know what you are doing. </member> <member name="collada/use_ambient" type="bool" setter="" getter="" default="false"> If [code]true[/code], ambient lights will be imported from COLLADA models as [DirectionalLight3D]. If [code]false[/code], ambient lights will be ignored. @@ -810,7 +810,9 @@ Main window can't be focused. No-focus window will ignore all input, except mouse clicks. </member> <member name="display/window/size/resizable" type="bool" setter="" getter="" default="true"> - Allows the window to be resizable by default. + If [code]true[/code], allows the window to be resizable by default. + [b]Note:[/b] This property is only read when the project starts. To change whether the window is resizable at runtime, set [member Window.unresizable] instead on the root Window, which can be retrieved using [code]get_viewport().get_window()[/code]. [member Window.unresizable] takes the opposite value of this setting. + [b]Note:[/b] Certain window managers can be configured to ignore the non-resizable status of a window. Do not rely on this setting as a guarantee that the window will [i]never[/i] be resizable. [b]Note:[/b] This setting is ignored on iOS. </member> <member name="display/window/size/transparent" type="bool" setter="" getter="" default="false"> @@ -1108,7 +1110,7 @@ [b]Note:[/b] Default [code]ui_*[/code] actions cannot be removed as they are necessary for the internal logic of several [Control]s. The events assigned to the action can however be modified. </member> <member name="input/ui_swap_input_direction" type="Dictionary" setter="" getter=""> - Default [InputEventAction] to swap input direction, i.e. change between left-to-right to right-to-left modes. Affects text-editting controls ([LineEdit], [TextEdit]). + Default [InputEventAction] to swap input direction, i.e. change between left-to-right to right-to-left modes. Affects text-editing controls ([LineEdit], [TextEdit]). </member> <member name="input/ui_text_add_selection_for_next_occurrence" type="Dictionary" setter="" getter=""> If a selection is currently active with the last caret in text fields, searches for the next occurrence of the selection, adds a caret and selects the next occurrence. @@ -1219,15 +1221,15 @@ [b]Note:[/b] Default [code]ui_*[/code] actions cannot be removed as they are necessary for the internal logic of several [Control]s. The events assigned to the action can however be modified. </member> <member name="input/ui_text_completion_accept" type="Dictionary" setter="" getter=""> - Default [InputEventAction] to accept an autocompetion hint. + Default [InputEventAction] to accept an autocompletion hint. [b]Note:[/b] Default [code]ui_*[/code] actions cannot be removed as they are necessary for the internal logic of several [Control]s. The events assigned to the action can however be modified. </member> <member name="input/ui_text_completion_query" type="Dictionary" setter="" getter=""> - Default [InputEventAction] to request autocompetion. + Default [InputEventAction] to request autocompletion. [b]Note:[/b] Default [code]ui_*[/code] actions cannot be removed as they are necessary for the internal logic of several [Control]s. The events assigned to the action can however be modified. </member> <member name="input/ui_text_completion_replace" type="Dictionary" setter="" getter=""> - Default [InputEventAction] to accept an autocompetion hint, replacing existing text. + Default [InputEventAction] to accept an autocompletion hint, replacing existing text. [b]Note:[/b] Default [code]ui_*[/code] actions cannot be removed as they are necessary for the internal logic of several [Control]s. The events assigned to the action can however be modified. </member> <member name="input/ui_text_dedent" type="Dictionary" setter="" getter=""> @@ -1993,9 +1995,6 @@ <member name="memory/limits/message_queue/max_size_mb" type="int" setter="" getter="" default="32"> Godot uses a message queue to defer some function calls. If you run out of space on it (you will see an error), you can increase the size here. </member> - <member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter="" default="60"> - This is used by servers when used in multi-threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number. - </member> <member name="navigation/2d/default_cell_size" type="float" setter="" getter="" default="1.0"> Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size]. </member> @@ -2211,7 +2210,7 @@ [b]Note:[/b] This property is only read when the project starts. To change the maximum number of simulated physics steps per frame at runtime, set [member Engine.max_physics_steps_per_frame] instead. </member> <member name="physics/common/physics_jitter_fix" type="float" setter="" getter="" default="0.5"> - Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended. + Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be good enough for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended. [b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics/common/physics_jitter_fix] to [code]0[/code]. [b]Note:[/b] This property is only read when the project starts. To change the physics jitter fix at runtime, set [member Engine.physics_jitter_fix] instead. </member> @@ -2537,8 +2536,6 @@ Decreasing this value may improve GPU performance on certain setups, even if the maximum number of clustered elements is never reached in the project. [b]Note:[/b] This setting is only effective when using the Forward+ rendering method, not Mobile and Compatibility. </member> - <member name="rendering/limits/forward_renderer/threaded_render_minimum_instances" type="int" setter="" getter="" default="500"> - </member> <member name="rendering/limits/global_shader_variables/buffer_size" type="int" setter="" getter="" default="65536"> </member> <member name="rendering/limits/opengl/max_lights_per_object" type="int" setter="" getter="" default="8"> @@ -2554,6 +2551,7 @@ [b]Note:[/b] This setting is only effective when using the Compatibility rendering method, not Forward+ and Mobile. </member> <member name="rendering/limits/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000"> + The minimum number of instances that must be present in a scene to enable culling computations on multiple threads. If a scene has fewer instances than this number, culling is done on a single thread. </member> <member name="rendering/limits/spatial_indexer/update_iterations_per_frame" type="int" setter="" getter="" default="10"> </member> @@ -2616,6 +2614,9 @@ <member name="rendering/renderer/rendering_method.web" type="String" setter="" getter="" default=""gl_compatibility""> Override for [member rendering/renderer/rendering_method] on web. </member> + <member name="rendering/rendering_device/d3d12/agility_sdk_version" type="int" setter="" getter="" default="610"> + Version code of the Direct3D 12 Agility SDK to use ([code]D3D12SDKVersion[/code]). + </member> <member name="rendering/rendering_device/d3d12/max_misc_descriptors_per_frame" type="int" setter="" getter="" default="512"> The number of entries in the miscellaneous descriptors heap the Direct3D 12 rendering driver uses each frame, used for various operations like clearing a texture. Depending on the complexity of scenes, this value may be lowered or may need to be raised. @@ -2768,8 +2769,6 @@ <member name="threading/worker_pool/max_threads" type="int" setter="" getter="" default="-1"> Maximum number of threads to be used by [WorkerThreadPool]. Value of [code]-1[/code] means no limit. </member> - <member name="threading/worker_pool/use_system_threads_for_low_priority_tasks" type="bool" setter="" getter="" default="true"> - </member> <member name="xr/openxr/default_action_map" type="String" setter="" getter="" default=""res://openxr_action_map.tres""> Action map configuration to load by default. </member> diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml index 74dfae77fc..61bc4f4720 100644 --- a/doc/classes/Quaternion.xml +++ b/doc/classes/Quaternion.xml @@ -79,6 +79,7 @@ <method name="exp" qualifiers="const"> <return type="Quaternion" /> <description> + Returns the exponential of this quaternion. The rotation axis of the result is the normalized rotation axis of this quaternion, the angle of the result is the length of the vector part of this quaternion. </description> </method> <method name="from_euler" qualifiers="static"> @@ -91,11 +92,14 @@ <method name="get_angle" qualifiers="const"> <return type="float" /> <description> + Returns the angle of the rotation represented by this quaternion. + [b]Note:[/b] The quaternion must be normalized. </description> </method> <method name="get_axis" qualifiers="const"> <return type="Vector3" /> <description> + Returns the rotation axis of the rotation represented by this quaternion. </description> </method> <method name="get_euler" qualifiers="const"> @@ -145,6 +149,7 @@ <method name="log" qualifiers="const"> <return type="Quaternion" /> <description> + Returns the logarithm of this quaternion. The vector part of the result is the rotation axis of this quaternion multiplied by its rotation angle, the real part of the result is zero. </description> </method> <method name="normalized" qualifiers="const"> diff --git a/doc/classes/RDUniform.xml b/doc/classes/RDUniform.xml index 7aab8b2810..77aaf0aae7 100644 --- a/doc/classes/RDUniform.xml +++ b/doc/classes/RDUniform.xml @@ -13,16 +13,19 @@ <return type="void" /> <param index="0" name="id" type="RID" /> <description> + Binds the given id to the uniform. The data associated with the id is then used when the uniform is passed to a shader. </description> </method> <method name="clear_ids"> <return type="void" /> <description> + Unbinds all ids currently bound to the uniform. </description> </method> <method name="get_ids" qualifiers="const"> <return type="RID[]" /> <description> + Returns an array of all ids currently bound to the uniform. </description> </method> </methods> diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml index 54f18a1ab4..2b6e6af596 100644 --- a/doc/classes/RandomNumberGenerator.xml +++ b/doc/classes/RandomNumberGenerator.xml @@ -6,7 +6,7 @@ <description> RandomNumberGenerator is a class for generating pseudo-random numbers. It currently uses [url=https://www.pcg-random.org/]PCG32[/url]. [b]Note:[/b] The underlying algorithm is an implementation detail and should not be depended upon. - To generate a random float number (within a given range) based on a time-dependant seed: + To generate a random float number (within a given range) based on a time-dependent seed: [codeblock] var rng = RandomNumberGenerator.new() func _ready(): diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index a841453ba0..54f3281e17 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -14,12 +14,12 @@ <link title="Using compute shaders">$DOCS_URL/tutorials/shaders/compute_shaders.html</link> </tutorials> <methods> - <method name="barrier"> + <method name="barrier" is_deprecated="true"> <return type="void" /> <param index="0" name="from" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <param index="1" name="to" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> - Puts a memory barrier in place. This is used for synchronization to avoid data races. See also [method full_barrier], which may be useful for debugging. + [i]Deprecated.[/i] Barriers are automatically inserted by RenderingDevice. </description> </method> <method name="buffer_clear"> @@ -27,9 +27,8 @@ <param index="0" name="buffer" type="RID" /> <param index="1" name="offset" type="int" /> <param index="2" name="size_bytes" type="int" /> - <param index="3" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> - Clears the contents of the [param buffer], clearing [param size_bytes] bytes, starting at [param offset]. Always raises a memory barrier. + Clears the contents of the [param buffer], clearing [param size_bytes] bytes, starting at [param offset]. Prints an error if: - the size isn't a multiple of four - the region specified by [param offset] + [param size_bytes] exceeds the buffer @@ -37,6 +36,21 @@ - a compute list is currently active (created by [method compute_list_begin]) </description> </method> + <method name="buffer_copy"> + <return type="int" enum="Error" /> + <param index="0" name="src_buffer" type="RID" /> + <param index="1" name="dst_buffer" type="RID" /> + <param index="2" name="src_offset" type="int" /> + <param index="3" name="dst_offset" type="int" /> + <param index="4" name="size" type="int" /> + <description> + Copies [param size] bytes from the [param src_buffer] at [param src_offset] into [param dst_buffer] at [param dst_offset]. + Prints an error if: + - [param size] exceeds the size of either [param src_buffer] or [param dst_buffer] at their corresponding offsets + - a draw list is currently active (created by [method draw_list_begin]) + - a compute list is currently active (created by [method compute_list_begin]) + </description> + </method> <method name="buffer_get_data"> <return type="PackedByteArray" /> <param index="0" name="buffer" type="RID" /> @@ -52,9 +66,8 @@ <param index="1" name="offset" type="int" /> <param index="2" name="size_bytes" type="int" /> <param index="3" name="data" type="PackedByteArray" /> - <param index="4" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> - Updates a region of [param size_bytes] bytes, starting at [param offset], in the buffer, with the specified [param data]. Raises a memory barrier except when [param post_barrier] is set to [constant BARRIER_MASK_NO_BARRIER]. + Updates a region of [param size_bytes] bytes, starting at [param offset], in the buffer, with the specified [param data]. Prints an error if: - the region specified by [param offset] + [param size_bytes] exceeds the buffer - a draw list is currently active (created by [method draw_list_begin]) @@ -77,10 +90,9 @@ </method> <method name="compute_list_begin"> <return type="int" /> - <param index="0" name="allow_draw_overlap" type="bool" default="false" /> <description> Starts a list of compute commands created with the [code]compute_*[/code] methods. The returned value should be passed to other [code]compute_list_*[/code] functions. - If [param allow_draw_overlap] is [code]true[/code], you may have one draw list running at the same time as one compute list. Multiple compute lists cannot be created at the same time; you must finish the previous compute list first using [method compute_list_end]. + Multiple compute lists cannot be created at the same time; you must finish the previous compute list first using [method compute_list_end]. A simple compute operation might look like this (code is not a complete example): [codeblock] var rd = RenderingDevice.new() @@ -128,7 +140,6 @@ </method> <method name="compute_list_end"> <return type="void" /> - <param index="0" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> Finishes a list of compute commands created with the [code]compute_*[/code] methods. </description> @@ -170,7 +181,7 @@ <param index="1" name="color" type="Color" /> <description> Create a command buffer debug label region that can be displayed in third-party tools such as [url=https://renderdoc.org/]RenderDoc[/url]. All regions must be ended with a [method draw_command_end_label] call. When viewed from the linear series of submissions to a single queue, calls to [method draw_command_begin_label] and [method draw_command_end_label] must be matched and balanced. - The [code]VK_EXT_DEBUG_UTILS_EXTENSION_NAME[/code] Vulkan extension must be available and enabled for command buffer debug label region to work. See also [method draw_command_insert_label] and [method draw_command_end_label]. + The [code]VK_EXT_DEBUG_UTILS_EXTENSION_NAME[/code] Vulkan extension must be available and enabled for command buffer debug label region to work. See also [method draw_command_end_label]. </description> </method> <method name="draw_command_end_label"> @@ -179,12 +190,12 @@ Ends the command buffer debug label region started by a [method draw_command_begin_label] call. </description> </method> - <method name="draw_command_insert_label"> + <method name="draw_command_insert_label" is_deprecated="true"> <return type="void" /> <param index="0" name="name" type="String" /> <param index="1" name="color" type="Color" /> <description> - Inserts a command buffer debug label region in the current command buffer. Unlike [method draw_command_begin_label], this region should not be ended with a [method draw_command_end_label] call. + [i]Deprecated.[/i] Inserting labels no longer applies due to command reordering. </description> </method> <method name="draw_list_begin"> @@ -198,14 +209,13 @@ <param index="6" name="clear_depth" type="float" default="1.0" /> <param index="7" name="clear_stencil" type="int" default="0" /> <param index="8" name="region" type="Rect2" default="Rect2(0, 0, 0, 0)" /> - <param index="9" name="storage_textures" type="RID[]" default="[]" /> <description> Starts a list of raster drawing commands created with the [code]draw_*[/code] methods. The returned value should be passed to other [code]draw_list_*[/code] functions. Multiple draw lists cannot be created at the same time; you must finish the previous draw list first using [method draw_list_end]. A simple drawing operation might look like this (code is not a complete example): [codeblock] var rd = RenderingDevice.new() - var clear_colors = PackedColorArray([Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0)] + var clear_colors = PackedColorArray([Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0)]) var draw_list = rd.draw_list_begin(framebuffers[i], RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_READ, RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_DISCARD, clear_colors) # Draw opaque. @@ -232,7 +242,7 @@ [b]Note:[/b] Cannot be used with local RenderingDevices, as these don't have a screen. If called on a local RenderingDevice, [method draw_list_begin_for_screen] returns [constant INVALID_ID]. </description> </method> - <method name="draw_list_begin_split"> + <method name="draw_list_begin_split" is_deprecated="true"> <return type="PackedInt64Array" /> <param index="0" name="framebuffer" type="RID" /> <param index="1" name="splits" type="int" /> @@ -246,7 +256,7 @@ <param index="9" name="region" type="Rect2" default="Rect2(0, 0, 0, 0)" /> <param index="10" name="storage_textures" type="RID[]" default="[]" /> <description> - Variant of [method draw_list_begin] with support for multiple splits. The [param splits] parameter determines how many splits are created. + [i]Deprecated.[/i] Split draw lists are used automatically by RenderingDevice. </description> </method> <method name="draw_list_bind_index_array"> @@ -310,7 +320,6 @@ </method> <method name="draw_list_end"> <return type="void" /> - <param index="0" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> Finishes a list of raster drawing commands created with the [code]draw_*[/code] methods. </description> @@ -335,14 +344,14 @@ <method name="draw_list_switch_to_next_pass"> <return type="int" /> <description> - Switches to the next draw pass and returns the split's ID. Equivalent to [method draw_list_switch_to_next_pass_split] with [code]splits[/code] set to [code]1[/code]. + Switches to the next draw pass. </description> </method> - <method name="draw_list_switch_to_next_pass_split"> + <method name="draw_list_switch_to_next_pass_split" is_deprecated="true"> <return type="PackedInt64Array" /> <param index="0" name="splits" type="int" /> <description> - Switches to the next draw pass, with the number of splits allocated specified in [param splits]. The return value is an array containing the ID of each split. For single-split usage, see [method draw_list_switch_to_next_pass]. + [i]Deprecated.[/i] Split draw lists are used automatically by RenderingDevice. </description> </method> <method name="framebuffer_create"> @@ -430,10 +439,10 @@ Tries to free an object in the RenderingDevice. To avoid memory leaks, this should be called after using an object as memory management does not occur automatically when using RenderingDevice directly. </description> </method> - <method name="full_barrier"> + <method name="full_barrier" is_deprecated="true"> <return type="void" /> <description> - Puts a [i]full[/i] memory barrier in place. This is a memory [method barrier] with all flags enabled. [method full_barrier] it should only be used for debugging as it can severely impact performance. + [i]Deprecated.[/i] Barriers are automatically inserted by RenderingDevice. </description> </method> <method name="get_captured_timestamp_cpu_time" qualifiers="const"> @@ -704,7 +713,6 @@ <param index="3" name="mipmap_count" type="int" /> <param index="4" name="base_layer" type="int" /> <param index="5" name="layer_count" type="int" /> - <param index="6" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> Clears the specified [param texture] by replacing all of its pixels with the specified [param color]. [param base_mipmap] and [param mipmap_count] determine which mipmaps of the texture are affected by this clear operation, while [param base_layer] and [param layer_count] determine which layers of a 3D texture (or texture array) are affected by this clear operation. For 2D textures (which only have one layer by design), [param base_layer] must be [code]0[/code] and [param layer_count] must be [code]1[/code]. [b]Note:[/b] [param texture] can't be cleared while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to [constant FINAL_ACTION_CONTINUE]) to clear this texture. @@ -721,7 +729,6 @@ <param index="6" name="dst_mipmap" type="int" /> <param index="7" name="src_layer" type="int" /> <param index="8" name="dst_layer" type="int" /> - <param index="9" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> Copies the [param from_texture] to [param to_texture] with the specified [param from_pos], [param to_pos] and [param size] coordinates. The Z axis of the [param from_pos], [param to_pos] and [param size] must be [code]0[/code] for 2-dimensional textures. Source and destination mipmaps/layers must also be specified, with these parameters being [code]0[/code] for textures without mipmaps or single-layer textures. Returns [constant @GlobalScope.OK] if the texture copy was successful or [constant @GlobalScope.ERR_INVALID_PARAMETER] otherwise. [b]Note:[/b] [param from_texture] texture can't be copied while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to [constant FINAL_ACTION_CONTINUE]) to copy this texture. @@ -831,7 +838,6 @@ <return type="int" enum="Error" /> <param index="0" name="from_texture" type="RID" /> <param index="1" name="to_texture" type="RID" /> - <param index="2" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> Resolves the [param from_texture] texture onto [param to_texture] with multisample antialiasing enabled. This must be used when rendering a framebuffer for MSAA to work. Returns [constant @GlobalScope.OK] if successful, [constant @GlobalScope.ERR_INVALID_PARAMETER] otherwise. [b]Note:[/b] [param from_texture] and [param to_texture] textures must have the same dimension, format and type (color or depth). @@ -848,7 +854,6 @@ <param index="0" name="texture" type="RID" /> <param index="1" name="layer" type="int" /> <param index="2" name="data" type="PackedByteArray" /> - <param index="3" name="post_barrier" type="int" enum="RenderingDevice.BarrierMask" is_bitfield="true" default="32767" /> <description> Updates texture data with new data, replacing the previous data in place. The updated texture data must have the same dimensions and format. For 2D textures (which only have one layer), [param layer] must be [code]0[/code]. Returns [constant @GlobalScope.OK] if the update was successful, [constant @GlobalScope.ERR_INVALID_PARAMETER] otherwise. [b]Note:[/b] Updating textures is forbidden during creation of a draw or compute list. @@ -2150,39 +2155,48 @@ </constant> <constant name="DYNAMIC_STATE_STENCIL_REFERENCE" value="64" enum="PipelineDynamicStateFlags" is_bitfield="true"> </constant> - <constant name="INITIAL_ACTION_CLEAR" value="0" enum="InitialAction"> - Start rendering and clear the whole framebuffer. + <constant name="INITIAL_ACTION_LOAD" value="0" enum="InitialAction"> + Load the previous contents of the framebuffer. </constant> - <constant name="INITIAL_ACTION_CLEAR_REGION" value="1" enum="InitialAction"> - Start rendering and clear the framebuffer in the specified region. + <constant name="INITIAL_ACTION_CLEAR" value="1" enum="InitialAction"> + Clear the whole framebuffer or its specified region. </constant> - <constant name="INITIAL_ACTION_CLEAR_REGION_CONTINUE" value="2" enum="InitialAction"> - Continue rendering and clear the framebuffer in the specified region. Framebuffer must have been left in [constant FINAL_ACTION_CONTINUE] state as the final action previously. + <constant name="INITIAL_ACTION_DISCARD" value="2" enum="InitialAction"> + Ignore the previous contents of the framebuffer. This is the fastest option if you'll overwrite all of the pixels and don't need to read any of them. </constant> - <constant name="INITIAL_ACTION_KEEP" value="3" enum="InitialAction"> - Start rendering, but keep attached color texture contents. If the framebuffer was previously used to read in a shader, this will automatically insert a layout transition. + <constant name="INITIAL_ACTION_MAX" value="3" enum="InitialAction"> + Represents the size of the [enum InitialAction] enum. </constant> - <constant name="INITIAL_ACTION_DROP" value="4" enum="InitialAction"> - Start rendering, ignore what is there; write above it. In general, this is the fastest option when you will be writing every single pixel and you don't need a clear color. + <constant name="INITIAL_ACTION_CLEAR_REGION" value="1" enum="InitialAction" is_deprecated="true"> + [i]Deprecated.[/i] Use [constant INITIAL_ACTION_CLEAR] instead. </constant> - <constant name="INITIAL_ACTION_CONTINUE" value="5" enum="InitialAction"> - Continue rendering. Framebuffer must have been left in [constant FINAL_ACTION_CONTINUE] state as the final action previously. + <constant name="INITIAL_ACTION_CLEAR_REGION_CONTINUE" value="1" enum="InitialAction" is_deprecated="true"> + [i]Deprecated.[/i] Use [constant INITIAL_ACTION_LOAD] instead. </constant> - <constant name="INITIAL_ACTION_MAX" value="6" enum="InitialAction"> - Represents the size of the [enum InitialAction] enum. + <constant name="INITIAL_ACTION_KEEP" value="0" enum="InitialAction" is_deprecated="true"> + [i]Deprecated.[/i] Use [constant INITIAL_ACTION_LOAD] instead. </constant> - <constant name="FINAL_ACTION_READ" value="0" enum="FinalAction"> - Store the texture for reading and make it read-only if it has the [constant TEXTURE_USAGE_SAMPLING_BIT] bit (only applies to color, depth and stencil attachments). + <constant name="INITIAL_ACTION_DROP" value="2" enum="InitialAction" is_deprecated="true"> + [i]Deprecated.[/i] Use [constant INITIAL_ACTION_DISCARD] instead. </constant> - <constant name="FINAL_ACTION_DISCARD" value="1" enum="FinalAction"> - Discard the texture data and make it read-only if it has the [constant TEXTURE_USAGE_SAMPLING_BIT] bit (only applies to color, depth and stencil attachments). + <constant name="INITIAL_ACTION_CONTINUE" value="0" enum="InitialAction" is_deprecated="true"> + [i]Deprecated.[/i] Use [constant INITIAL_ACTION_LOAD] instead. </constant> - <constant name="FINAL_ACTION_CONTINUE" value="2" enum="FinalAction"> - Store the texture and continue for further processing. Similar to [constant FINAL_ACTION_READ], but does not make the texture read-only if it has the [constant TEXTURE_USAGE_SAMPLING_BIT] bit. + <constant name="FINAL_ACTION_STORE" value="0" enum="FinalAction"> + Store the result of the draw list in the framebuffer. This is generally what you want to do. </constant> - <constant name="FINAL_ACTION_MAX" value="3" enum="FinalAction"> + <constant name="FINAL_ACTION_DISCARD" value="1" enum="FinalAction"> + Discard the contents of the framebuffer. This is the fastest option if you don't need to use the results of the draw list. + </constant> + <constant name="FINAL_ACTION_MAX" value="2" enum="FinalAction"> Represents the size of the [enum FinalAction] enum. </constant> + <constant name="FINAL_ACTION_READ" value="0" enum="FinalAction" is_deprecated="true"> + [i]Deprecated.[/i] Use [constant FINAL_ACTION_STORE] instead. + </constant> + <constant name="FINAL_ACTION_CONTINUE" value="0" enum="FinalAction" is_deprecated="true"> + [i]Deprecated.[/i] Use [constant FINAL_ACTION_STORE] instead. + </constant> <constant name="SHADER_STAGE_VERTEX" value="0" enum="ShaderStage"> Vertex shader stage. This can be used to manipulate vertices from a shader (but not create new vertices). </constant> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index a3ec4d25f1..42a164bbeb 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1556,11 +1556,11 @@ Returns [code]true[/code] if changes have been made to the RenderingServer's data. [method force_draw] is usually called if this happens. </description> </method> - <method name="has_feature" qualifiers="const"> + <method name="has_feature" qualifiers="const" is_deprecated="true"> <return type="bool" /> <param index="0" name="feature" type="int" enum="RenderingServer.Features" /> <description> - Not yet implemented. Always returns [code]false[/code]. + [i]Deprecated.[/i] This method has not been used since Godot 3.0. Always returns false. </description> </method> <method name="has_os_feature" qualifiers="const"> @@ -5332,11 +5332,11 @@ <constant name="RENDERING_INFO_VIDEO_MEM_USED" value="5" enum="RenderingInfo"> Video memory used (in bytes). When using the Forward+ or mobile rendering backends, this is always greater than the sum of [constant RENDERING_INFO_TEXTURE_MEM_USED] and [constant RENDERING_INFO_BUFFER_MEM_USED], since there is miscellaneous data not accounted for by those two metrics. When using the GL Compatibility backend, this is equal to the sum of [constant RENDERING_INFO_TEXTURE_MEM_USED] and [constant RENDERING_INFO_BUFFER_MEM_USED]. </constant> - <constant name="FEATURE_SHADERS" value="0" enum="Features"> - Hardware supports shaders. This enum is currently unused in Godot 3.x. + <constant name="FEATURE_SHADERS" value="0" enum="Features" is_deprecated="true"> + [i]Deprecated.[/i] This constant has not been used since Godot 3.0. </constant> - <constant name="FEATURE_MULTITHREADED" value="1" enum="Features"> - Hardware supports multithreading. This enum is currently unused in Godot 3.x. + <constant name="FEATURE_MULTITHREADED" value="1" enum="Features" is_deprecated="true"> + [i]Deprecated.[/i] This constant has not been used since Godot 3.0. </constant> </constants> </class> diff --git a/doc/classes/ResourceImporterOBJ.xml b/doc/classes/ResourceImporterOBJ.xml index fa964e5016..55043a311c 100644 --- a/doc/classes/ResourceImporterOBJ.xml +++ b/doc/classes/ResourceImporterOBJ.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ResourceImporterOBJ" inherits="ResourceImporter" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Imports an OBJ 3D model as a standalone [Mesh] or scene. + Imports an OBJ 3D model as an independent [Mesh] or scene. </brief_description> <description> Unlike [ResourceImporterScene], [ResourceImporterOBJ] will import a single [Mesh] resource by default instead of importing a [PackedScene]. This makes it easier to use the [Mesh] resource in nodes that expect direct [Mesh] resources, such as [GridMap], [GPUParticles3D] or [CPUParticles3D]. Note that it is still possible to save mesh resources from 3D scenes using the [b]Advanced Import Settings[/b] dialog, regardless of the source format. diff --git a/doc/classes/ResourceImporterScene.xml b/doc/classes/ResourceImporterScene.xml index 1769da9f24..6a88adf421 100644 --- a/doc/classes/ResourceImporterScene.xml +++ b/doc/classes/ResourceImporterScene.xml @@ -4,7 +4,7 @@ Imports a glTF, FBX, Collada or Blender 3D scene. </brief_description> <description> - See also [ResourceImporterOBJ], which is used for OBJ models that can be imported as a standalone [Mesh] or a scene. + See also [ResourceImporterOBJ], which is used for OBJ models that can be imported as an independent [Mesh] or a scene. Additional options (such as extracting individual meshes or materials to files) are available in the [b]Advanced Import Settings[/b] dialog. This dialog can be accessed by double-clicking a 3D scene in the FileSystem dock or by selecting a 3D scene in the FileSystem dock, going to the Import dock and choosing [b]Advanced[/b]. [b]Note:[/b] [ResourceImporterScene] is [i]not[/i] used for [PackedScene]s, such as [code].tscn[/code] and [code].scn[/code] files. </description> diff --git a/doc/classes/ScriptLanguageExtension.xml b/doc/classes/ScriptLanguageExtension.xml index b4e2f40612..c5248f4888 100644 --- a/doc/classes/ScriptLanguageExtension.xml +++ b/doc/classes/ScriptLanguageExtension.xml @@ -114,9 +114,10 @@ </method> <method name="_find_function" qualifiers="virtual const"> <return type="int" /> - <param index="0" name="class_name" type="String" /> - <param index="1" name="function_name" type="String" /> + <param index="0" name="function" type="String" /> + <param index="1" name="code" type="String" /> <description> + Returns the line where the function is defined in the code, or [code]-1[/code] if the function is not present. </description> </method> <method name="_finish" qualifiers="virtual"> diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml index 0471b8c275..492b6164bf 100644 --- a/doc/classes/Slider.xml +++ b/doc/classes/Slider.xml @@ -33,7 +33,7 @@ </signal> <signal name="drag_started"> <description> - Emitted when dragging is started. + Emitted when dragging is started. This is emitted before the corresponding [signal Range.value_changed] signal. </description> </signal> </signals> diff --git a/doc/classes/SoftBody3D.xml b/doc/classes/SoftBody3D.xml index b5202bd4e3..a4d80a7c3e 100644 --- a/doc/classes/SoftBody3D.xml +++ b/doc/classes/SoftBody3D.xml @@ -41,6 +41,7 @@ <method name="get_physics_rid" qualifiers="const"> <return type="RID" /> <description> + Returns the internal [RID] used by the [PhysicsServer3D] for this body. </description> </method> <method name="get_point_transform"> @@ -100,11 +101,14 @@ [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01"> + The body's damping coefficient. Higher values will slow down the body more noticeably when forces are applied. </member> <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftBody3D.DisableMode" default="0"> Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. </member> <member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0"> + The body's drag coefficient. Higher values increase this body's air resistance. + [b]Note:[/b] This value is currently unused by Godot's default physics implementation. </member> <member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5"> Higher values will result in a stiffer body, while lower values will increase the body's ability to bend. The value can be between [code]0.0[/code] and [code]1.0[/code] (inclusive). @@ -113,6 +117,7 @@ [NodePath] to a [CollisionObject3D] this SoftBody3D should avoid clipping. </member> <member name="pressure_coefficient" type="float" setter="set_pressure_coefficient" getter="get_pressure_coefficient" default="0.0"> + The pressure coefficient of this soft body. Simulate pressure build-up from inside this body. Higher values increase the strength of this effect. </member> <member name="ray_pickable" type="bool" setter="set_ray_pickable" getter="is_ray_pickable" default="true"> If [code]true[/code], the [SoftBody3D] will respond to [RayCast3D]s. diff --git a/doc/classes/String.xml b/doc/classes/String.xml index af4297afae..e1b60b1656 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -96,13 +96,14 @@ [gdscript] "move_local_x".capitalize() # Returns "Move Local X" "sceneFile_path".capitalize() # Returns "Scene File Path" + "2D, FPS, PNG".capitalize() # Returns "2d, Fps, Png" [/gdscript] [csharp] "move_local_x".Capitalize(); // Returns "Move Local X" "sceneFile_path".Capitalize(); // Returns "Scene File Path" + "2D, FPS, PNG".Capitalize(); // Returns "2d, Fps, Png" [/csharp] [/codeblocks] - [b]Note:[/b] This method not the same as the default appearance of properties in the Inspector dock, as it does not capitalize acronyms ([code]"2D"[/code], [code]"FPS"[/code], [code]"PNG"[/code], etc.) as you may expect. </description> </method> <method name="casecmp_to" qualifiers="const"> @@ -318,7 +319,7 @@ <return type="int" /> <description> Returns the 32-bit hash value representing the string's contents. - [b]Note:[/b] Strings with equal hash values are [i]not[/i] guaranteed to be the same, as a result of hash collisions. On the countrary, strings with different hash values are guaranteed to be different. + [b]Note:[/b] Strings with equal hash values are [i]not[/i] guaranteed to be the same, as a result of hash collisions. On the contrary, strings with different hash values are guaranteed to be different. </description> </method> <method name="hex_decode" qualifiers="const"> @@ -949,7 +950,7 @@ <method name="to_lower" qualifiers="const"> <return type="String" /> <description> - Returns the string converted to lowercase. + Returns the string converted to [code]lowercase[/code]. </description> </method> <method name="to_pascal_case" qualifiers="const"> @@ -962,12 +963,25 @@ <return type="String" /> <description> Returns the string converted to [code]snake_case[/code]. + [b]Note:[/b] Numbers followed by a [i]single[/i] letter are not separated in the conversion to keep some words (such as "2D") together. + [codeblocks] + [gdscript] + "Node2D".to_snake_case() # Returns "node_2d" + "2nd place".to_snake_case() # Returns "2_nd_place" + "Texture3DAssetFolder".to_snake_case() # Returns "texture_3d_asset_folder" + [/gdscript] + [csharp] + "Node2D".ToSnakeCase(); // Returns "node_2d" + "2nd place".ToSnakeCase(); // Returns "2_nd_place" + "Texture3DAssetFolder".ToSnakeCase(); // Returns "texture_3d_asset_folder" + [/csharp] + [/codeblocks] </description> </method> <method name="to_upper" qualifiers="const"> <return type="String" /> <description> - Returns the string converted to uppercase. + Returns the string converted to [code]UPPERCASE[/code]. </description> </method> <method name="to_utf8_buffer" qualifiers="const"> diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml index 1c5032be9b..844782eb9a 100644 --- a/doc/classes/StringName.xml +++ b/doc/classes/StringName.xml @@ -8,6 +8,7 @@ You will usually just pass a [String] to methods expecting a [StringName] and it will be automatically converted, but you may occasionally want to construct a [StringName] ahead of time with the [StringName] constructor or, in GDScript, the literal syntax [code]&"example"[/code]. See also [NodePath], which is a similar concept specifically designed to store pre-parsed scene tree paths. All of [String]'s methods are available in this class too. They convert the [StringName] into a string, and they also return a string. This is highly inefficient and should only be used if the string is desired. + [b]Note:[/b] In C#, an explicit conversion to [code]System.String[/code] is required to use the methods listed on this page. Use the [code]ToString()[/code] method to cast a [StringName] to a string, and then use the equivalent methods in [code]System.String[/code] or [code]StringExtensions[/code]. [b]Note:[/b] In a boolean context, a [StringName] will evaluate to [code]false[/code] if it is empty ([code]StringName("")[/code]). Otherwise, a [StringName] will always evaluate to [code]true[/code]. The [code]not[/code] operator cannot be used. Instead, [method is_empty] should be used to check for empty [StringName]s. </description> <tutorials> @@ -90,13 +91,14 @@ [gdscript] "move_local_x".capitalize() # Returns "Move Local X" "sceneFile_path".capitalize() # Returns "Scene File Path" + "2D, FPS, PNG".capitalize() # Returns "2d, Fps, Png" [/gdscript] [csharp] "move_local_x".Capitalize(); // Returns "Move Local X" "sceneFile_path".Capitalize(); // Returns "Scene File Path" + "2D, FPS, PNG".Capitalize(); // Returns "2d, Fps, Png" [/csharp] [/codeblocks] - [b]Note:[/b] This method not the same as the default appearance of properties in the Inspector dock, as it does not capitalize acronyms ([code]"2D"[/code], [code]"FPS"[/code], [code]"PNG"[/code], etc.) as you may expect. </description> </method> <method name="casecmp_to" qualifiers="const"> @@ -301,7 +303,7 @@ <return type="int" /> <description> Returns the 32-bit hash value representing the string's contents. - [b]Note:[/b] Strings with equal hash values are [i]not[/i] guaranteed to be the same, as a result of hash collisions. On the countrary, strings with different hash values are guaranteed to be different. + [b]Note:[/b] Strings with equal hash values are [i]not[/i] guaranteed to be the same, as a result of hash collisions. On the contrary, strings with different hash values are guaranteed to be different. </description> </method> <method name="hex_decode" qualifiers="const"> @@ -856,7 +858,7 @@ <method name="to_lower" qualifiers="const"> <return type="String" /> <description> - Returns the string converted to lowercase. + Returns the string converted to [code]lowercase[/code]. </description> </method> <method name="to_pascal_case" qualifiers="const"> @@ -869,12 +871,25 @@ <return type="String" /> <description> Returns the string converted to [code]snake_case[/code]. + [b]Note:[/b] Numbers followed by a [i]single[/i] letter are not separated in the conversion to keep some words (such as "2D") together. + [codeblocks] + [gdscript] + "Node2D".to_snake_case() # Returns "node_2d" + "2nd place".to_snake_case() # Returns "2_nd_place" + "Texture3DAssetFolder".to_snake_case() # Returns "texture_3d_asset_folder" + [/gdscript] + [csharp] + "Node2D".ToSnakeCase(); // Returns "node_2d" + "2nd place".ToSnakeCase(); // Returns "2_nd_place" + "Texture3DAssetFolder".ToSnakeCase(); // Returns "texture_3d_asset_folder" + [/csharp] + [/codeblocks] </description> </method> <method name="to_upper" qualifiers="const"> <return type="String" /> <description> - Returns the string converted to uppercase. + Returns the string converted to [code]UPPERCASE[/code]. </description> </method> <method name="to_utf8_buffer" qualifiers="const"> diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index 5562342eac..32c5f8dff7 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -125,7 +125,7 @@ <param index="1" name="target_index_count" type="int" default="3" /> <description> Generates a LOD for a given [param nd_threshold] in linear units (square root of quadric error metric), using at most [param target_index_count] indices. - [i]Deprecated.[/i] Unused internally and neglects to preserve normals or UVs. Consider using [method ImporterMesh.generate_lods] instead. + [i]Deprecated.[/i] Unused internally and fails to preserve normals or UVs. Consider using [method ImporterMesh.generate_lods] instead. </description> </method> <method name="generate_normals"> diff --git a/doc/classes/SystemFont.xml b/doc/classes/SystemFont.xml index 239bcc257c..fe93571fbe 100644 --- a/doc/classes/SystemFont.xml +++ b/doc/classes/SystemFont.xml @@ -7,7 +7,7 @@ [SystemFont] loads a font from a system font with the first matching name from [member font_names]. It will attempt to match font style, but it's not guaranteed. The returned font might be part of a font collection or be a variable font with OpenType "weight", "width" and/or "italic" features set. - You can create [FontVariation] of the system font for fine control over its features. + You can create [FontVariation] of the system font for precise control over its features. [b]Note:[/b] This class is implemented on iOS, Linux, macOS and Windows, on other platforms it will fallback to default theme font. </description> <tutorials> diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index b3a9264569..1f3c3531c6 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -193,6 +193,9 @@ <member name="tab_focus_mode" type="int" setter="set_tab_focus_mode" getter="get_tab_focus_mode" enum="Control.FocusMode" default="2"> The focus access mode for the internal [TabBar] node. </member> + <member name="tabs_position" type="int" setter="set_tabs_position" getter="get_tabs_position" enum="TabContainer.TabPosition" default="0"> + Sets the position of the tab bar. See [enum TabPosition] for details. + </member> <member name="tabs_rearrange_group" type="int" setter="set_tabs_rearrange_group" getter="get_tabs_rearrange_group" default="-1"> [TabContainer]s with the same rearrange group ID will allow dragging the tabs between them. Enable drag with [member drag_to_rearrange_enabled]. Setting this to [code]-1[/code] will disable rearranging between [TabContainer]s. @@ -247,6 +250,17 @@ </description> </signal> </signals> + <constants> + <constant name="POSITION_TOP" value="0" enum="TabPosition"> + Places the tab bar at the top. + </constant> + <constant name="POSITION_BOTTOM" value="1" enum="TabPosition"> + Places the tab bar at the bottom. The tab bar's [StyleBox] will be flipped vertically. + </constant> + <constant name="POSITION_MAX" value="2" enum="TabPosition"> + Represents the size of the [enum TabPosition] enum. + </constant> + </constants> <theme_items> <theme_item name="drop_mark_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)"> Modulation color for the [theme_item drop_mark] icon. diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 4148c4eb09..ea8185fff4 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -1106,7 +1106,7 @@ </member> <member name="caret_move_on_right_click" type="bool" setter="set_move_caret_on_right_click_enabled" getter="is_move_caret_on_right_click_enabled" default="true"> If [code]true[/code], a right-click moves the caret at the mouse position before displaying the context menu. - If [code]false[/code], the context menu disregards mouse location. + If [code]false[/code], the context menu ignores mouse location. </member> <member name="caret_multiple" type="bool" setter="set_multiple_carets_enabled" getter="is_multiple_carets_enabled" default="true"> Sets if multiple carets are allowed. diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 09f484f523..cf4d92d119 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -1744,6 +1744,7 @@ Vertical BGR subpixel layout. </constant> <constant name="FONT_LCD_SUBPIXEL_LAYOUT_MAX" value="5" enum="FontLCDSubpixelLayout"> + Represents the size of the [enum FontLCDSubpixelLayout] enum. </constant> <constant name="DIRECTION_AUTO" value="0" enum="Direction"> Text direction is determined based on contents and current locale. @@ -1867,6 +1868,7 @@ Determines whether the ellipsis at the end of the text is enforced and may not be hidden. </constant> <constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag" is_bitfield="true"> + Accounts for the text being justified before attempting to trim it (see [enum JustificationFlag]). </constant> <constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag" is_bitfield="true"> Grapheme is supported by the font, and can be drawn. @@ -2005,6 +2007,7 @@ Spacing at the bottom of the line. </constant> <constant name="SPACING_MAX" value="4" enum="SpacingType"> + Represents the size of the [enum SpacingType] enum. </constant> <constant name="FONT_BOLD" value="1" enum="FontStyle" is_bitfield="true"> Font is bold. diff --git a/doc/classes/Texture2D.xml b/doc/classes/Texture2D.xml index 087f3a70f8..7254a92e36 100644 --- a/doc/classes/Texture2D.xml +++ b/doc/classes/Texture2D.xml @@ -123,6 +123,7 @@ <return type="Image" /> <description> Returns an [Image] that is a copy of data from this [Texture2D] (a new [Image] is created each time). [Image]s can be accessed and manipulated directly. + [b]Note:[/b] This will return [code]null[/code] if this [Texture2D] is invalid. [b]Note:[/b] This will fetch the texture data from the GPU, which might cause performance problems when overused. </description> </method> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index aee70f6b59..4247ff81ee 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -5,7 +5,7 @@ </brief_description> <description> A 2×3 matrix (2 rows, 3 columns) used for 2D linear transformations. It can represent transformations such as translation, rotation, and scaling. It consists of three [Vector2] values: [member x], [member y], and the [member origin]. - For more information, read the "Matrices and transforms" documentation article. + For a general introduction, see the [url=$DOCS_URL/tutorials/math/matrices_and_transforms.html]Matrices and transforms[/url] tutorial. </description> <tutorials> <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> @@ -286,6 +286,20 @@ This operator multiplies all components of the [Transform2D], including the [member origin] vector, which scales it uniformly. </description> </operator> + <operator name="operator /"> + <return type="Transform2D" /> + <param index="0" name="right" type="float" /> + <description> + This operator divides all components of the [Transform2D], including the [member origin] vector, which inversely scales it uniformly. + </description> + </operator> + <operator name="operator /"> + <return type="Transform2D" /> + <param index="0" name="right" type="int" /> + <description> + This operator divides all components of the [Transform2D], including the [member origin] vector, which inversely scales it uniformly. + </description> + </operator> <operator name="operator =="> <return type="bool" /> <param index="0" name="right" type="Transform2D" /> diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml index 85da629d70..a1ddb75bc2 100644 --- a/doc/classes/Transform3D.xml +++ b/doc/classes/Transform3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> A 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations. It can represent transformations such as translation, rotation, and scaling. It consists of a [member basis] (first 3 columns) and a [Vector3] for the [member origin] (last column). - For more information, read the "Matrices and transforms" documentation article. + For a general introduction, see the [url=$DOCS_URL/tutorials/math/matrices_and_transforms.html]Matrices and transforms[/url] tutorial. </description> <tutorials> <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> @@ -245,6 +245,20 @@ This operator multiplies all components of the [Transform3D], including the [member origin] vector, which scales it uniformly. </description> </operator> + <operator name="operator /"> + <return type="Transform3D" /> + <param index="0" name="right" type="float" /> + <description> + This operator divides all components of the [Transform3D], including the [member origin] vector, which inversely scales it uniformly. + </description> + </operator> + <operator name="operator /"> + <return type="Transform3D" /> + <param index="0" name="right" type="int" /> + <description> + This operator divides all components of the [Transform3D], including the [member origin] vector, which inversely scales it uniformly. + </description> + </operator> <operator name="operator =="> <return type="bool" /> <param index="0" name="right" type="Transform3D" /> diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index 0ecfe53123..b265f8ba11 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -5,7 +5,7 @@ </brief_description> <description> Tweens are mostly useful for animations requiring a numerical property to be interpolated over a range of values. The name [i]tween[/i] comes from [i]in-betweening[/i], an animation technique where you specify [i]keyframes[/i] and the computer interpolates the frames that appear between them. Animating something with a [Tween] is called tweening. - [Tween] is more suited than [AnimationPlayer] for animations where you don't know the final values in advance. For example, interpolating a dynamically-chosen camera zoom value is best done with a [Tween]; it would be difficult to do the same thing with an [AnimationPlayer] node. Tweens are also more light-weight than [AnimationPlayer], so they are very much suited for simple animations or general tasks that don't require visual tweaking provided by the editor. They can be used in a fire-and-forget manner for some logic that normally would be done by code. You can e.g. make something shoot periodically by using a looped [CallbackTweener] with a delay. + [Tween] is more suited than [AnimationPlayer] for animations where you don't know the final values in advance. For example, interpolating a dynamically-chosen camera zoom value is best done with a [Tween]; it would be difficult to do the same thing with an [AnimationPlayer] node. Tweens are also more light-weight than [AnimationPlayer], so they are very much suited for simple animations or general tasks that don't require visual tweaking provided by the editor. They can be used in a "fire-and-forget" manner for some logic that normally would be done by code. You can e.g. make something shoot periodically by using a looped [CallbackTweener] with a delay. A [Tween] can be created by using either [method SceneTree.create_tween] or [method Node.create_tween]. [Tween]s created manually (i.e. by using [code]Tween.new()[/code]) are invalid and can't be used for tweening values. A tween animation is created by adding [Tweener]s to the [Tween] object, using [method tween_property], [method tween_interval], [method tween_callback] or [method tween_method]: [codeblocks] diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml index 2100cd7612..e004755818 100644 --- a/doc/classes/Vector2i.xml +++ b/doc/classes/Vector2i.xml @@ -64,6 +64,21 @@ Returns a new vector with all components clamped between the components of [param min] and [param max], by running [method @GlobalScope.clamp] on each component. </description> </method> + <method name="distance_squared_to" qualifiers="const"> + <return type="int" /> + <param index="0" name="to" type="Vector2i" /> + <description> + Returns the squared distance between this vector and [param to]. + This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula. + </description> + </method> + <method name="distance_to" qualifiers="const"> + <return type="float" /> + <param index="0" name="to" type="Vector2i" /> + <description> + Returns the distance between this vector and [param to]. + </description> + </method> <method name="length" qualifiers="const"> <return type="float" /> <description> diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml index 8906bf0aa7..96760ed9f9 100644 --- a/doc/classes/Vector3i.xml +++ b/doc/classes/Vector3i.xml @@ -59,6 +59,21 @@ Returns a new vector with all components clamped between the components of [param min] and [param max], by running [method @GlobalScope.clamp] on each component. </description> </method> + <method name="distance_squared_to" qualifiers="const"> + <return type="int" /> + <param index="0" name="to" type="Vector3i" /> + <description> + Returns the squared distance between this vector and [param to]. + This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula. + </description> + </method> + <method name="distance_to" qualifiers="const"> + <return type="float" /> + <param index="0" name="to" type="Vector3i" /> + <description> + Returns the distance between this vector and [param to]. + </description> + </method> <method name="length" qualifiers="const"> <return type="float" /> <description> diff --git a/doc/classes/Vector4i.xml b/doc/classes/Vector4i.xml index a612c135dd..464c19c223 100644 --- a/doc/classes/Vector4i.xml +++ b/doc/classes/Vector4i.xml @@ -57,6 +57,21 @@ Returns a new vector with all components clamped between the components of [param min] and [param max], by running [method @GlobalScope.clamp] on each component. </description> </method> + <method name="distance_squared_to" qualifiers="const"> + <return type="int" /> + <param index="0" name="to" type="Vector4i" /> + <description> + Returns the squared distance between this vector and [param to]. + This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula. + </description> + </method> + <method name="distance_to" qualifiers="const"> + <return type="float" /> + <param index="0" name="to" type="Vector4i" /> + <description> + Returns the distance between this vector and [param to]. + </description> + </method> <method name="length" qualifiers="const"> <return type="float" /> <description> diff --git a/doc/classes/VehicleWheel3D.xml b/doc/classes/VehicleWheel3D.xml index 9c7ba58534..77cb5ca9f8 100644 --- a/doc/classes/VehicleWheel3D.xml +++ b/doc/classes/VehicleWheel3D.xml @@ -81,7 +81,7 @@ This is the distance in meters the wheel is lowered from its origin point. Don't set this to 0.0 and move the wheel into position, instead move the origin point of your wheel (the gizmo in Godot) to the position the wheel will take when bottoming out, then use the rest length to move the wheel down to the position it should be in when the car is in rest. </member> <member name="wheel_roll_influence" type="float" setter="set_roll_influence" getter="get_roll_influence" default="0.1"> - This value affects the roll of your vehicle. If set to 1.0 for all wheels, your vehicle will be prone to rolling over, while a value of 0.0 will resist body roll. + This value affects the roll of your vehicle. If set to 1.0 for all wheels, your vehicle will resist body roll, while a value of 0.0 will be prone to rolling over. </member> </members> </class> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index 5f6b1960b7..618a774aae 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -357,10 +357,11 @@ Centers a native window on the current screen and an embedded window on its embedder [Viewport]. </description> </method> - <method name="move_to_foreground"> + <method name="move_to_foreground" is_deprecated="true"> <return type="void" /> <description> Moves the [Window] on top of other windows and focuses it. + [i]Deprecated.[/i] Use [method Window.grab_focus] instead. </description> </method> <method name="popup"> @@ -668,6 +669,9 @@ If [code]true[/code], the [Window] is transient, i.e. it's considered a child of another [Window]. The transient window will be destroyed with its transient parent and will return focus to their parent when closed. The transient window is displayed on top of a non-exclusive full-screen parent window. Transient windows can't enter full-screen mode. Note that behavior might be different depending on the platform. </member> + <member name="transient_to_focused" type="bool" setter="set_transient_to_focused" getter="is_transient_to_focused" default="false"> + If [code]true[/code], and the [Window] is [member transient], this window will (at the time of becoming visible) become transient to the currently focused window instead of the immediate parent window in the hierarchy. Note that the transient parent is assigned at the time this window becomes visible, so changing it afterwards has no effect until re-shown. + </member> <member name="transparent" type="bool" setter="set_flag" getter="get_flag" default="false"> If [code]true[/code], the [Window]'s background can be transparent. This is best used with embedded windows. [b]Note:[/b] Transparency support is implemented on Linux, macOS and Windows, but availability might vary depending on GPU driver, display manager, and compositor capabilities. diff --git a/doc/classes/WorkerThreadPool.xml b/doc/classes/WorkerThreadPool.xml index d6751d31ce..fa1f08b149 100644 --- a/doc/classes/WorkerThreadPool.xml +++ b/doc/classes/WorkerThreadPool.xml @@ -106,7 +106,7 @@ Pauses the thread that calls this method until the task with the given ID is completed. Returns [constant @GlobalScope.OK] if the task could be successfully awaited. Returns [constant @GlobalScope.ERR_INVALID_PARAMETER] if a task with the passed ID does not exist (maybe because it was already awaited and disposed of). - Returns [constant @GlobalScope.ERR_BUSY] if the call is made from another running task and, due to task scheduling, the task to await is at a lower level in the call stack and therefore can't progress. This is an advanced situation that should only matter when some tasks depend on others. + Returns [constant @GlobalScope.ERR_BUSY] if the call is made from another running task and, due to task scheduling, there's potential for deadlocking (e.g., the task to await may be at a lower level in the call stack and therefore can't progress). This is an advanced situation that should only matter when some tasks depend on others (in the current implementation, the tricky case is a task trying to wait on an older one). </description> </method> </methods> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index c3a21f3d7b..4435d52527 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -68,6 +68,8 @@ BASE_STRINGS = [ "This value is an integer composed as a bitmask of the following flags.", "There is currently no description for this class. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!", "There is currently no description for this signal. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!", + "There is currently no description for this enum. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!", + "There is currently no description for this constant. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!", "There is currently no description for this annotation. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!", "There is currently no description for this property. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!", "There is currently no description for this constructor. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!", @@ -105,6 +107,7 @@ EDITOR_CLASSES: List[str] = [ CLASSES_WITH_CSHARP_DIFFERENCES: List[str] = [ "@GlobalScope", "String", + "StringName", "NodePath", "Signal", "Callable", @@ -140,6 +143,9 @@ class State: self.classes: OrderedDict[str, ClassDef] = OrderedDict() self.current_class: str = "" + # Additional content and structure checks and validators. + self.script_language_parity_check: ScriptLanguageParityCheck = ScriptLanguageParityCheck() + def parse_class(self, class_root: ET.Element, filepath: str) -> None: class_name = class_root.attrib["name"] self.current_class = class_name @@ -542,6 +548,9 @@ class ClassDef(DefinitionBase): def __init__(self, name: str) -> None: super().__init__("class", name) + self.class_group = "variant" + self.editor_class = self._is_editor_class() + self.constants: OrderedDict[str, ConstantDef] = OrderedDict() self.enums: OrderedDict[str, EnumDef] = OrderedDict() self.properties: OrderedDict[str, PropertyDef] = OrderedDict() @@ -559,6 +568,65 @@ class ClassDef(DefinitionBase): # Used to match the class with XML source for output filtering purposes. self.filepath: str = "" + def _is_editor_class(self) -> bool: + if self.name.startswith("Editor"): + return True + if self.name in EDITOR_CLASSES: + return True + + return False + + def update_class_group(self, state: State) -> None: + group_name = "variant" + + if self.name.startswith("@"): + group_name = "global" + elif self.inherits: + inherits = self.inherits.strip() + + while inherits in state.classes: + if inherits == "Node": + group_name = "node" + break + if inherits == "Resource": + group_name = "resource" + break + if inherits == "Object": + group_name = "object" + break + + inode = state.classes[inherits].inherits + if inode: + inherits = inode.strip() + else: + break + + self.class_group = group_name + + +# Checks if code samples have both GDScript and C# variations. +# For simplicity we assume that a GDScript example is always present, and ignore contexts +# which don't necessarily need C# examples. +class ScriptLanguageParityCheck: + def __init__(self) -> None: + self.hit_map: OrderedDict[str, List[Tuple[DefinitionBase, str]]] = OrderedDict() + self.hit_count = 0 + + def add_hit(self, class_name: str, context: DefinitionBase, error: str, state: State) -> None: + if class_name in ["@GDScript", "@GlobalScope"]: + return # We don't expect these contexts to have parity. + + class_def = state.classes[class_name] + if class_def.class_group == "variant" and class_def.name != "Object": + return # Variant types are replaced with native types in C#, we don't expect parity. + + self.hit_count += 1 + + if class_name not in self.hit_map: + self.hit_map[class_name] = [] + + self.hit_map[class_name].append((context, error)) + # Entry point for the RST generator. def main() -> None: @@ -589,6 +657,11 @@ def main() -> None: action="store_true", help="If passed, no output will be generated and XML files are only checked for errors.", ) + parser.add_argument( + "--verbose", + action="store_true", + help="If passed, enables verbose printing.", + ) args = parser.parse_args() should_color = args.color or (hasattr(sys.stdout, "isatty") and sys.stdout.isatty()) @@ -683,15 +756,15 @@ def main() -> None: if args.filter and not pattern.search(class_def.filepath): continue state.current_class = class_name - make_rst_class(class_def, state, args.dry_run, args.output) - group_name = get_class_group(class_def, state) + class_def.update_class_group(state) + make_rst_class(class_def, state, args.dry_run, args.output) - if group_name not in grouped_classes: - grouped_classes[group_name] = [] - grouped_classes[group_name].append(class_name) + if class_def.class_group not in grouped_classes: + grouped_classes[class_def.class_group] = [] + grouped_classes[class_def.class_group].append(class_name) - if is_editor_class(class_def): + if class_def.editor_class: if "editor" not in grouped_classes: grouped_classes["editor"] = [] grouped_classes["editor"].append(class_name) @@ -703,6 +776,26 @@ def main() -> None: print("") + # Print out checks. + + if state.script_language_parity_check.hit_count > 0: + if not args.verbose: + print( + f'{STYLES["yellow"]}{state.script_language_parity_check.hit_count} code samples failed parity check. Use --verbose to get more information.{STYLES["reset"]}' + ) + else: + print( + f'{STYLES["yellow"]}{state.script_language_parity_check.hit_count} code samples failed parity check:{STYLES["reset"]}' + ) + + for class_name in state.script_language_parity_check.hit_map.keys(): + class_hits = state.script_language_parity_check.hit_map[class_name] + print(f'{STYLES["yellow"]}- {len(class_hits)} hits in class "{class_name}"{STYLES["reset"]}') + + for context, error in class_hits: + print(f" - {error} in {format_context_name(context)}") + print("") + # Print out warnings and errors, or lack thereof, and exit with an appropriate code. if state.num_warnings >= 2: @@ -759,46 +852,6 @@ def get_git_branch() -> str: return "master" -def get_class_group(class_def: ClassDef, state: State) -> str: - group_name = "variant" - class_name = class_def.name - - if class_name.startswith("@"): - group_name = "global" - elif class_def.inherits: - inherits = class_def.inherits.strip() - - while inherits in state.classes: - if inherits == "Node": - group_name = "node" - break - if inherits == "Resource": - group_name = "resource" - break - if inherits == "Object": - group_name = "object" - break - - inode = state.classes[inherits].inherits - if inode: - inherits = inode.strip() - else: - break - - return group_name - - -def is_editor_class(class_def: ClassDef) -> bool: - class_name = class_def.name - - if class_name.startswith("Editor"): - return True - if class_name in EDITOR_CLASSES: - return True - - return False - - # Generator methods. @@ -1051,6 +1104,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir: if value.text is not None and value.text.strip() != "": f.write(f"{format_text_block(value.text.strip(), value, state)}") + else: + f.write(".. container:: contribute\n\n\t") + f.write( + translate( + "There is currently no description for this enum. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!" + ) + + "\n\n" + ) f.write("\n\n") @@ -1074,6 +1135,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir: if constant.text is not None and constant.text.strip() != "": f.write(f"{format_text_block(constant.text.strip(), constant, state)}") + else: + f.write(".. container:: contribute\n\n\t") + f.write( + translate( + "There is currently no description for this constant. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!" + ) + + "\n\n" + ) f.write("\n\n") @@ -1641,7 +1710,7 @@ def parse_link_target(link_target: str, state: State, context_name: str) -> List def format_text_block( text: str, - context: Union[DefinitionBase, None], + context: DefinitionBase, state: State, ) -> str: # Linebreak + tabs in the XML should become two line breaks unless in a "codeblock" @@ -1690,6 +1759,10 @@ def format_text_block( inside_code_tag = "" inside_code_tabs = False ignore_code_warnings = False + code_warning_if_intended_string = "If this is intended, use [code skip-lint]...[/code]." + + has_codeblocks_gdscript = False + has_codeblocks_csharp = False pos = 0 tag_depth = 0 @@ -1748,7 +1821,7 @@ def format_text_block( else: if not ignore_code_warnings and tag_state.closing: print_warning( - f'{state.current_class}.xml: Found a code string that looks like a closing tag "[{tag_state.raw}]" in {context_name}.', + f'{state.current_class}.xml: Found a code string that looks like a closing tag "[{tag_state.raw}]" in {context_name}. {code_warning_if_intended_string}', state, ) @@ -1758,6 +1831,17 @@ def format_text_block( elif tag_state.name == "codeblocks": if tag_state.closing: + if not has_codeblocks_gdscript or not has_codeblocks_csharp: + state.script_language_parity_check.add_hit( + state.current_class, + context, + "Only one script language sample found in [codeblocks]", + state, + ) + + has_codeblocks_gdscript = False + has_codeblocks_csharp = False + tag_depth -= 1 tag_text = "" inside_code_tabs = False @@ -1775,6 +1859,8 @@ def format_text_block( f"{state.current_class}.xml: GDScript code block is used outside of [codeblocks] in {context_name}.", state, ) + else: + has_codeblocks_gdscript = True tag_text = "\n .. code-tab:: gdscript\n" elif tag_state.name == "csharp": if not inside_code_tabs: @@ -1782,8 +1868,17 @@ def format_text_block( f"{state.current_class}.xml: C# code block is used outside of [codeblocks] in {context_name}.", state, ) + else: + has_codeblocks_csharp = True tag_text = "\n .. code-tab:: csharp\n" else: + state.script_language_parity_check.add_hit( + state.current_class, + context, + "Code sample is formatted with [codeblock] where [codeblocks] should be used", + state, + ) + tag_text = "\n::\n" inside_code = True @@ -1815,7 +1910,7 @@ def format_text_block( if inside_code_text in state.classes: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches one of the known classes in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches one of the known classes in {context_name}. {code_warning_if_intended_string}', state, ) @@ -1825,49 +1920,49 @@ def format_text_block( if target_name in class_def.methods: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} method in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} method in {context_name}. {code_warning_if_intended_string}', state, ) elif target_name in class_def.constructors: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} constructor in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} constructor in {context_name}. {code_warning_if_intended_string}', state, ) elif target_name in class_def.operators: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} operator in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} operator in {context_name}. {code_warning_if_intended_string}', state, ) elif target_name in class_def.properties: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} member in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} member in {context_name}. {code_warning_if_intended_string}', state, ) elif target_name in class_def.signals: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} signal in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} signal in {context_name}. {code_warning_if_intended_string}', state, ) elif target_name in class_def.annotations: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} annotation in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} annotation in {context_name}. {code_warning_if_intended_string}', state, ) elif target_name in class_def.theme_items: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} theme item in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} theme item in {context_name}. {code_warning_if_intended_string}', state, ) elif target_name in class_def.constants: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} constant in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} constant in {context_name}. {code_warning_if_intended_string}', state, ) @@ -1875,7 +1970,7 @@ def format_text_block( for enum in class_def.enums.values(): if target_name in enum.values: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} enum value in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches the {target_class_name}.{target_name} enum value in {context_name}. {code_warning_if_intended_string}', state, ) break @@ -1886,7 +1981,7 @@ def format_text_block( for param_def in context_params: if param_def.name == inside_code_text: print_warning( - f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches one of the parameters in {context_name}.', + f'{state.current_class}.xml: Found a code string "{inside_code_text}" that matches one of the parameters in {context_name}. {code_warning_if_intended_string}', state, ) break diff --git a/drivers/d3d12/SCsub b/drivers/d3d12/SCsub index 11ae52fd40..a49d55ebc0 100644 --- a/drivers/d3d12/SCsub +++ b/drivers/d3d12/SCsub @@ -5,8 +5,6 @@ from pathlib import Path Import("env") -env.Append(CPPDEFINES=["RD_ENABLED"]) - env_d3d12_rdd = env.Clone() thirdparty_obj = [] diff --git a/drivers/d3d12/d3d12_context.cpp b/drivers/d3d12/d3d12_context.cpp index 36492b198b..0ba3f59119 100644 --- a/drivers/d3d12/d3d12_context.cpp +++ b/drivers/d3d12/d3d12_context.cpp @@ -57,25 +57,11 @@ #include <dxguids.h> #endif +// Note: symbol is not available in MinGW and old MSVC import libraries. +const CLSID CLSID_D3D12DeviceFactoryGodot = __uuidof(ID3D12DeviceFactory); + extern "C" { char godot_nir_arch_name[32]; - -#ifdef AGILITY_SDK_ENABLED -__declspec(dllexport) extern const UINT D3D12SDKVersion = 610; -#ifdef AGILITY_SDK_MULTIARCH_ENABLED -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) -__declspec(dllexport) extern const char *D3D12SDKPath = "\\.\\arm64"; -#elif defined(__arm__) || defined(_M_ARM) -__declspec(dllexport) extern const char *D3D12SDKPath = "\\.\\arm32"; -#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) -__declspec(dllexport) extern const char *D3D12SDKPath = "\\.\\x86_64"; -#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) -__declspec(dllexport) extern const char *D3D12SDKPath = "\\.\\x86_32"; -#endif -#else -__declspec(dllexport) extern const char *D3D12SDKPath = "\\."; -#endif // AGILITY_SDK_MULTIARCH -#endif // AGILITY_SDK_ENABLED } #ifdef PIX_ENABLED @@ -89,6 +75,8 @@ __declspec(dllexport) extern const char *D3D12SDKPath = "\\."; #endif #endif +#define D3D12_DEBUG_LAYER_BREAK_ON_ERROR 0 + void D3D12Context::_debug_message_func( D3D12_MESSAGE_CATEGORY p_category, D3D12_MESSAGE_SEVERITY p_severity, @@ -295,7 +283,12 @@ Error D3D12Context::_check_capabilities() { Error D3D12Context::_initialize_debug_layers() { ComPtr<ID3D12Debug> debug_controller; - HRESULT res = D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller)); + HRESULT res; + if (device_factory) { + res = device_factory->GetConfigurationInterface(CLSID_D3D12Debug, IID_PPV_ARGS(&debug_controller)); + } else { + res = D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller)); + } ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_QUERY_FAILED); debug_controller->EnableDebugLayer(); return OK; @@ -501,7 +494,12 @@ void D3D12Context::_dump_adapter_info(int p_index) { } Error D3D12Context::_create_device(DeviceBasics &r_basics) { - HRESULT res = D3D12CreateDevice(gpu.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(r_basics.device.GetAddressOf())); + HRESULT res; + if (device_factory) { + res = device_factory->CreateDevice(gpu.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(r_basics.device.GetAddressOf())); + } else { + res = D3D12CreateDevice(gpu.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(r_basics.device.GetAddressOf())); + } ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "D3D12CreateDevice failed with error " + vformat("0x%08ux", (uint64_t)res) + "."); // Create direct command queue. @@ -566,6 +564,11 @@ Error D3D12Context::_create_device(DeviceBasics &r_basics) { res = info_queue->PushStorageFilter(&filter); ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE); + +#if D3D12_DEBUG_LAYER_BREAK_ON_ERROR + res = info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); + ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE); +#endif } return OK; @@ -808,7 +811,32 @@ Error D3D12Context::_update_swap_chain(Window *window) { return OK; } +void D3D12Context::_init_device_factory() { + uint32_t agility_sdk_version = GLOBAL_GET("rendering/rendering_device/d3d12/agility_sdk_version"); + String agility_sdk_path = String(".\\") + Engine::get_singleton()->get_architecture_name(); + + // Note: symbol is not available in MinGW import library. + PFN_D3D12_GET_INTERFACE d3d_D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)GetProcAddress(LoadLibraryW(L"D3D12.dll"), "D3D12GetInterface"); + ERR_FAIL_COND(!d3d_D3D12GetInterface); + + ID3D12SDKConfiguration *sdk_config = nullptr; + if (SUCCEEDED(d3d_D3D12GetInterface(CLSID_D3D12SDKConfiguration, IID_PPV_ARGS(&sdk_config)))) { + ID3D12SDKConfiguration1 *sdk_config1 = nullptr; + if (SUCCEEDED(sdk_config->QueryInterface(&sdk_config1))) { + if (SUCCEEDED(sdk_config1->CreateDeviceFactory(agility_sdk_version, agility_sdk_path.ascii().get_data(), IID_PPV_ARGS(device_factory.GetAddressOf())))) { + d3d_D3D12GetInterface(CLSID_D3D12DeviceFactoryGodot, IID_PPV_ARGS(device_factory.GetAddressOf())); + } else if (SUCCEEDED(sdk_config1->CreateDeviceFactory(agility_sdk_version, ".\\", IID_PPV_ARGS(device_factory.GetAddressOf())))) { + d3d_D3D12GetInterface(CLSID_D3D12DeviceFactoryGodot, IID_PPV_ARGS(device_factory.GetAddressOf())); + } + sdk_config1->Release(); + } + sdk_config->Release(); + } +} + Error D3D12Context::initialize() { + _init_device_factory(); + if (_use_validation_layers()) { Error err = _initialize_debug_layers(); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); @@ -867,7 +895,9 @@ void D3D12Context::_wait_for_idle_queue(ID3D12CommandQueue *p_queue) { #endif } -void D3D12Context::flush(bool p_flush_setup, bool p_flush_pending) { +void D3D12Context::flush(bool p_flush_setup, bool p_flush_pending, bool p_sync) { + ERR_FAIL_COND_MSG(!p_sync, "Flush without sync is not supported."); // This is a special case for Vulkan on mobile XR hardware, not applicable to D3D12 + if (p_flush_setup && command_list_queue[0]) { md.queue->ExecuteCommandLists(1, command_list_queue.ptr()); command_list_queue[0] = nullptr; @@ -1032,27 +1062,6 @@ void D3D12Context::local_device_free(RID p_local_device) { local_device_owner.free(p_local_device); } -void D3D12Context::command_begin_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) { -#ifdef PIX_ENABLED - const RenderingDeviceDriverD3D12::CommandBufferInfo *cmd_buf_info = (const RenderingDeviceDriverD3D12::CommandBufferInfo *)p_command_buffer.id; - PIXBeginEvent(cmd_buf_info->cmd_list.Get(), p_color.to_argb32(), p_label_name.utf8().get_data()); -#endif -} - -void D3D12Context::command_insert_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) { -#ifdef PIX_ENABLED - const RenderingDeviceDriverD3D12::CommandBufferInfo *cmd_buf_info = (const RenderingDeviceDriverD3D12::CommandBufferInfo *)p_command_buffer.id; - PIXSetMarker(cmd_buf_info->cmd_list.Get(), p_color.to_argb32(), p_label_name.utf8().get_data()); -#endif -} - -void D3D12Context::command_end_label(RDD::CommandBufferID p_command_buffer) { -#ifdef PIX_ENABLED - const RenderingDeviceDriverD3D12::CommandBufferInfo *cmd_buf_info = (const RenderingDeviceDriverD3D12::CommandBufferInfo *)p_command_buffer.id; - PIXEndEvent(cmd_buf_info->cmd_list.Get()); -#endif -} - void D3D12Context::set_object_name(ID3D12Object *p_object, String p_object_name) { ERR_FAIL_NULL(p_object); int name_len = p_object_name.size(); @@ -1101,6 +1110,14 @@ RenderingDeviceDriver *D3D12Context::get_driver(RID p_local_device) { } } +bool D3D12Context::is_debug_utils_enabled() const { +#ifdef PIX_ENABLED + return true; +#else + return false; +#endif +} + D3D12Context::D3D12Context() { command_list_queue.resize(1); // First one is always the setup command. command_list_queue[0] = nullptr; diff --git a/drivers/d3d12/d3d12_context.h b/drivers/d3d12/d3d12_context.h index ec4bc832b6..ac90d38467 100644 --- a/drivers/d3d12/d3d12_context.h +++ b/drivers/d3d12/d3d12_context.h @@ -110,6 +110,7 @@ private: IMAGE_COUNT = FRAME_LAG + 1, }; + ComPtr<ID3D12DeviceFactory> device_factory; ComPtr<IDXGIFactory2> dxgi_factory; ComPtr<IDXGIAdapter> gpu; DeviceLimits gpu_limits = {}; @@ -181,6 +182,7 @@ private: void *p_context); Error _initialize_debug_layers(); + void _init_device_factory(); Error _select_adapter(int &r_index); void _dump_adapter_info(int p_index); @@ -232,15 +234,12 @@ public: virtual void set_setup_buffer(RDD::CommandBufferID p_command_buffer) override final; virtual void append_command_buffer(RDD::CommandBufferID p_command_buffer) override final; void resize_notify(); - virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false) override final; + virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false, bool p_sync = true) override final; virtual Error prepare_buffers(RDD::CommandBufferID p_command_buffer) override final; virtual void postpare_buffers(RDD::CommandBufferID p_command_buffer) override final; virtual Error swap_buffers() override final; virtual Error initialize() override final; - virtual void command_begin_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) override final; - virtual void command_insert_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) override final; - virtual void command_end_label(RDD::CommandBufferID p_command_buffer) override final; void set_object_name(ID3D12Object *p_object, String p_object_name); virtual String get_device_vendor_name() const override final; @@ -253,6 +252,7 @@ public: virtual DisplayServer::VSyncMode get_vsync_mode(DisplayServer::WindowID p_window = 0) const override final; virtual RenderingDeviceDriver *get_driver(RID p_local_device = RID()) override final; + virtual bool is_debug_utils_enabled() const override final; D3D12Context(); virtual ~D3D12Context(); diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp index 6a2a3c32b0..aed82b4ce8 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp @@ -78,6 +78,17 @@ extern "C" { #undef UNUSED #endif +#ifdef PIX_ENABLED +#if defined(__GNUC__) +#define _MSC_VER 1800 +#endif +#define USE_PIX +#include "WinPixEventRuntime/pix3.h" +#if defined(__GNUC__) +#undef _MSC_VER +#endif +#endif + static const D3D12_RANGE VOID_RANGE = {}; static const uint32_t ROOT_CONSTANT_SPACE = RDD::MAX_UNIFORM_SETS + 1; @@ -5159,7 +5170,21 @@ void RenderingDeviceDriverD3D12::command_timestamp_write(CommandBufferID p_cmd_b TimestampQueryPoolInfo *tqp_info = (TimestampQueryPoolInfo *)p_pool_id.id; ID3D12Resource *results_buffer = tqp_info->results_buffer_allocation->GetResource(); cmd_buf_info->cmd_list->EndQuery(tqp_info->query_heap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, p_index); - cmd_buf_info->cmd_list->ResolveQueryData(tqp_info->query_heap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, p_index, tqp_info->query_count, results_buffer, p_index * sizeof(uint64_t)); + cmd_buf_info->cmd_list->ResolveQueryData(tqp_info->query_heap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, p_index, 1, results_buffer, p_index * sizeof(uint64_t)); +} + +void RenderingDeviceDriverD3D12::command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) { +#ifdef PIX_ENABLED + const CommandBufferInfo *cmd_buf_info = (const CommandBufferInfo *)p_cmd_buffer.id; + PIXBeginEvent(cmd_buf_info->cmd_list.Get(), p_color.to_argb32(), p_label_name); +#endif +} + +void RenderingDeviceDriverD3D12::command_end_label(CommandBufferID p_cmd_buffer) { +#ifdef PIX_ENABLED + const CommandBufferInfo *cmd_buf_info = (const CommandBufferInfo *)p_cmd_buffer.id; + PIXEndEvent(cmd_buf_info->cmd_list.Get()); +#endif } /****************/ diff --git a/drivers/d3d12/rendering_device_driver_d3d12.h b/drivers/d3d12/rendering_device_driver_d3d12.h index bd19572878..0da339c6fd 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.h +++ b/drivers/d3d12/rendering_device_driver_d3d12.h @@ -771,6 +771,13 @@ public: virtual void command_timestamp_write(CommandBufferID p_cmd_buffer, QueryPoolID p_pool_id, uint32_t p_index) override final; /****************/ + /**** LABELS ****/ + /****************/ + + virtual void command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) override final; + virtual void command_end_label(CommandBufferID p_cmd_buffer) override final; + + /****************/ /**** SCREEN ****/ /****************/ diff --git a/drivers/egl/egl_manager.h b/drivers/egl/egl_manager.h index c3a749cd19..61d3289b2d 100644 --- a/drivers/egl/egl_manager.h +++ b/drivers/egl/egl_manager.h @@ -45,7 +45,7 @@ class EGLManager { private: - // An EGL-side rappresentation of a display with its own rendering + // An EGL-side representation of a display with its own rendering // context. struct GLDisplay { void *display = nullptr; diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp index 996e7eee7f..c6fb6ca70b 100644 --- a/drivers/gles3/effects/copy_effects.cpp +++ b/drivers/gles3/effects/copy_effects.cpp @@ -125,6 +125,18 @@ void CopyEffects::copy_to_rect(const Rect2 &p_rect) { draw_screen_quad(); } +void CopyEffects::copy_to_and_from_rect(const Rect2 &p_rect) { + bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION_SOURCE); + if (!success) { + return; + } + + copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION_SOURCE); + copy.shader.version_set_uniform(CopyShaderGLES3::SOURCE_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION_SOURCE); + + draw_screen_quad(); +} + void CopyEffects::copy_screen() { bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT); if (!success) { diff --git a/drivers/gles3/effects/copy_effects.h b/drivers/gles3/effects/copy_effects.h index 6e2cb07382..509d07b955 100644 --- a/drivers/gles3/effects/copy_effects.h +++ b/drivers/gles3/effects/copy_effects.h @@ -62,6 +62,7 @@ public: // These functions assume that a framebuffer and texture are bound already. They only manage the shader, uniforms, and vertex array. void copy_to_rect(const Rect2 &p_rect); + void copy_to_and_from_rect(const Rect2 &p_rect); void copy_screen(); void copy_cube_to_rect(const Rect2 &p_rect); void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region); diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 5d6cef6e05..fe16d8838b 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -2295,14 +2295,18 @@ void RasterizerCanvasGLES3::_prepare_canvas_texture(RID p_texture, RS::CanvasIte GLES3::Texture *texture = texture_storage->get_texture(ct->diffuse); Size2i size_cache; + + // Cache default white resource ID. + const RID default_texture_id = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE); + + // If no texture is assigned, assign default white. if (!texture) { - ct->diffuse = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE); - GLES3::Texture *tex = texture_storage->get_texture(ct->diffuse); - size_cache = Size2i(tex->width, tex->height); - } else { - size_cache = Size2i(texture->width, texture->height); + ct->diffuse = default_texture_id; } + // Enforce a 1x1 size if default white texture. + size_cache = ct->diffuse == default_texture_id ? Size2i(1, 1) : Size2i(texture->width, texture->height); + GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map); if (ct->specular_color.a < 0.999) { diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index c048e9bf37..6ab98a9473 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -103,6 +103,11 @@ void RasterizerGLES3::begin_frame(double frame_step) { } void RasterizerGLES3::end_frame(bool p_swap_buffers) { + GLES3::Utilities *utils = GLES3::Utilities::get_singleton(); + utils->capture_timestamps_end(); +} + +void RasterizerGLES3::end_viewport(bool p_swap_buffers) { if (p_swap_buffers) { DisplayServer::get_singleton()->swap_buffers(); } else { @@ -352,13 +357,6 @@ RasterizerGLES3::~RasterizerGLES3() { } void RasterizerGLES3::prepare_for_blitting_render_targets() { - // This is a hack, but this function is called one time after all viewports have been updated. - // So it marks the end of the frame for all viewports - // In the OpenGL renderer we have to call end_frame for each viewport so we can swap the - // buffers for each window before proceeding to the next. - // This allows us to only increment the frame after all viewports are done. - GLES3::Utilities *utils = GLES3::Utilities::get_singleton(); - utils->capture_timestamps_end(); } void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect, uint32_t p_layer, bool p_first) { @@ -474,7 +472,7 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c copy_effects->copy_to_rect(screenrect); glBindTexture(GL_TEXTURE_2D, 0); - end_frame(true); + end_viewport(true); texture_storage->texture_free(texture); } diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index b19ca0e9c9..d9f436a2ec 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -93,6 +93,7 @@ public: void prepare_for_blitting_render_targets(); void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount); + void end_viewport(bool p_swap_buffers); void end_frame(bool p_swap_buffers); void finalize(); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index a860793c21..045511321a 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -328,6 +328,7 @@ private: }; enum { + INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3, INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4, INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5, INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 7, diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 75b2662a1c..27402da7c8 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -49,7 +49,7 @@ void ShaderGLES3::_add_stage(const char *p_code, StageType p_stage_type) { String text; for (int i = 0; i < lines.size(); i++) { - String l = lines[i]; + const String &l = lines[i]; bool push_chunk = false; StageTemplate::Chunk chunk; @@ -611,6 +611,7 @@ void ShaderGLES3::_save_to_cache(Version *p_version) { #ifdef WEB_ENABLED // not supported in webgl return; #else + ERR_FAIL_COND(!shader_cache_dir_valid); #if !defined(ANDROID_ENABLED) && !defined(IOS_ENABLED) if (RasterizerGLES3::is_gles_over_gl() && (glGetProgramBinary == NULL)) { // ARB_get_program_binary extension not available. return; diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 0cb53da316..8968e76c12 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -209,7 +209,9 @@ protected: _compile_specialization(s, p_variant, version, p_specialization); version->variants[p_variant].insert(p_specialization, s); spec = version->variants[p_variant].lookup_ptr(p_specialization); - _save_to_cache(version); + if (shader_cache_dir_valid) { + _save_to_cache(version); + } } } else if (spec->build_queued) { // Still queued, wait diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index 265acc1430..f37968a4fd 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -3,6 +3,7 @@ mode_default = #define MODE_SIMPLE_COPY mode_copy_section = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY +mode_copy_section_source = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define MODE_COPY_FROM mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR mode_mipmap = #define MODE_MIPMAP mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION @@ -21,7 +22,7 @@ out vec2 uv_interp; // Defined in 0-1 coords. uniform highp vec4 copy_section; #endif -#ifdef MODE_GAUSSIAN_BLUR +#if defined(MODE_GAUSSIAN_BLUR) || defined(MODE_COPY_FROM) uniform highp vec4 source_section; #endif @@ -32,7 +33,7 @@ void main() { #if defined(USE_COPY_SECTION) || defined(MODE_GAUSSIAN_BLUR) gl_Position.xy = (copy_section.xy + uv_interp.xy * copy_section.zw) * 2.0 - 1.0; #endif -#ifdef MODE_GAUSSIAN_BLUR +#if defined(MODE_GAUSSIAN_BLUR) || defined(MODE_COPY_FROM) uv_interp = source_section.xy + uv_interp * source_section.zw; #endif } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 1d9ba623c4..e95d684763 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -607,8 +607,7 @@ layout(std140) uniform GlobalShaderUniformData { //ubo:1 vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; - /* Material Uniforms */ - +/* Material Uniforms */ #ifdef MATERIAL_UNIFORMS_USED /* clang-format off */ diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index e5080b39a3..b4e266d976 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -1538,7 +1538,7 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float)); } } - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { multimesh->data_cache_dirty_regions[i] = false; @@ -1549,7 +1549,7 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; #ifdef DEBUG_ENABLED - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug #endif if (!multimesh->data_cache_dirty_regions[region_index]) { @@ -1570,7 +1570,7 @@ void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { if (p_data) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { if (!multimesh->data_cache_dirty_regions[i]) { @@ -1917,7 +1917,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b multimesh->data_cache = multimesh->data_cache; { //clear dirty since nothing will be dirty anymore - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { multimesh->data_cache_dirty_regions[i] = false; } @@ -2044,8 +2044,8 @@ void MeshStorage::_update_dirty_multimeshes() { uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; if (multimesh->data_cache_used_dirty_regions) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, (int)MULTIMESH_DIRTY_REGION_SIZE); + uint32_t visible_region_count = visible_instances == 0 ? 0 : Math::division_round_up(visible_instances, (uint32_t)MULTIMESH_DIRTY_REGION_SIZE); GLint region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 4e34fbcf0a..5a59f6c772 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -766,7 +766,7 @@ void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<R ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6); ERR_FAIL_COND_MSG(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY, "Cubemap Arrays are not supported in the GL Compatibility backend."); - Ref<Image> image = p_layers[0]; + const Ref<Image> &image = p_layers[0]; { int valid_width = 0; int valid_height = 0; @@ -1475,7 +1475,7 @@ void TextureStorage::update_texture_atlas() { //generate atlas Vector<TextureAtlas::SortItem> itemsv; itemsv.resize(texture_atlas.textures.size()); - int base_size = 8; + uint32_t base_size = 8; int idx = 0; @@ -1488,7 +1488,7 @@ void TextureStorage::update_texture_atlas() { si.size.height = (src_tex->height / border) + 1; si.pixel_size = Size2i(src_tex->width, src_tex->height); - if (base_size < si.size.width) { + if (base_size < (uint32_t)si.size.width) { base_size = nearest_power_of_2_templated(si.size.width); } @@ -1519,7 +1519,7 @@ void TextureStorage::update_texture_atlas() { TextureAtlas::SortItem &si = items[i]; int best_idx = -1; int best_height = 0x7FFFFFFF; - for (int j = 0; j <= base_size - si.size.width; j++) { + for (uint32_t j = 0; j <= base_size - si.size.width; j++) { int height = 0; for (int k = 0; k < si.size.width; k++) { int h = v_offsets[k + j]; @@ -1550,7 +1550,7 @@ void TextureStorage::update_texture_atlas() { } } - if (max_height <= base_size * 2) { + if ((uint32_t)max_height <= base_size * 2) { atlas_height = max_height; break; //good ratio, break; } @@ -2647,7 +2647,10 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, rt->color); - GLES3::CopyEffects::get_singleton()->copy_screen(); + Rect2 normalized_region = region; + normalized_region.position = normalized_region.position / Size2(rt->size); + normalized_region.size = normalized_region.size / Size2(rt->size); + GLES3::CopyEffects::get_singleton()->copy_to_and_from_rect(normalized_region); if (p_gen_mipmaps) { GLES3::CopyEffects::get_singleton()->gaussian_blur(rt->backbuffer, rt->mipmap_count, region, rt->size); diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index cbcb54bc11..6f98f072dd 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -66,12 +66,14 @@ Ref<Image> ImageLoaderPNG::load_mem_png(const uint8_t *p_png, int p_size) { return img; } +Ref<Image> ImageLoaderPNG::unpack_mem_png(const uint8_t *p_png, int p_size) { + ERR_FAIL_COND_V(p_size < 4, Ref<Image>()); + ERR_FAIL_COND_V(p_png[0] != 'P' || p_png[1] != 'N' || p_png[2] != 'G' || p_png[3] != ' ', Ref<Image>()); + return load_mem_png(&p_png[4], p_size - 4); +} + Ref<Image> ImageLoaderPNG::lossless_unpack_png(const Vector<uint8_t> &p_data) { - const int len = p_data.size(); - ERR_FAIL_COND_V(len < 4, Ref<Image>()); - const uint8_t *r = p_data.ptr(); - ERR_FAIL_COND_V(r[0] != 'P' || r[1] != 'N' || r[2] != 'G' || r[3] != ' ', Ref<Image>()); - return load_mem_png(&r[4], len - 4); + return unpack_mem_png(p_data.ptr(), p_data.size()); } Vector<uint8_t> ImageLoaderPNG::lossless_pack_png(const Ref<Image> &p_image) { @@ -99,6 +101,7 @@ Vector<uint8_t> ImageLoaderPNG::lossless_pack_png(const Ref<Image> &p_image) { ImageLoaderPNG::ImageLoaderPNG() { Image::_png_mem_loader_func = load_mem_png; + Image::_png_mem_unpacker_func = unpack_mem_png; Image::png_unpacker = lossless_unpack_png; Image::png_packer = lossless_pack_png; } diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index d587672dd1..ecce9a405b 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -37,6 +37,7 @@ class ImageLoaderPNG : public ImageFormatLoader { private: static Vector<uint8_t> lossless_pack_png(const Ref<Image> &p_image); static Ref<Image> lossless_unpack_png(const Vector<uint8_t> &p_data); + static Ref<Image> unpack_mem_png(const uint8_t *p_png, int p_size); static Ref<Image> load_mem_png(const uint8_t *p_png, int p_size); public: diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index ca5a13799e..d1e4d207e7 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -228,6 +228,51 @@ uint8_t FileAccessUnix::get_8() const { return b; } +uint16_t FileAccessUnix::get_16() const { + ERR_FAIL_NULL_V_MSG(f, 0, "File must be opened before use."); + + uint16_t b = 0; + if (fread(&b, 1, 2, f) != 2) { + check_errors(); + } + + if (big_endian) { + b = BSWAP16(b); + } + + return b; +} + +uint32_t FileAccessUnix::get_32() const { + ERR_FAIL_NULL_V_MSG(f, 0, "File must be opened before use."); + + uint32_t b = 0; + if (fread(&b, 1, 4, f) != 4) { + check_errors(); + } + + if (big_endian) { + b = BSWAP32(b); + } + + return b; +} + +uint64_t FileAccessUnix::get_64() const { + ERR_FAIL_NULL_V_MSG(f, 0, "File must be opened before use."); + + uint64_t b = 0; + if (fread(&b, 1, 8, f) != 8) { + check_errors(); + } + + if (big_endian) { + b = BSWAP64(b); + } + + return b; +} + uint64_t FileAccessUnix::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); ERR_FAIL_NULL_V_MSG(f, -1, "File must be opened before use."); @@ -251,6 +296,36 @@ void FileAccessUnix::store_8(uint8_t p_dest) { ERR_FAIL_COND(fwrite(&p_dest, 1, 1, f) != 1); } +void FileAccessUnix::store_16(uint16_t p_dest) { + ERR_FAIL_NULL_MSG(f, "File must be opened before use."); + + if (big_endian) { + p_dest = BSWAP16(p_dest); + } + + ERR_FAIL_COND(fwrite(&p_dest, 1, 2, f) != 2); +} + +void FileAccessUnix::store_32(uint32_t p_dest) { + ERR_FAIL_NULL_MSG(f, "File must be opened before use."); + + if (big_endian) { + p_dest = BSWAP32(p_dest); + } + + ERR_FAIL_COND(fwrite(&p_dest, 1, 4, f) != 4); +} + +void FileAccessUnix::store_64(uint64_t p_dest) { + ERR_FAIL_NULL_MSG(f, "File must be opened before use."); + + if (big_endian) { + p_dest = BSWAP64(p_dest); + } + + ERR_FAIL_COND(fwrite(&p_dest, 1, 8, f) != 8); +} + void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_NULL_MSG(f, "File must be opened before use."); ERR_FAIL_COND(!p_src && p_length > 0); diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 2bfac27c4f..553fbcf355 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -68,12 +68,18 @@ public: virtual bool eof_reached() const override; ///< reading passed EOF virtual uint8_t get_8() const override; ///< get a byte + virtual uint16_t get_16() const override; + virtual uint32_t get_32() const override; + virtual uint64_t get_64() const override; virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; virtual Error get_error() const override; ///< get last error virtual void flush() override; virtual void store_8(uint8_t p_dest) override; ///< store a byte + virtual void store_16(uint16_t p_dest) override; + virtual void store_32(uint32_t p_dest) override; + virtual void store_64(uint64_t p_dest) override; virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes virtual bool file_exists(const String &p_path) override; ///< return true if a file exists diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 9a77930d75..8126f74332 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -153,7 +153,9 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) { } void OS_Unix::initialize_core() { +#ifdef THREADS_ENABLED init_thread_posix(); +#endif FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES); FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA); @@ -656,6 +658,8 @@ Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle path = get_executable_path().get_base_dir().path_join("../lib").path_join(p_path.get_file()); } + ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND); + p_library_handle = dlopen(path.utf8().get_data(), GODOT_DLOPEN_MODE); ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror())); @@ -751,12 +755,27 @@ String OS_Unix::get_executable_path() const { return OS::get_executable_path(); } return b; -#elif defined(__OpenBSD__) || defined(__NetBSD__) +#elif defined(__OpenBSD__) char resolved_path[MAXPATHLEN]; realpath(OS::get_executable_path().utf8().get_data(), resolved_path); return String(resolved_path); +#elif defined(__NetBSD__) + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; + char buf[MAXPATHLEN]; + size_t len = sizeof(buf); + if (sysctl(mib, 4, buf, &len, nullptr, 0) != 0) { + WARN_PRINT("Couldn't get executable path from sysctl"); + return OS::get_executable_path(); + } + + // NetBSD does not always return a normalized path. For example if argv[0] is "./a.out" then executable path is "/home/netbsd/./a.out". Normalize with realpath: + char resolved_path[MAXPATHLEN]; + + realpath(buf, resolved_path); + + return String(resolved_path); #elif defined(__FreeBSD__) int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; char buf[MAXPATHLEN]; diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub index 5e4bc986b8..a076c0ac54 100644 --- a/drivers/vulkan/SCsub +++ b/drivers/vulkan/SCsub @@ -2,8 +2,6 @@ Import("env") -env.Append(CPPDEFINES=["RD_ENABLED"]) - thirdparty_obj = [] thirdparty_dir = "#thirdparty/vulkan" thirdparty_volk_dir = "#thirdparty/volk" diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp index 911efa7755..8378e26666 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp @@ -733,6 +733,9 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create_shared_from_slice(Tex case TEXTURE_SLICE_2D_ARRAY: { image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; } break; + default: { + return TextureID(nullptr); + } } image_view_create_info.format = RD_TO_VK_FORMAT[p_view.format]; image_view_create_info.components.r = (VkComponentSwizzle)p_view.swizzle_r; @@ -805,8 +808,11 @@ void RenderingDeviceDriverVulkan::texture_get_copyable_layout(TextureID p_textur h = MAX(1u, h >> 1); d = MAX(1u, d >> 1); } - r_layout->size = get_image_format_required_size(tex_info->rd_format, w, h, d, 1); - r_layout->row_pitch = r_layout->size / (h * d); + uint32_t bw = 0, bh = 0; + get_compressed_image_format_block_dimensions(tex_info->rd_format, bw, bh); + uint32_t sbw = 0, sbh = 0; + r_layout->size = get_image_format_required_size(tex_info->rd_format, w, h, d, 1, &sbw, &sbh); + r_layout->row_pitch = r_layout->size / ((sbh / bh) * d); r_layout->depth_pitch = r_layout->size / d; r_layout->layer_pitch = r_layout->size / tex_info->vk_create_info.arrayLayers; } @@ -1172,7 +1178,7 @@ bool RenderingDeviceDriverVulkan::command_buffer_begin_secondary(CommandBufferID VkCommandBufferBeginInfo cmd_buf_begin_info = {}; cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmd_buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; + cmd_buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; cmd_buf_begin_info.pInheritanceInfo = &inheritance_info; VkResult err = vkBeginCommandBuffer((VkCommandBuffer)p_cmd_buffer.id, &cmd_buf_begin_info); @@ -1557,11 +1563,9 @@ RDD::ShaderID RenderingDeviceDriverVulkan::shader_create_from_bytecode(const Vec read_offset += sizeof(ShaderBinary::SpecializationConstant); } - struct Stage { - ShaderStage type = SHADER_STAGE_MAX; - Vector<uint8_t> spirv; - }; - Vector<Stage> stages; + Vector<Vector<uint8_t>> stages_spirv; + stages_spirv.resize(binary_data.stage_count); + r_shader_desc.stages.resize(binary_data.stage_count); for (uint32_t i = 0; i < binary_data.stage_count; i++) { ERR_FAIL_COND_V(read_offset + sizeof(uint32_t) * 3 >= binsize, ShaderID()); @@ -1587,17 +1591,14 @@ RDD::ShaderID RenderingDeviceDriverVulkan::shader_create_from_bytecode(const Vec src_smolv = binptr + read_offset; } - Vector<uint8_t> spirv; + Vector<uint8_t> &spirv = stages_spirv.ptrw()[i]; uint32_t spirv_size = smolv::GetDecodedBufferSize(src_smolv, smolv_size); spirv.resize(spirv_size); if (!smolv::Decode(src_smolv, smolv_size, spirv.ptrw(), spirv_size)) { ERR_FAIL_V_MSG(ShaderID(), "Malformed smolv input uncompressing shader stage:" + String(SHADER_STAGE_NAMES[stage])); } - Stage stage_entry; - stage_entry.type = ShaderStage(stage); - stage_entry.spirv = spirv; - stages.push_back(stage_entry); + r_shader_desc.stages.set(i, ShaderStage(stage)); if (buf_size % 4 != 0) { buf_size += 4 - (buf_size % 4); @@ -1614,22 +1615,22 @@ RDD::ShaderID RenderingDeviceDriverVulkan::shader_create_from_bytecode(const Vec String error_text; - for (int i = 0; i < stages.size(); i++) { + for (int i = 0; i < r_shader_desc.stages.size(); i++) { VkShaderModuleCreateInfo shader_module_create_info = {}; shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_module_create_info.codeSize = stages[i].spirv.size(); - shader_module_create_info.pCode = (const uint32_t *)stages[i].spirv.ptr(); + shader_module_create_info.codeSize = stages_spirv[i].size(); + shader_module_create_info.pCode = (const uint32_t *)stages_spirv[i].ptr(); VkShaderModule vk_module = VK_NULL_HANDLE; VkResult res = vkCreateShaderModule(vk_device, &shader_module_create_info, nullptr, &vk_module); if (res) { - error_text = "Error (" + itos(res) + ") creating shader module for stage: " + String(SHADER_STAGE_NAMES[stages[i].type]); + error_text = "Error (" + itos(res) + ") creating shader module for stage: " + String(SHADER_STAGE_NAMES[r_shader_desc.stages[i]]); break; } VkPipelineShaderStageCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - create_info.stage = RD_STAGE_TO_VK_SHADER_STAGE_BITS[stages[i].type]; + create_info.stage = RD_STAGE_TO_VK_SHADER_STAGE_BITS[r_shader_desc.stages[i]]; create_info.module = vk_module; create_info.pName = "main"; @@ -2920,7 +2921,7 @@ RDD::PipelineID RenderingDeviceDriverVulkan::render_pipeline_create( VkPipeline vk_pipeline = VK_NULL_HANDLE; VkResult err = vkCreateGraphicsPipelines(vk_device, pipelines_cache.vk_cache, 1, &pipeline_create_info, nullptr, &vk_pipeline); - ERR_FAIL_COND_V_MSG(err, PipelineID(), "vkCreateComputePipelines failed with error " + itos(err) + "."); + ERR_FAIL_COND_V_MSG(err, PipelineID(), "vkCreateGraphicsPipelines failed with error " + itos(err) + "."); return PipelineID(vk_pipeline); } @@ -3054,6 +3055,26 @@ void RenderingDeviceDriverVulkan::command_timestamp_write(CommandBufferID p_cmd_ } /****************/ +/**** LABELS ****/ +/****************/ + +void RenderingDeviceDriverVulkan::command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) { + VkDebugUtilsLabelEXT label; + label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + label.pNext = nullptr; + label.pLabelName = p_label_name; + label.color[0] = p_color[0]; + label.color[1] = p_color[1]; + label.color[2] = p_color[2]; + label.color[3] = p_color[3]; + vkCmdBeginDebugUtilsLabelEXT((VkCommandBuffer)p_cmd_buffer.id, &label); +} + +void RenderingDeviceDriverVulkan::command_end_label(CommandBufferID p_cmd_buffer) { + vkCmdEndDebugUtilsLabelEXT((VkCommandBuffer)p_cmd_buffer.id); +} + +/****************/ /**** SCREEN ****/ /****************/ diff --git a/drivers/vulkan/rendering_device_driver_vulkan.h b/drivers/vulkan/rendering_device_driver_vulkan.h index 6d8f6fd0e0..1edee6b76e 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.h +++ b/drivers/vulkan/rendering_device_driver_vulkan.h @@ -433,6 +433,13 @@ public: virtual void command_timestamp_write(CommandBufferID p_cmd_buffer, QueryPoolID p_pool_id, uint32_t p_index) override final; /****************/ + /**** LABELS ****/ + /****************/ + + virtual void command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) override final; + virtual void command_end_label(CommandBufferID p_cmd_buffer) override final; + + /****************/ /**** SCREEN ****/ /****************/ diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 1b1d4fa50f..7db2a9cd66 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -2395,9 +2395,11 @@ void VulkanContext::append_command_buffer(RDD::CommandBufferID p_command_buffer) command_buffer_count++; } -void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { +void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending, bool p_sync) { // Ensure everything else pending is executed. - vkDeviceWaitIdle(device); + if (p_sync) { + vkDeviceWaitIdle(device); + } // Flush the pending setup buffer. @@ -2440,7 +2442,9 @@ void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { ERR_FAIL_COND(err); } - vkDeviceWaitIdle(device); + if (p_sync) { + vkDeviceWaitIdle(device); + } } Error VulkanContext::prepare_buffers(RDD::CommandBufferID p_command_buffer) { @@ -2504,7 +2508,7 @@ Error VulkanContext::swap_buffers() { return OK; } - // print_line("swapbuffers?"); + //print_line("swap_buffers"); VkResult err; #if 0 @@ -2818,46 +2822,6 @@ void VulkanContext::local_device_free(RID p_local_device) { local_device_owner.free(p_local_device); } -void VulkanContext::command_begin_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) { - if (!is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { - return; - } - - CharString cs = p_label_name.utf8(); - VkDebugUtilsLabelEXT label; - label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; - label.pNext = nullptr; - label.pLabelName = cs.get_data(); - label.color[0] = p_color[0]; - label.color[1] = p_color[1]; - label.color[2] = p_color[2]; - label.color[3] = p_color[3]; - CmdBeginDebugUtilsLabelEXT((VkCommandBuffer)p_command_buffer.id, &label); -} - -void VulkanContext::command_insert_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) { - if (!is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { - return; - } - CharString cs = p_label_name.utf8(); - VkDebugUtilsLabelEXT label; - label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; - label.pNext = nullptr; - label.pLabelName = cs.get_data(); - label.color[0] = p_color[0]; - label.color[1] = p_color[1]; - label.color[2] = p_color[2]; - label.color[3] = p_color[3]; - CmdInsertDebugUtilsLabelEXT((VkCommandBuffer)p_command_buffer.id, &label); -} - -void VulkanContext::command_end_label(RDD::CommandBufferID p_command_buffer) { - if (!is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { - return; - } - CmdEndDebugUtilsLabelEXT((VkCommandBuffer)p_command_buffer.id); -} - void VulkanContext::set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name) { if (!is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { return; @@ -2913,6 +2877,10 @@ RenderingDeviceDriver *VulkanContext::get_driver(RID p_local_device) { } } +bool VulkanContext::is_debug_utils_enabled() const { + return is_instance_extension_enabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); +} + VulkanContext::VulkanContext() { command_buffer_queue.resize(1); // First one is always the setup command. command_buffer_queue[0] = nullptr; diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index ce1299a559..cbb6cf326f 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -321,15 +321,12 @@ public: virtual void set_setup_buffer(RDD::CommandBufferID p_command_buffer) override final; virtual void append_command_buffer(RDD::CommandBufferID p_command_buffer) override final; void resize_notify(); - virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false) override final; + virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false, bool p_sync = true) override final; virtual Error prepare_buffers(RDD::CommandBufferID p_command_buffer) override final; virtual void postpare_buffers(RDD::CommandBufferID p_command_buffer) override final; virtual Error swap_buffers() override final; virtual Error initialize() override final; - virtual void command_begin_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) override final; - virtual void command_insert_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) override final; - virtual void command_end_label(RDD::CommandBufferID p_command_buffer) override final; void set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name); virtual String get_device_vendor_name() const override final; @@ -342,6 +339,7 @@ public: virtual DisplayServer::VSyncMode get_vsync_mode(DisplayServer::WindowID p_window = 0) const override final; virtual RenderingDeviceDriver *get_driver(RID p_local_device = RID()) override final; + virtual bool is_debug_utils_enabled() const override final; VulkanContext(); virtual ~VulkanContext(); diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index e39373e7a0..64f2d1f203 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -557,13 +557,11 @@ Error AudioDriverWASAPI::init() { target_latency_ms = Engine::get_singleton()->get_audio_output_latency(); - Error err = init_output_device(); - if (err != OK) { - ERR_PRINT("WASAPI: init_output_device error"); - } - exit_thread.clear(); + Error err = init_output_device(); + ERR_FAIL_COND_V_MSG(err != OK, err, "WASAPI: init_output_device error."); + thread.start(thread_func, this); return OK; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 9d21073f19..1b69f5da2c 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -284,6 +284,72 @@ uint8_t FileAccessWindows::get_8() const { return b; } +uint16_t FileAccessWindows::get_16() const { + ERR_FAIL_NULL_V(f, 0); + + if (flags == READ_WRITE || flags == WRITE_READ) { + if (prev_op == WRITE) { + fflush(f); + } + prev_op = READ; + } + + uint16_t b = 0; + if (fread(&b, 1, 2, f) != 2) { + check_errors(); + } + + if (big_endian) { + b = BSWAP16(b); + } + + return b; +} + +uint32_t FileAccessWindows::get_32() const { + ERR_FAIL_NULL_V(f, 0); + + if (flags == READ_WRITE || flags == WRITE_READ) { + if (prev_op == WRITE) { + fflush(f); + } + prev_op = READ; + } + + uint32_t b = 0; + if (fread(&b, 1, 4, f) != 4) { + check_errors(); + } + + if (big_endian) { + b = BSWAP32(b); + } + + return b; +} + +uint64_t FileAccessWindows::get_64() const { + ERR_FAIL_NULL_V(f, 0); + + if (flags == READ_WRITE || flags == WRITE_READ) { + if (prev_op == WRITE) { + fflush(f); + } + prev_op = READ; + } + + uint64_t b = 0; + if (fread(&b, 1, 8, f) != 8) { + check_errors(); + } + + if (big_endian) { + b = BSWAP64(b); + } + + return b; +} + uint64_t FileAccessWindows::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); ERR_FAIL_NULL_V(f, -1); @@ -326,6 +392,63 @@ void FileAccessWindows::store_8(uint8_t p_dest) { fwrite(&p_dest, 1, 1, f); } +void FileAccessWindows::store_16(uint16_t p_dest) { + ERR_FAIL_NULL(f); + + if (flags == READ_WRITE || flags == WRITE_READ) { + if (prev_op == READ) { + if (last_error != ERR_FILE_EOF) { + fseek(f, 0, SEEK_CUR); + } + } + prev_op = WRITE; + } + + if (big_endian) { + p_dest = BSWAP16(p_dest); + } + + fwrite(&p_dest, 1, 2, f); +} + +void FileAccessWindows::store_32(uint32_t p_dest) { + ERR_FAIL_NULL(f); + + if (flags == READ_WRITE || flags == WRITE_READ) { + if (prev_op == READ) { + if (last_error != ERR_FILE_EOF) { + fseek(f, 0, SEEK_CUR); + } + } + prev_op = WRITE; + } + + if (big_endian) { + p_dest = BSWAP32(p_dest); + } + + fwrite(&p_dest, 1, 4, f); +} + +void FileAccessWindows::store_64(uint64_t p_dest) { + ERR_FAIL_NULL(f); + + if (flags == READ_WRITE || flags == WRITE_READ) { + if (prev_op == READ) { + if (last_error != ERR_FILE_EOF) { + fseek(f, 0, SEEK_CUR); + } + } + prev_op = WRITE; + } + + if (big_endian) { + p_dest = BSWAP64(p_dest); + } + + fwrite(&p_dest, 1, 8, f); +} + void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_NULL(f); ERR_FAIL_COND(!p_src && p_length > 0); diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 73143009fc..dabb174cb2 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -69,12 +69,18 @@ public: virtual bool eof_reached() const override; ///< reading passed EOF virtual uint8_t get_8() const override; ///< get a byte + virtual uint16_t get_16() const override; + virtual uint32_t get_32() const override; + virtual uint64_t get_64() const override; virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; virtual Error get_error() const override; ///< get last error virtual void flush() override; virtual void store_8(uint8_t p_dest) override; ///< store a byte + virtual void store_16(uint16_t p_dest) override; + virtual void store_32(uint32_t p_dest) override; + virtual void store_64(uint64_t p_dest) override; virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes virtual bool file_exists(const String &p_name) override; ///< return true if a file exists diff --git a/editor/SCsub b/editor/SCsub index b1a47dae45..5b36bca81a 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -104,19 +104,6 @@ if env.editor_build: env.Run(editor_builders.make_doc_translations_header, "Generating translations header."), ) - # Fonts - flist = glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.ttf") - flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.otf")) - flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff")) - flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff2")) - flist.sort() - env.Depends("#editor/builtin_fonts.gen.h", flist) - env.CommandNoCache( - "#editor/builtin_fonts.gen.h", - flist, - env.Run(editor_builders.make_fonts_header, "Generating builtin fonts header."), - ) - env.add_source_files(env.editor_sources, "*.cpp") env.add_source_files(env.editor_sources, "register_exporters.gen.cpp") @@ -126,6 +113,7 @@ if env.editor_build: SConscript("icons/SCsub") SConscript("import/SCsub") SConscript("plugins/SCsub") + SConscript("themes/SCsub") lib = env.add_library("editor", env.editor_sources) env.Prepend(LIBS=[lib]) diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index ab923f99fe..5154d2e0e0 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -30,12 +30,13 @@ #include "editor/action_map_editor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/event_listener_line_edit.h" #include "editor/input_event_configuration_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_button.h" +#include "scene/gui/separator.h" #include "scene/gui/tree.h" #include "scene/scene_string_names.h" @@ -357,6 +358,7 @@ void ActionMapEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { action_list_search->set_right_icon(get_editor_theme_icon(SNAME("Search"))); + add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); if (!actions_cache.is_empty()) { update_action_list(); } @@ -532,7 +534,7 @@ ActionMapEditor::ActionMapEditor() { action_list_search = memnew(LineEdit); action_list_search->set_h_size_flags(Control::SIZE_EXPAND_FILL); - action_list_search->set_placeholder(TTR("Filter by name...")); + action_list_search->set_placeholder(TTR("Filter by Name")); action_list_search->set_clear_button_enabled(true); action_list_search->connect("text_changed", callable_mp(this, &ActionMapEditor::_search_term_updated)); top_hbox->add_child(action_list_search); @@ -570,6 +572,8 @@ ActionMapEditor::ActionMapEditor() { // Disable the button and set its tooltip. _add_edit_text_changed(add_edit->get_text()); + add_hbox->add_child(memnew(VSeparator)); + show_builtin_actions_checkbutton = memnew(CheckButton); show_builtin_actions_checkbutton->set_text(TTR("Show Built-in Actions")); show_builtin_actions_checkbutton->connect("toggled", callable_mp(this, &ActionMapEditor::set_show_builtin_actions)); diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 08306256f1..f29b851673 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -31,10 +31,10 @@ #include "animation_bezier_editor.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/view_panner.h" #include "scene/resources/text_line.h" @@ -334,7 +334,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { } } - Color dc = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)); + Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)); Ref<Texture2D> remove = get_editor_theme_icon(SNAME("Remove")); float remove_hpos = limit - hsep - remove->get_width(); @@ -908,7 +908,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { if (Math::is_finite(minimum_time) && Math::is_finite(maximum_time) && maximum_time - minimum_time > CMP_EPSILON) { timeline->get_zoom()->set_value(zoom_value); - timeline->call_deferred("set_value", minimum_time); + callable_mp((Range *)timeline, &Range::set_value).call_deferred(minimum_time); } if (Math::is_finite(minimum_value) && Math::is_finite(maximum_value)) { @@ -1520,7 +1520,7 @@ void AnimationBezierTrackEdit::_zoom_callback(float p_zoom_factor, Vector2 p_ori // Alternate zoom (doesn't affect timeline). timeline_v_zoom = CLAMP(timeline_v_zoom * p_zoom_factor, 0.000001, 100000); } else { - timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / p_zoom_factor); + timeline->_zoom_callback(p_zoom_factor, p_origin, p_event); } timeline_v_scroll = timeline_v_scroll + (p_origin.y - get_size().y / 2.0) * (timeline_v_zoom - v_zoom_orig); queue_redraw(); @@ -1688,6 +1688,7 @@ void AnimationBezierTrackEdit::_bind_methods() { AnimationBezierTrackEdit::AnimationBezierTrackEdit() { panner.instantiate(); panner->set_callbacks(callable_mp(this, &AnimationBezierTrackEdit::_pan_callback), callable_mp(this, &AnimationBezierTrackEdit::_zoom_callback)); + panner->set_scroll_zoom_factor(AnimationTimelineEdit::SCROLL_ZOOM_FACTOR); play_position = memnew(Control); play_position->set_mouse_filter(MOUSE_FILTER_PASS); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 8268cf10ae..3c704b3473 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -35,7 +35,6 @@ #include "core/input/input.h" #include "editor/animation_bezier_editor.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" @@ -43,6 +42,7 @@ #include "editor/gui/scene_tree_editor.h" #include "editor/inspector_dock.h" #include "editor/plugins/animation_player_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/animation/animation_player.h" #include "scene/animation/tween.h" #include "scene/gui/check_box.h" @@ -1247,6 +1247,58 @@ void AnimationMultiTrackKeyEdit::set_use_fps(bool p_enable) { } void AnimationTimelineEdit::_zoom_changed(double) { + double zoom_pivot = 0; // Point on timeline to stay fixed. + double zoom_pivot_delta = 0; // Delta seconds from left-most point on timeline to zoom pivot. + + int timeline_width_pixels = get_size().width - get_buttons_width() - get_name_limit(); + double timeline_width_seconds = timeline_width_pixels / last_zoom_scale; // Length (in seconds) of visible part of timeline before zoom. + double updated_timeline_width_seconds = timeline_width_pixels / get_zoom_scale(); // Length after zoom. + double updated_timeline_half_width = updated_timeline_width_seconds / 2.0; + bool zooming = updated_timeline_width_seconds < timeline_width_seconds; + + double timeline_left = get_value(); + double timeline_right = timeline_left + timeline_width_seconds; + double timeline_center = timeline_left + timeline_width_seconds / 2.0; + + if (zoom_callback_occured) { // Zooming with scroll wheel will focus on the position of the mouse. + double zoom_scroll_origin_norm = (zoom_scroll_origin.x - get_name_limit()) / timeline_width_pixels; + zoom_scroll_origin_norm = MAX(zoom_scroll_origin_norm, 0); + zoom_pivot = timeline_left + timeline_width_seconds * zoom_scroll_origin_norm; + zoom_pivot_delta = updated_timeline_width_seconds * zoom_scroll_origin_norm; + zoom_callback_occured = false; + } else { // Zooming with slider will depend on the current play position. + // If the play position is not in range, or exactly in the center, zoom in on the center. + if (get_play_position() < timeline_left || get_play_position() > timeline_left + timeline_width_seconds || get_play_position() == timeline_center) { + zoom_pivot = timeline_center; + zoom_pivot_delta = updated_timeline_half_width; + } + // Zoom from right if play position is right of center, + // and shrink from right if play position is left of center. + else if ((get_play_position() > timeline_center) == zooming) { + // If play position crosses to other side of center, center it. + bool center_passed = (get_play_position() < timeline_right - updated_timeline_half_width) == zooming; + zoom_pivot = center_passed ? get_play_position() : timeline_right; + double center_offset = CMP_EPSILON * (zooming ? 1 : -1); // Small offset to prevent crossover. + zoom_pivot_delta = center_passed ? updated_timeline_half_width + center_offset : updated_timeline_width_seconds; + } + // Zoom from left if play position is left of center, + // and shrink from left if play position is right of center. + else if ((get_play_position() <= timeline_center) == zooming) { + // If play position crosses to other side of center, center it. + bool center_passed = (get_play_position() > timeline_left + updated_timeline_half_width) == zooming; + zoom_pivot = center_passed ? get_play_position() : timeline_left; + double center_offset = CMP_EPSILON * (zooming ? -1 : 1); // Small offset to prevent crossover. + zoom_pivot_delta = center_passed ? updated_timeline_half_width + center_offset : 0; + } + } + + double hscroll_pos = zoom_pivot - zoom_pivot_delta; + hscroll_pos = CLAMP(hscroll_pos, hscroll->get_min(), hscroll->get_max()); + + hscroll->set_value(hscroll_pos); + hscroll_on_zoom_buffer = hscroll_pos; // In case of page update. + last_zoom_scale = get_zoom_scale(); + queue_redraw(); play_position->queue_redraw(); emit_signal(SNAME("zoom_changed")); @@ -1428,6 +1480,11 @@ void AnimationTimelineEdit::_notification(int p_what) { set_page(zoomw / scale); + if (hscroll->is_visible() && hscroll_on_zoom_buffer >= 0) { + hscroll->set_value(hscroll_on_zoom_buffer); + hscroll_on_zoom_buffer = -1.0; + } + int end_px = (l - get_value()) * scale; int begin_px = -get_value() * scale; Color notimecol = get_theme_color(SNAME("dark_color_2"), EditorStringName(Editor)); @@ -1733,7 +1790,9 @@ void AnimationTimelineEdit::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> void AnimationTimelineEdit::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) { double current_zoom_value = get_zoom()->get_value(); - get_zoom()->set_value(MAX(0.01, current_zoom_value * p_zoom_factor)); + zoom_scroll_origin = p_origin; + zoom_callback_occured = true; + get_zoom()->set_value(MAX(0.01, current_zoom_value - (1.0 - p_zoom_factor))); } void AnimationTimelineEdit::set_use_fps(bool p_use_fps) { @@ -1809,6 +1868,7 @@ AnimationTimelineEdit::AnimationTimelineEdit() { len_hb->hide(); panner.instantiate(); + panner->set_scroll_zoom_factor(SCROLL_ZOOM_FACTOR); panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback)); panner->set_pan_axis(ViewPanner::PAN_AXIS_HORIZONTAL); @@ -1861,7 +1921,7 @@ void AnimationTrackEdit::_notification(int p_what) { Color linecolor = color; linecolor.a = 0.2; - Color dc = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)); + Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)); // NAMES AND ICONS // @@ -2718,9 +2778,9 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { PropertyInfo prop_info; ClassDB::get_property_info(nd->get_class(), prop, &prop_info); #ifdef DISABLE_DEPRECATED - bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.find("radians_as_degrees") != -1; + bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.contains("radians_as_degrees"); #else - bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.find("radians") != -1; + bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.contains("radians"); #endif // DISABLE_DEPRECATED if (is_angle) { menu->add_icon_item(get_editor_theme_icon(SNAME("InterpLinearAngle")), TTR("Linear Angle"), MENU_INTERPOLATION_LINEAR_ANGLE); @@ -4190,27 +4250,11 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD bool create_reset_track = p_reset_wanted && track_type_is_resettable(p_id.type); Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE; + Animation::InterpolationType interp_type = Animation::INTERPOLATION_LINEAR; + bool loop_wrap = true; if (create_normal_track || create_reset_track) { if (p_id.type == Animation::TYPE_VALUE || p_id.type == Animation::TYPE_BEZIER) { - // Hack. - NodePath np; - animation->add_track(p_id.type); - animation->track_set_path(animation->get_track_count() - 1, p_id.path); - PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np); - animation->remove_track(animation->get_track_count() - 1); // Hack. - - if (h.type == Variant::FLOAT || - h.type == Variant::VECTOR2 || - h.type == Variant::RECT2 || - h.type == Variant::VECTOR3 || - h.type == Variant::AABB || - h.type == Variant::QUATERNION || - h.type == Variant::COLOR || - h.type == Variant::PLANE || - h.type == Variant::TRANSFORM2D || - h.type == Variant::TRANSFORM3D) { - update_mode = Animation::UPDATE_CONTINUOUS; - } + _fetch_value_track_options(p_id.path, &update_mode, &interp_type, &loop_wrap); } } @@ -4237,6 +4281,8 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD undo_redo->add_do_method(animation.ptr(), "add_track", p_id.type); undo_redo->add_do_method(animation.ptr(), "track_set_path", p_id.track_idx, p_id.path); + undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", p_id.track_idx, interp_type); + undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", p_id.track_idx, loop_wrap); if (p_id.type == Animation::TYPE_VALUE) { undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", p_id.track_idx, update_mode); } @@ -4567,7 +4613,7 @@ void AnimationTrackEditor::_animation_changed() { } animation_changing_awaiting_update = true; - call_deferred(SNAME("_animation_update")); + callable_mp(this, &AnimationTrackEditor::_animation_update).call_deferred(); } void AnimationTrackEditor::_snap_mode_changed(int p_mode) { @@ -4824,36 +4870,82 @@ void AnimationTrackEditor::_add_track(int p_type) { pick_track->get_filter_line_edit()->grab_focus(); } +void AnimationTrackEditor::_fetch_value_track_options(const NodePath &p_path, Animation::UpdateMode *r_update_mode, Animation::InterpolationType *r_interpolation_type, bool *r_loop_wrap) { + AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player(); + if (player->has_animation(SceneStringNames::get_singleton()->RESET)) { + Ref<Animation> reset_anim = player->get_animation(SceneStringNames::get_singleton()->RESET); + int rt = reset_anim->find_track(p_path, Animation::TrackType::TYPE_VALUE); + if (rt >= 0) { + *r_update_mode = reset_anim->value_track_get_update_mode(rt); + *r_interpolation_type = reset_anim->track_get_interpolation_type(rt); + *r_loop_wrap = reset_anim->track_get_interpolation_loop_wrap(rt); + return; + } + rt = reset_anim->find_track(p_path, Animation::TrackType::TYPE_BEZIER); + if (rt >= 0) { + *r_interpolation_type = reset_anim->track_get_interpolation_type(rt); + *r_loop_wrap = reset_anim->track_get_interpolation_loop_wrap(rt); + return; + } + } + + // Hack. + NodePath np; + animation->add_track(Animation::TYPE_VALUE); + animation->track_set_path(animation->get_track_count() - 1, p_path); + PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np); + animation->remove_track(animation->get_track_count() - 1); // Hack. + switch (h.type) { + case Variant::FLOAT: { +#ifdef DISABLE_DEPRECATED + bool is_angle = h.type == Variant::FLOAT && h.hint_string.contains("radians_as_degrees"); +#else + bool is_angle = h.type == Variant::FLOAT && h.hint_string.contains("radians"); +#endif // DISABLE_DEPRECATED + if (is_angle) { + *r_interpolation_type = Animation::INTERPOLATION_LINEAR_ANGLE; + } + [[fallthrough]]; + } + case Variant::VECTOR2: + case Variant::RECT2: + case Variant::VECTOR3: + case Variant::TRANSFORM2D: + case Variant::VECTOR4: + case Variant::PLANE: + case Variant::QUATERNION: + case Variant::AABB: + case Variant::BASIS: + case Variant::TRANSFORM3D: + case Variant::PROJECTION: + case Variant::COLOR: + case Variant::PACKED_FLOAT32_ARRAY: + case Variant::PACKED_FLOAT64_ARRAY: + case Variant::PACKED_VECTOR2_ARRAY: + case Variant::PACKED_VECTOR3_ARRAY: + case Variant::PACKED_COLOR_ARRAY: { + *r_update_mode = Animation::UPDATE_CONTINUOUS; + } break; + default: { + } + } +} + void AnimationTrackEditor::_new_track_property_selected(String p_name) { String full_path = String(adding_track_path) + ":" + p_name; EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - if (adding_track_type == Animation::TYPE_VALUE) { - Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE; - { - // Hack. - NodePath np; - animation->add_track(Animation::TYPE_VALUE); - animation->track_set_path(animation->get_track_count() - 1, full_path); - PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np); - animation->remove_track(animation->get_track_count() - 1); // Hack. - if (h.type == Variant::FLOAT || - h.type == Variant::VECTOR2 || - h.type == Variant::RECT2 || - h.type == Variant::VECTOR3 || - h.type == Variant::AABB || - h.type == Variant::QUATERNION || - h.type == Variant::COLOR || - h.type == Variant::PLANE || - h.type == Variant::TRANSFORM2D || - h.type == Variant::TRANSFORM3D) { - update_mode = Animation::UPDATE_CONTINUOUS; - } - } + Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE; + Animation::InterpolationType interp_type = Animation::INTERPOLATION_LINEAR; + bool loop_wrap = true; + _fetch_value_track_options(full_path, &update_mode, &interp_type, &loop_wrap); + if (adding_track_type == Animation::TYPE_VALUE) { undo_redo->create_action(TTR("Add Track")); undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type); undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), full_path); + undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", animation->get_track_count(), interp_type); + undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", animation->get_track_count(), loop_wrap); undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", animation->get_track_count(), update_mode); undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count()); undo_redo->commit_action(); @@ -4877,8 +4969,11 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) { undo_redo->create_action(TTR("Add Bezier Track")); int base_track = animation->get_track_count(); for (int i = 0; i < subindices.size(); i++) { + int track_idx = base_track + i; undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type); - undo_redo->add_do_method(animation.ptr(), "track_set_path", base_track + i, full_path + subindices[i]); + undo_redo->add_do_method(animation.ptr(), "track_set_path", track_idx, full_path + subindices[i]); + undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", track_idx, interp_type); + undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", track_idx, loop_wrap); undo_redo->add_undo_method(animation.ptr(), "remove_track", base_track); } undo_redo->commit_action(); @@ -5458,8 +5553,7 @@ void AnimationTrackEditor::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p } void AnimationTrackEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) { - double current_zoom_value = timeline->get_zoom()->get_value(); - timeline->get_zoom()->set_value(MAX(0.01, current_zoom_value * p_zoom_factor)); + timeline->_zoom_callback(p_zoom_factor, p_origin, p_event); } void AnimationTrackEditor::_cancel_bezier_edit() { @@ -6038,6 +6132,15 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { existing_idx = reset->track_find_key(dst_track, 0, Animation::FIND_MODE_APPROX); } + if (animation->track_get_type(sk.track) == Animation::TYPE_VALUE) { + undo_redo->add_do_method(reset.ptr(), "value_track_set_update_mode", dst_track, animation->value_track_get_update_mode(sk.track)); + } + if (animation->track_get_type(sk.track) == Animation::TYPE_AUDIO) { + undo_redo->add_do_method(reset.ptr(), "audio_track_set_use_blend", dst_track, animation->audio_track_is_use_blend(sk.track)); + } + undo_redo->add_do_method(reset.ptr(), "track_set_interpolation_type", dst_track, animation->track_get_interpolation_type(sk.track)); + undo_redo->add_do_method(reset.ptr(), "track_set_interpolation_loop_wrap", dst_track, animation->track_get_interpolation_loop_wrap(sk.track)); + undo_redo->add_do_method(reset.ptr(), "track_insert_key", dst_track, 0, animation->track_get_key_value(sk.track, sk.key), animation->track_get_key_transition(sk.track, sk.key)); undo_redo->add_undo_method(reset.ptr(), "track_remove_key_at_time", dst_track, 0); @@ -6375,7 +6478,6 @@ void AnimationTrackEditor::_select_all_tracks_for_copy() { } void AnimationTrackEditor::_bind_methods() { - ClassDB::bind_method("_animation_update", &AnimationTrackEditor::_animation_update); ClassDB::bind_method("_track_grab_focus", &AnimationTrackEditor::_track_grab_focus); ClassDB::bind_method("_redraw_tracks", &AnimationTrackEditor::_redraw_tracks); ClassDB::bind_method("_clear_selection_for_anim", &AnimationTrackEditor::_clear_selection_for_anim); @@ -6489,6 +6591,7 @@ AnimationTrackEditor::AnimationTrackEditor() { timeline->connect("length_changed", callable_mp(this, &AnimationTrackEditor::_update_length)); panner.instantiate(); + panner->set_scroll_zoom_factor(AnimationTimelineEdit::SCROLL_ZOOM_FACTOR); panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback)); scroll = memnew(ScrollContainer); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 4b9849b26c..b5242e2f67 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -131,6 +131,11 @@ protected: class AnimationTimelineEdit : public Range { GDCLASS(AnimationTimelineEdit, Range); + friend class AnimationBezierTrackEdit; + friend class AnimationTrackEditor; + + static constexpr float SCROLL_ZOOM_FACTOR = 1.02f; // Zoom factor per mouse scroll in the animation editor. The closer to 1.0, the finer the control. + Ref<Animation> animation; bool read_only = false; @@ -167,6 +172,11 @@ class AnimationTimelineEdit : public Range { bool dragging_hsize = false; float dragging_hsize_from = 0.0f; float dragging_hsize_at = 0.0f; + double last_zoom_scale = 1.0; + double hscroll_on_zoom_buffer = -1.0; + + Vector2 zoom_scroll_origin; + bool zoom_callback_occured = false; virtual void gui_input(const Ref<InputEvent> &p_event) override; void _track_added(int p_track); @@ -481,6 +491,8 @@ class AnimationTrackEditor : public VBoxContainer { void _insert_key_from_track(float p_ofs, int p_track); void _add_method_key(const String &p_method); + void _fetch_value_track_options(const NodePath &p_path, Animation::UpdateMode *r_update_mode, Animation::InterpolationType *r_interpolation_type, bool *r_loop_wrap); + void _clear_selection_for_anim(const Ref<Animation> &p_anim); void _select_at_anim(const Ref<Animation> &p_anim, int p_track, float p_pos); diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index 390b722b7b..7a53f4dded 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -32,9 +32,9 @@ #include "editor/audio_stream_preview.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/animated_sprite_2d.h" #include "scene/2d/sprite_2d.h" #include "scene/3d/sprite_3d.h" diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index c1935b4844..0b9289ff06 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -158,7 +158,7 @@ void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) { } frames_todo -= to_read; - singleton->call_deferred(SNAME("_update_emit"), preview->id); + callable_mp(singleton, &AudioStreamPreviewGenerator::_update_emit).call_deferred(preview->id); } preview->preview->version++; @@ -216,7 +216,6 @@ Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref< } void AudioStreamPreviewGenerator::_bind_methods() { - ClassDB::bind_method("_update_emit", &AudioStreamPreviewGenerator::_update_emit); ClassDB::bind_method(D_METHOD("generate_preview", "stream"), &AudioStreamPreviewGenerator::generate_preview); ADD_SIGNAL(MethodInfo("preview_updated", PropertyInfo(Variant::INT, "obj_id"))); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 9a10766900..76d0d40110 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -34,10 +34,10 @@ #include "core/os/keyboard.h" #include "core/string/string_builder.h" #include "core/templates/pair.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/font.h" void GotoLineDialog::popup_find_line(CodeEdit *p_edit) { @@ -336,7 +336,7 @@ void FindReplaceBar::_replace_all() { matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color(SNAME("font_color"), SNAME("Label")) : get_theme_color(SNAME("error_color"), EditorStringName(Editor))); matches_label->set_text(vformat(TTR("%d replaced."), rc)); - text_editor->call_deferred(SNAME("connect"), "text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); + callable_mp((Object *)text_editor, &Object::connect).call_deferred("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed), 0U); results_count = -1; results_count_to_current = -1; needs_to_count_results = true; @@ -517,10 +517,10 @@ void FindReplaceBar::_show_search(bool p_focus_replace, bool p_show_only) { if (p_focus_replace) { search_text->deselect(); - replace_text->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)replace_text, &Control::grab_focus).call_deferred(); } else { replace_text->deselect(); - search_text->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)search_text, &Control::grab_focus).call_deferred(); } if (text_editor->has_selection(0) && !is_selection_only()) { @@ -1277,7 +1277,7 @@ void CodeTextEditor::move_lines_up() { for (int j = 0; j < caret_groups[i].size(); j++) { int c = caret_groups[i][j]; - Vector<int> caret_parameters = caret_group_parameters[j]; + const Vector<int> &caret_parameters = caret_group_parameters[j]; text_editor->set_caret_line(caret_parameters[4] - 1, c == 0, true, 0, c); text_editor->set_caret_column(caret_parameters[5], c == 0, c); @@ -1374,7 +1374,7 @@ void CodeTextEditor::move_lines_down() { for (int j = 0; j < caret_groups[i].size(); j++) { int c = caret_groups[i][j]; - Vector<int> caret_parameters = caret_group_parameters[j]; + const Vector<int> &caret_parameters = caret_group_parameters[j]; text_editor->set_caret_line(caret_parameters[4] + 1, c == 0, true, 0, c); text_editor->set_caret_column(caret_parameters[5], c == 0, c); @@ -1572,20 +1572,20 @@ void CodeTextEditor::goto_line(int p_line) { text_editor->remove_secondary_carets(); text_editor->deselect(); text_editor->unfold_line(p_line); - text_editor->call_deferred(SNAME("set_caret_line"), p_line); + callable_mp((TextEdit *)text_editor, &TextEdit::set_caret_line).call_deferred(p_line, true, true, 0, 0); } void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) { text_editor->remove_secondary_carets(); text_editor->unfold_line(p_line); - text_editor->call_deferred(SNAME("set_caret_line"), p_line); - text_editor->call_deferred(SNAME("set_caret_column"), p_begin); + callable_mp((TextEdit *)text_editor, &TextEdit::set_caret_line).call_deferred(p_line, true, true, 0, 0); + callable_mp((TextEdit *)text_editor, &TextEdit::set_caret_column).call_deferred(p_begin, true, 0); text_editor->select(p_line, p_begin, p_line, p_end); } void CodeTextEditor::goto_line_centered(int p_line) { goto_line(p_line); - text_editor->call_deferred(SNAME("center_viewport_to_caret")); + callable_mp((TextEdit *)text_editor, &TextEdit::center_viewport_to_caret).call_deferred(0); } void CodeTextEditor::set_executing_line(int p_line) { diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 69908af47d..0285692ab7 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -35,13 +35,13 @@ #include "editor/editor_help.h" #include "editor/editor_inspector.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/scene_tree_editor.h" #include "editor/node_dock.h" #include "editor/scene_tree_dock.h" +#include "editor/themes/editor_scale.h" #include "plugins/script_editor_plugin.h" #include "scene/gui/button.h" #include "scene/gui/check_box.h" @@ -1202,7 +1202,22 @@ void ConnectionsDock::_slot_menu_about_to_popup() { slot_menu->set_item_disabled(slot_menu->get_item_index(SLOT_MENU_DISCONNECT), connection_is_inherited); } -void ConnectionsDock::_rmb_pressed(const Ref<InputEvent> &p_event) { +void ConnectionsDock::_tree_gui_input(const Ref<InputEvent> &p_event) { + // Handle Delete press. + if (ED_IS_SHORTCUT("connections_editor/disconnect", p_event)) { + TreeItem *item = tree->get_selected(); + if (item && _get_item_type(*item) == TREE_ITEM_TYPE_CONNECTION) { + Connection connection = item->get_metadata(0); + _disconnect(connection); + update_tree(); + + // Stop the Delete input from propagating elsewhere. + accept_event(); + return; + } + } + + // Handle RMB press. const Ref<InputEventMouseButton> &mb_event = p_event; if (mb_event.is_null() || !mb_event->is_pressed() || mb_event->get_button_index() != MouseButton::RIGHT) { return; @@ -1536,13 +1551,13 @@ ConnectionsDock::ConnectionsDock() { slot_menu->connect("about_to_popup", callable_mp(this, &ConnectionsDock::_slot_menu_about_to_popup)); slot_menu->add_item(TTR("Edit..."), SLOT_MENU_EDIT); slot_menu->add_item(TTR("Go to Method"), SLOT_MENU_GO_TO_METHOD); - slot_menu->add_item(TTR("Disconnect"), SLOT_MENU_DISCONNECT); + slot_menu->add_shortcut(ED_SHORTCUT("connections_editor/disconnect", TTR("Disconnect"), Key::KEY_DELETE), SLOT_MENU_DISCONNECT); add_child(slot_menu); connect_dialog->connect("connected", callable_mp(this, &ConnectionsDock::_make_or_edit_connection)); tree->connect("item_selected", callable_mp(this, &ConnectionsDock::_tree_item_selected)); tree->connect("item_activated", callable_mp(this, &ConnectionsDock::_tree_item_activated)); - tree->connect("gui_input", callable_mp(this, &ConnectionsDock::_rmb_pressed)); + tree->connect("gui_input", callable_mp(this, &ConnectionsDock::_tree_gui_input)); add_theme_constant_override("separation", 3 * EDSCALE); } diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h index 2fd4778389..a99f0dd0fe 100644 --- a/editor/connections_dialog.h +++ b/editor/connections_dialog.h @@ -252,7 +252,7 @@ class ConnectionsDock : public VBoxContainer { void _signal_menu_about_to_popup(); void _handle_slot_menu_option(int p_option); void _slot_menu_about_to_popup(); - void _rmb_pressed(const Ref<InputEvent> &p_event); + void _tree_gui_input(const Ref<InputEvent> &p_event); void _close(); protected: diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index e37035f5eb..da0182b176 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -35,9 +35,9 @@ #include "editor/editor_feature_profile.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_current_type, const String &p_current_name) { _fill_type_list(); @@ -306,7 +306,7 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type)); if (!instantiable) { - r_item->set_custom_color(0, search_options->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + r_item->set_custom_color(0, search_options->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } HashMap<String, DocData::ClassDoc>::Iterator class_doc = EditorHelp::get_doc_data()->class_list.find(p_type); @@ -474,7 +474,7 @@ void CreateDialog::_notification(int p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { if (is_visible()) { - search_box->call_deferred(SNAME("grab_focus")); // still not visible + callable_mp((Control *)search_box, &Control::grab_focus).call_deferred(); // Still not visible. search_box->select_all(); } else { EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "create_new_node", Rect2(get_position(), get_size())); @@ -794,6 +794,7 @@ CreateDialog::CreateDialog() { rec_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL); recent = memnew(ItemList); + recent->set_auto_translate(false); rec_vb->add_margin_child(TTR("Recent:"), recent, true); recent->set_allow_reselect(true); recent->connect("item_selected", callable_mp(this, &CreateDialog::_history_selected)); diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.cpp b/editor/debugger/debug_adapter/debug_adapter_parser.cpp index 929f323e80..e854681010 100644 --- a/editor/debugger/debug_adapter/debug_adapter_parser.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_parser.cpp @@ -44,7 +44,7 @@ void DebugAdapterParser::_bind_methods() { ClassDB::bind_method(D_METHOD("req_attach", "params"), &DebugAdapterParser::req_attach); ClassDB::bind_method(D_METHOD("req_restart", "params"), &DebugAdapterParser::req_restart); ClassDB::bind_method(D_METHOD("req_terminate", "params"), &DebugAdapterParser::req_terminate); - ClassDB::bind_method(D_METHOD("req_configurationDone", "params"), &DebugAdapterParser::prepare_success_response); + ClassDB::bind_method(D_METHOD("req_configurationDone", "params"), &DebugAdapterParser::req_configurationDone); ClassDB::bind_method(D_METHOD("req_pause", "params"), &DebugAdapterParser::req_pause); ClassDB::bind_method(D_METHOD("req_continue", "params"), &DebugAdapterParser::req_continue); ClassDB::bind_method(D_METHOD("req_threads", "params"), &DebugAdapterParser::req_threads); @@ -180,6 +180,13 @@ Dictionary DebugAdapterParser::req_launch(const Dictionary &p_params) const { DebugAdapterProtocol::get_singleton()->get_current_peer()->supportsCustomData = args["godot/custom_data"]; } + DebugAdapterProtocol::get_singleton()->get_current_peer()->pending_launch = p_params; + + return Dictionary(); +} + +Dictionary DebugAdapterParser::_launch_process(const Dictionary &p_params) const { + Dictionary args = p_params["arguments"]; ScriptEditorDebugger *dbg = EditorDebuggerNode::get_singleton()->get_default_debugger(); if ((bool)args["noDebug"] != dbg->is_skip_breakpoints()) { dbg->debug_skip_breakpoints(); @@ -246,7 +253,7 @@ Dictionary DebugAdapterParser::req_restart(const Dictionary &p_params) const { args = args["arguments"]; params["arguments"] = args; - Dictionary response = DebugAdapterProtocol::get_singleton()->get_current_peer()->attached ? req_attach(params) : req_launch(params); + Dictionary response = DebugAdapterProtocol::get_singleton()->get_current_peer()->attached ? req_attach(params) : _launch_process(params); if (!response["success"]) { response["command"] = p_params["command"]; return response; @@ -261,6 +268,16 @@ Dictionary DebugAdapterParser::req_terminate(const Dictionary &p_params) const { return prepare_success_response(p_params); } +Dictionary DebugAdapterParser::req_configurationDone(const Dictionary &p_params) const { + Ref<DAPeer> peer = DebugAdapterProtocol::get_singleton()->get_current_peer(); + if (!peer->pending_launch.is_empty()) { + peer->res_queue.push_back(_launch_process(peer->pending_launch)); + peer->pending_launch.clear(); + } + + return prepare_success_response(p_params); +} + Dictionary DebugAdapterParser::req_pause(const Dictionary &p_params) const { EditorRunBar::get_singleton()->get_pause_button()->set_pressed(true); EditorDebuggerNode::get_singleton()->_paused(); diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.h b/editor/debugger/debug_adapter/debug_adapter_parser.h index 9995066ab4..e5493a4b9f 100644 --- a/editor/debugger/debug_adapter/debug_adapter_parser.h +++ b/editor/debugger/debug_adapter/debug_adapter_parser.h @@ -71,6 +71,7 @@ public: Dictionary req_attach(const Dictionary &p_params) const; Dictionary req_restart(const Dictionary &p_params) const; Dictionary req_terminate(const Dictionary &p_params) const; + Dictionary req_configurationDone(const Dictionary &p_params) const; Dictionary req_pause(const Dictionary &p_params) const; Dictionary req_continue(const Dictionary &p_params) const; Dictionary req_threads(const Dictionary &p_params) const; @@ -84,6 +85,9 @@ public: Dictionary req_evaluate(const Dictionary &p_params) const; Dictionary req_godot_put_msg(const Dictionary &p_params) const; + // Internal requests + Dictionary _launch_process(const Dictionary &p_params) const; + // Events Dictionary ev_initialized() const; Dictionary ev_process(const String &p_command) const; diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp index 26fb73570e..7417a3d8f7 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp @@ -678,7 +678,10 @@ bool DebugAdapterProtocol::process_message(const String &p_text) { if (!response.is_empty()) { _current_peer->res_queue.push_front(response); } else { - completed = false; + // Launch request needs to be deferred until we receive a configurationDone request. + if (command != "req_launch") { + completed = false; + } } } diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.h b/editor/debugger/debug_adapter/debug_adapter_protocol.h index ddc55816db..fb1c533bbb 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.h +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.h @@ -63,6 +63,7 @@ struct DAPeer : RefCounted { // Internal client info bool attached = false; + Dictionary pending_launch; Error handle_data(); Error send_data(); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index 8229abb5a0..6471bd449e 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -455,7 +455,7 @@ void EditorDebuggerNode::_debugger_wants_stop(int p_id) { // Ask editor to kill PID. int pid = get_debugger(p_id)->get_remote_pid(); if (pid) { - EditorNode::get_singleton()->call_deferred(SNAME("stop_child_process"), pid); + callable_mp(EditorNode::get_singleton(), &EditorNode::stop_child_process).call_deferred(pid); } } @@ -593,9 +593,15 @@ void EditorDebuggerNode::set_breakpoints(const String &p_path, Array p_lines) { } } -void EditorDebuggerNode::reload_scripts() { +void EditorDebuggerNode::reload_all_scripts() { _for_all(tabs, [&](ScriptEditorDebugger *dbg) { - dbg->reload_scripts(); + dbg->reload_all_scripts(); + }); +} + +void EditorDebuggerNode::reload_scripts(const Vector<String> &p_script_paths) { + _for_all(tabs, [&](ScriptEditorDebugger *dbg) { + dbg->reload_scripts(p_script_paths); }); } diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h index 4338f144b8..d30f29c7c6 100644 --- a/editor/debugger/editor_debugger_node.h +++ b/editor/debugger/editor_debugger_node.h @@ -187,7 +187,8 @@ public: bool is_skip_breakpoints() const; void set_breakpoint(const String &p_path, int p_line, bool p_enabled); void set_breakpoints(const String &p_path, Array p_lines); - void reload_scripts(); + void reload_all_scripts(); + void reload_scripts(const Vector<String> &p_script_paths); // Remote inspector/edit. void request_remote_tree(); diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp index 6305b7435a..7d3ea33fb5 100644 --- a/editor/debugger/editor_debugger_tree.cpp +++ b/editor/debugger/editor_debugger_tree.cpp @@ -253,7 +253,7 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int } debugger_id = p_debugger; // Needed by hook, could be avoided if every debugger had its own tree if (scroll_item) { - call_deferred(SNAME("scroll_to_item"), scroll_item); + callable_mp((Tree *)this, &Tree::scroll_to_item).call_deferred(scroll_item, false); } last_filter = filter; updating_scene_tree = false; diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp index e93369179c..af723cc731 100644 --- a/editor/debugger/editor_performance_profiler.cpp +++ b/editor/debugger/editor_performance_profiler.cpp @@ -31,9 +31,9 @@ #include "editor_performance_profiler.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "main/performance.h" EditorPerformanceProfiler::Monitor::Monitor() {} diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index d54fd62e8c..2809b873b1 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -31,9 +31,9 @@ #include "editor_profiler.h" #include "core/os/os.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/image_texture.h" void EditorProfiler::_make_metric_ptrs(Metric &m) { diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index 7df942e288..4ebed726c5 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -31,9 +31,9 @@ #include "editor_visual_profiler.h" #include "core/os/os.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/image_texture.h" void EditorVisualProfiler::add_frame_metric(const Metric &p_metric) { diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 7077bce9f7..3c863bdc19 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -44,7 +44,6 @@ #include "editor/editor_log.h" #include "editor/editor_node.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" @@ -52,6 +51,7 @@ #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "main/performance.h" #include "scene/3d/camera_3d.h" #include "scene/debugger/scene_debugger.h" @@ -1518,8 +1518,12 @@ void ScriptEditorDebugger::set_breakpoint(const String &p_path, int p_line, bool } } -void ScriptEditorDebugger::reload_scripts() { - _put_msg("reload_scripts", Array(), debugging_thread_id != Thread::UNASSIGNED_ID ? debugging_thread_id : Thread::MAIN_ID); +void ScriptEditorDebugger::reload_all_scripts() { + _put_msg("reload_all_scripts", Array(), debugging_thread_id != Thread::UNASSIGNED_ID ? debugging_thread_id : Thread::MAIN_ID); +} + +void ScriptEditorDebugger::reload_scripts(const Vector<String> &p_script_paths) { + _put_msg("reload_scripts", Variant(p_script_paths).operator Array(), debugging_thread_id != Thread::UNASSIGNED_ID ? debugging_thread_id : Thread::MAIN_ID); } bool ScriptEditorDebugger::is_skip_breakpoints() { @@ -1687,7 +1691,7 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) { // Parse back the `file:line @ method()` string. const Vector<String> file_line_number = ci->get_text(1).split("@")[0].strip_edges().split(":"); ERR_FAIL_COND_MSG(file_line_number.size() < 2, "Incorrect C++ source stack trace file:line format (please report)."); - const String file = file_line_number[0]; + const String &file = file_line_number[0]; const int line_number = file_line_number[1].to_int(); // Construct a GitHub repository URL and open it in the user's default web browser. diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index 79224061ff..589e82ef25 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -300,7 +300,8 @@ public: void update_live_edit_root(); - void reload_scripts(); + void reload_all_scripts(); + void reload_scripts(const Vector<String> &p_script_paths); bool is_skip_breakpoints(); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 26779f5b52..4be6afbcff 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -35,9 +35,9 @@ #include "core/io/resource_loader.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/margin_container.h" void DependencyEditor::_searched(const String &p_path) { @@ -398,6 +398,7 @@ DependencyEditorOwners::DependencyEditorOwners() { file_options->connect("id_pressed", callable_mp(this, &DependencyEditorOwners::_file_option)); owners = memnew(ItemList); + owners->set_auto_translate(false); owners->set_select_mode(ItemList::SELECT_MULTI); owners->connect("item_clicked", callable_mp(this, &DependencyEditorOwners::_list_rmb_clicked)); owners->connect("item_activated", callable_mp(this, &DependencyEditorOwners::_select_file)); diff --git a/editor/directory_create_dialog.cpp b/editor/directory_create_dialog.cpp index 0efd11a6c1..6f9b91731b 100644 --- a/editor/directory_create_dialog.cpp +++ b/editor/directory_create_dialog.cpp @@ -32,8 +32,8 @@ #include "core/io/dir_access.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/gui/editor_validation_panel.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" @@ -110,7 +110,7 @@ void DirectoryCreateDialog::ok_pressed() { err = da->make_dir_recursive(path); if (err == OK) { - emit_signal(SNAME("dir_created")); + emit_signal(SNAME("dir_created"), base_dir.path_join(path)); } else { EditorNode::get_singleton()->show_warning(TTR("Could not create folder.")); } @@ -131,7 +131,7 @@ void DirectoryCreateDialog::config(const String &p_base_dir) { } void DirectoryCreateDialog::_bind_methods() { - ADD_SIGNAL(MethodInfo("dir_created")); + ADD_SIGNAL(MethodInfo("dir_created", PropertyInfo(Variant::STRING, "path"))); } DirectoryCreateDialog::DirectoryCreateDialog() { diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index a7e3c03250..44f6444a31 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -307,21 +307,21 @@ void DocTools::merge_from(const DocTools &p_data) { } } -void DocTools::remove_from(const DocTools &p_data) { - for (const KeyValue<String, DocData::ClassDoc> &E : p_data.class_list) { - if (class_list.has(E.key)) { - class_list.erase(E.key); - } - } -} - void DocTools::add_doc(const DocData::ClassDoc &p_class_doc) { ERR_FAIL_COND(p_class_doc.name.is_empty()); class_list[p_class_doc.name] = p_class_doc; + inheriting[p_class_doc.inherits].insert(p_class_doc.name); } void DocTools::remove_doc(const String &p_class_name) { ERR_FAIL_COND(p_class_name.is_empty() || !class_list.has(p_class_name)); + const String &inherits = class_list[p_class_name].inherits; + if (inheriting.has(inherits)) { + inheriting[inherits].erase(p_class_name); + if (inheriting[inherits].is_empty()) { + inheriting.erase(inherits); + } + } class_list.erase(p_class_name); } @@ -382,7 +382,7 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) { continue; } - String cname = name; + const String &cname = name; // Property setters and getters do not get exposed as individual methods. HashSet<StringName> setters_getters; @@ -391,6 +391,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) { c.name = cname; c.inherits = ClassDB::get_parent_class(name); + inheriting[c.inherits].insert(cname); + List<PropertyInfo> properties; List<PropertyInfo> own_properties; @@ -692,6 +694,7 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) { // it's not a ClassDB-exposed class. class_list["Variant"] = DocData::ClassDoc(); class_list["Variant"].name = "Variant"; + inheriting[""].insert("Variant"); } // Add Variant data types. @@ -709,6 +712,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) { DocData::ClassDoc &c = class_list[cname]; c.name = cname; + inheriting[""].insert(cname); + Callable::CallError cerror; Variant v; Variant::construct(Variant::Type(i), v, nullptr, 0, cerror); @@ -870,6 +875,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) { DocData::ClassDoc &c = class_list[cname]; c.name = cname; + inheriting[""].insert(cname); + // Global constants. for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) { DocData::ConstantDoc cd; @@ -953,6 +960,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) { DocData::ClassDoc c; c.name = cname; + inheriting[""].insert(cname); + // Get functions. List<MethodInfo> minfo; lang->get_public_functions(&minfo); @@ -1195,6 +1204,8 @@ Error DocTools::_load(Ref<XMLParser> parser) { c.inherits = parser->get_named_attribute_value("inherits"); } + inheriting[c.inherits].insert(name); + if (parser->has_attribute("is_deprecated")) { c.is_deprecated = parser->get_named_attribute_value("is_deprecated").to_lower() == "true"; } diff --git a/editor/doc_tools.h b/editor/doc_tools.h index 5fffb6be38..7f29cc238a 100644 --- a/editor/doc_tools.h +++ b/editor/doc_tools.h @@ -32,16 +32,17 @@ #define DOC_TOOLS_H #include "core/doc_data.h" +#include "core/templates/rb_set.h" class DocTools { public: String version; HashMap<String, DocData::ClassDoc> class_list; + HashMap<String, RBSet<String, NaturalNoCaseComparator>> inheriting; static Error erase_classes(const String &p_dir); void merge_from(const DocTools &p_data); - void remove_from(const DocTools &p_data); void add_doc(const DocData::ClassDoc &p_class_doc); void remove_doc(const String &p_class_name); bool has_doc(const String &p_class_name); diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 672697bab0..6c859ce236 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -35,6 +35,7 @@ #include "core/license.gen.h" #include "core/version.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" // The metadata key used to store and retrieve the version text to copy to the clipboard. const String EditorAbout::META_TEXT_TO_COPY = "text_to_copy"; @@ -99,6 +100,7 @@ ScrollContainer *EditorAbout::_populate_list(const String &p_name, const List<St vbc->add_child(lbl); ItemList *il = memnew(ItemList); + il->set_auto_translate(false); il->set_h_size_flags(Control::SIZE_EXPAND_FILL); il->set_same_column_width(true); il->set_auto_height(true); diff --git a/editor/editor_about.h b/editor/editor_about.h index 22b5f3ded0..639dc6cc3f 100644 --- a/editor/editor_about.h +++ b/editor/editor_about.h @@ -42,8 +42,6 @@ #include "scene/gui/texture_rect.h" #include "scene/gui/tree.h" -#include "editor/editor_scale.h" - /** * NOTE: Do not assume the EditorNode singleton to be available in this class' methods. * EditorAbout is also used from the project manager where EditorNode isn't initialized. diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index b609de9f67..ab0816805f 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -35,11 +35,11 @@ #include "core/io/zip_io.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" #include "editor/gui/editor_toaster.h" #include "editor/progress_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_box.h" #include "scene/gui/label.h" #include "scene/gui/link_button.h" diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index f4a9e0a2ef..50845b4458 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -35,12 +35,12 @@ #include "core/io/resource_saver.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/separator.h" #include "scene/resources/font.h" #include "servers/audio_server.h" @@ -1234,7 +1234,7 @@ void EditorAudioBuses::_load_default_layout() { AudioServer::get_singleton()->set_bus_layout(state); _rebuild_buses(); EditorUndoRedoManager::get_singleton()->clear_history(true, EditorUndoRedoManager::GLOBAL_HISTORY); - call_deferred(SNAME("_select_layout")); + callable_mp(this, &EditorAudioBuses::_select_layout).call_deferred(); } void EditorAudioBuses::_file_dialog_callback(const String &p_string) { @@ -1250,7 +1250,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) { AudioServer::get_singleton()->set_bus_layout(state); _rebuild_buses(); EditorUndoRedoManager::get_singleton()->clear_history(true, EditorUndoRedoManager::GLOBAL_HISTORY); - call_deferred(SNAME("_select_layout")); + callable_mp(this, &EditorAudioBuses::_select_layout).call_deferred(); } else if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { if (new_layout) { @@ -1270,14 +1270,13 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) { file->set_text(String(TTR("Layout:")) + " " + p_string.get_file()); _rebuild_buses(); EditorUndoRedoManager::get_singleton()->clear_history(true, EditorUndoRedoManager::GLOBAL_HISTORY); - call_deferred(SNAME("_select_layout")); + callable_mp(this, &EditorAudioBuses::_select_layout).call_deferred(); } } void EditorAudioBuses::_bind_methods() { ClassDB::bind_method("_update_bus", &EditorAudioBuses::_update_bus); ClassDB::bind_method("_update_sends", &EditorAudioBuses::_update_sends); - ClassDB::bind_method("_select_layout", &EditorAudioBuses::_select_layout); } EditorAudioBuses::EditorAudioBuses() { @@ -1370,7 +1369,7 @@ void EditorAudioBuses::open_layout(const String &p_path) { AudioServer::get_singleton()->set_bus_layout(state); _rebuild_buses(); EditorUndoRedoManager::get_singleton()->clear_history(true, EditorUndoRedoManager::GLOBAL_HISTORY); - call_deferred(SNAME("_select_layout")); + callable_mp(this, &EditorAudioBuses::_select_layout).call_deferred(); } void AudioBusesEditorPlugin::edit(Object *p_node) { diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 204b717296..4d5393299c 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -33,12 +33,12 @@ #include "core/config/project_settings.h" #include "core/core_constants.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" #include "editor/gui/editor_file_dialog.h" #include "editor/project_settings_editor.h" +#include "editor/themes/editor_scale.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" @@ -57,7 +57,7 @@ void EditorAutoloadSettings::_notification(int p_what) { for (const AutoloadInfo &info : autoload_cache) { if (info.node && info.in_editor) { - get_tree()->get_root()->call_deferred(SNAME("add_child"), info.node); + callable_mp((Node *)get_tree()->get_root(), &Node::add_child).call_deferred(info.node, false, Node::INTERNAL_MODE_DISABLED); } } browse_button->set_icon(get_editor_theme_icon(SNAME("Folder"))); @@ -65,6 +65,7 @@ void EditorAutoloadSettings::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { browse_button->set_icon(get_editor_theme_icon(SNAME("Folder"))); + add_autoload->set_icon(get_editor_theme_icon(SNAME("Add"))); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -533,7 +534,7 @@ void EditorAutoloadSettings::update_autoload() { } if (info.in_editor) { ERR_CONTINUE(!info.node); - get_tree()->get_root()->call_deferred(SNAME("remove_child"), info.node); + callable_mp((Node *)get_tree()->get_root(), &Node::remove_child).call_deferred(info.node); } if (info.node) { diff --git a/editor/editor_build_profile.cpp b/editor/editor_build_profile.cpp index c4a5fbd939..3d10b7949e 100644 --- a/editor/editor_build_profile.cpp +++ b/editor/editor_build_profile.cpp @@ -36,10 +36,10 @@ #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" const char *EditorBuildProfile::build_option_identifiers[BUILD_OPTION_MAX] = { // This maps to SCons build options. @@ -481,7 +481,7 @@ void EditorBuildProfileManager::_detect_classes() { String l = f->get_line(); Vector<String> fields = l.split("::"); if (fields.size() == 4) { - String path = fields[0]; + const String &path = fields[0]; DetectedFile df; df.timestamp = fields[1].to_int(); df.md5 = fields[2]; @@ -597,11 +597,11 @@ void EditorBuildProfileManager::_fill_classes_from(TreeItem *p_parent, const Str TreeItem *class_item = class_list->create_item(p_parent); class_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); class_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_class)); - String text = p_class; + const String &text = p_class; bool disabled = edited->is_class_disabled(p_class); if (disabled) { - class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + class_item->set_custom_color(0, class_list->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } class_item->set_text(0, text); @@ -888,7 +888,7 @@ EditorBuildProfileManager::EditorBuildProfileManager() { export_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM); force_detect_classes = memnew(LineEdit); - main_vbc->add_margin_child(TTR("Forced classes on detect:"), force_detect_classes); + main_vbc->add_margin_child(TTR("Forced Classes on Detect:"), force_detect_classes); force_detect_classes->connect("text_changed", callable_mp(this, &EditorBuildProfileManager::_force_detect_classes_changed)); set_title(TTR("Edit Build Configuration Profile")); diff --git a/editor/editor_builders.py b/editor/editor_builders.py index 90ecccbf30..25004da877 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -3,6 +3,7 @@ All such functions are invoked in a subprocess on Windows to prevent build flakiness. """ + import os import os.path import shutil @@ -49,34 +50,6 @@ def make_doc_header(target, source, env): g.close() -def make_fonts_header(target, source, env): - dst = target[0] - - g = open(dst, "w", encoding="utf-8") - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef _EDITOR_FONTS_H\n") - g.write("#define _EDITOR_FONTS_H\n") - - # Saving uncompressed, since FreeType will reference from memory pointer. - for i in range(len(source)): - with open(source[i], "rb") as f: - buf = f.read() - - name = os.path.splitext(os.path.basename(source[i]))[0] - - g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n") - g.write("static const unsigned char _font_" + name + "[] = {\n") - for j in range(len(buf)): - g.write("\t" + str(buf[j]) + ",\n") - - g.write("};\n") - - g.write("#endif") - - g.close() - - def make_translations_header(target, source, env, category): dst = target[0] diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index 6626251ee6..567b686b85 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -31,10 +31,10 @@ #include "editor/editor_command_palette.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_toaster.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/control.h" #include "scene/gui/tree.h" @@ -74,7 +74,7 @@ void EditorCommandPalette::_update_command_search(const String &search_text) { CommandEntry r; r.key_name = E.key; r.display_name = E.value.name; - r.shortcut_text = E.value.shortcut; + r.shortcut_text = E.value.shortcut_text; r.last_used = E.value.last_used; bool is_subsequence_of_key_name = search_text.is_subsequence_ofn(r.key_name); @@ -92,8 +92,6 @@ void EditorCommandPalette::_update_command_search(const String &search_text) { } } - command_keys.clear(); - TreeItem *root = search_options->get_root(); root->clear_children(); @@ -168,6 +166,19 @@ void EditorCommandPalette::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { command_search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); } break; + + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + if (!EditorSettings::get_singleton()->check_changed_settings_in_group("shortcuts")) { + break; + } + + for (KeyValue<String, Command> &kv : commands) { + Command &c = kv.value; + if (c.shortcut.is_valid()) { + c.shortcut_text = c.shortcut->get_as_text(); + } + } + } break; } } @@ -221,7 +232,7 @@ void EditorCommandPalette::remove_command(String p_key_name) { commands.erase(p_key_name); } -void EditorCommandPalette::add_command(String p_command_name, String p_key_name, Callable p_action, Vector<Variant> arguments, String p_shortcut_text) { +void EditorCommandPalette::add_command(String p_command_name, String p_key_name, Callable p_action, Vector<Variant> arguments, const Ref<Shortcut> &p_shortcut) { ERR_FAIL_COND_MSG(commands.has(p_key_name), "The Command '" + String(p_command_name) + "' already exists. Unable to add it."); const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * arguments.size()); @@ -231,7 +242,12 @@ void EditorCommandPalette::add_command(String p_command_name, String p_key_name, Command command; command.name = p_command_name; command.callable = p_action.bindp(argptrs, arguments.size()); - command.shortcut = p_shortcut_text; + if (p_shortcut.is_null()) { + command.shortcut_text = "None"; + } else { + command.shortcut = p_shortcut; + command.shortcut_text = p_shortcut->get_as_text(); + } commands[p_key_name] = command; } @@ -242,7 +258,7 @@ void EditorCommandPalette::_add_command(String p_command_name, String p_key_name Command command; command.name = p_command_name; command.callable = p_binded_action; - command.shortcut = p_shortcut_text; + command.shortcut_text = p_shortcut_text; // Commands added from plugins don't exist yet when the history is loaded, so we assign the last use time here if it was recorded. Dictionary command_history = EditorSettings::get_singleton()->get_project_metadata("command_palette", "command_history", Dictionary()); @@ -275,8 +291,7 @@ void EditorCommandPalette::register_shortcuts_as_command() { Ref<InputEventShortcut> ev; ev.instantiate(); ev->set_shortcut(shortcut); - String shortcut_text = String(shortcut->get_as_text()); - add_command(command_name, E.key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::push_input), varray(ev, false), shortcut_text); + add_command(command_name, E.key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::push_input), varray(ev, false), shortcut); } unregistered_shortcuts.clear(); @@ -296,8 +311,7 @@ Ref<Shortcut> EditorCommandPalette::add_shortcut_command(const String &p_command Ref<InputEventShortcut> ev; ev.instantiate(); ev->set_shortcut(p_shortcut); - String shortcut_text = String(p_shortcut->get_as_text()); - add_command(p_command, p_key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::push_input), varray(ev, false), shortcut_text); + add_command(p_command, p_key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::push_input), varray(ev, false), p_shortcut); } else { const String key_name = String(p_key); const String command_name = String(p_command); diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h index 01fa6896a9..cc0f726b3a 100644 --- a/editor/editor_command_palette.h +++ b/editor/editor_command_palette.h @@ -46,7 +46,8 @@ class EditorCommandPalette : public ConfirmationDialog { struct Command { Callable callable; String name; - String shortcut; + Ref<Shortcut> shortcut; + String shortcut_text; int last_used = 0; // Store time as int, because doubles have problems with text serialization. }; @@ -77,8 +78,6 @@ class EditorCommandPalette : public ConfirmationDialog { HashMap<String, Command> commands; HashMap<String, Pair<String, Ref<Shortcut>>> unregistered_shortcuts; - List<String> command_keys; - void _update_command_search(const String &search_text); float _score_path(const String &p_search, const String &p_path); void _sbox_input(const Ref<InputEvent> &p_ie); @@ -95,7 +94,7 @@ protected: public: void open_popup(); void get_actions_list(List<String> *p_list) const; - void add_command(String p_command_name, String p_key_name, Callable p_action, Vector<Variant> arguments, String p_shortcut_text = "None"); + void add_command(String p_command_name, String p_key_name, Callable p_action, Vector<Variant> arguments, const Ref<Shortcut> &p_shortcut); void execute_command(const String &p_command_name); void register_shortcuts_as_command(); Ref<Shortcut> add_shortcut_command(const String &p_command, const String &p_key, Ref<Shortcut> p_shortcut); diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index fe8c42ea3b..794d1b3e10 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -37,10 +37,10 @@ #include "core/io/resource_loader.h" #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "editor/editor_scale.h" #include "editor/editor_undo_redo_manager.h" #include "editor/multi_node_edit.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/packed_scene.h" void EditorSelectionHistory::cleanup_history() { @@ -1242,7 +1242,6 @@ void EditorSelection::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_node", "node"), &EditorSelection::remove_node); ClassDB::bind_method(D_METHOD("get_selected_nodes"), &EditorSelection::get_selected_nodes); ClassDB::bind_method(D_METHOD("get_transformable_selected_nodes"), &EditorSelection::_get_transformable_selected_nodes); - ClassDB::bind_method(D_METHOD("_emit_change"), &EditorSelection::_emit_change); ADD_SIGNAL(MethodInfo("selection_changed")); } @@ -1290,7 +1289,7 @@ void EditorSelection::update() { changed = false; if (!emitted) { emitted = true; - call_deferred(SNAME("_emit_change")); + callable_mp(this, &EditorSelection::_emit_change).call_deferred(); } } diff --git a/editor/editor_dock_manager.cpp b/editor/editor_dock_manager.cpp new file mode 100644 index 0000000000..dfe9504706 --- /dev/null +++ b/editor/editor_dock_manager.cpp @@ -0,0 +1,716 @@ +/**************************************************************************/ +/* editor_dock_manager.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "editor_dock_manager.h" + +#include "scene/gui/box_container.h" +#include "scene/gui/button.h" +#include "scene/gui/label.h" +#include "scene/gui/popup.h" +#include "scene/gui/split_container.h" +#include "scene/gui/tab_container.h" +#include "scene/main/window.h" + +#include "editor/editor_node.h" +#include "editor/editor_settings.h" +#include "editor/editor_string_names.h" +#include "editor/filesystem_dock.h" +#include "editor/themes/editor_scale.h" +#include "editor/window_wrapper.h" + +EditorDockManager *EditorDockManager::singleton = nullptr; + +void DockSplitContainer::_update_visibility() { + if (is_updating) { + return; + } + is_updating = true; + bool any_visible = false; + for (int i = 0; i < 2; i++) { + Control *split = get_containable_child(i); + if (split && split->is_visible()) { + any_visible = true; + break; + } + } + set_visible(any_visible); + is_updating = false; +} + +void DockSplitContainer::add_child_notify(Node *p_child) { + SplitContainer::add_child_notify(p_child); + + Control *child_control = nullptr; + for (int i = 0; i < 2; i++) { + Control *split = get_containable_child(i); + if (p_child == split) { + child_control = split; + break; + } + } + if (!child_control) { + return; + } + + child_control->connect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility)); + _update_visibility(); +} + +void DockSplitContainer::remove_child_notify(Node *p_child) { + SplitContainer::remove_child_notify(p_child); + + Control *child_control = nullptr; + for (int i = 0; i < 2; i++) { + Control *split = get_containable_child(i); + if (p_child == split) { + child_control = split; + break; + } + } + if (!child_control) { + return; + } + + child_control->disconnect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility)); + _update_visibility(); +} + +void EditorDockManager::_dock_select_popup_theme_changed() { + if (dock_float) { + dock_float->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("MakeFloating"))); + } + if (dock_select_popup->is_layout_rtl()) { + dock_tab_move_left->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Forward"))); + dock_tab_move_right->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Back"))); + } else { + dock_tab_move_left->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Back"))); + dock_tab_move_right->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Forward"))); + } +} + +void EditorDockManager::_dock_popup_exit() { + dock_select_rect_over_idx = -1; + dock_select->queue_redraw(); +} + +void EditorDockManager::_dock_pre_popup(int p_dock_slot) { + dock_popup_selected_idx = p_dock_slot; +} + +void EditorDockManager::_dock_move_left() { + if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) { + return; + } + Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab()); + Control *prev_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() - 1); + if (!current_ctl || !prev_ctl) { + return; + } + dock_slot[dock_popup_selected_idx]->move_child(current_ctl, prev_ctl->get_index(false)); + dock_select->queue_redraw(); + _edit_current(); + emit_signal(SNAME("layout_changed")); +} + +void EditorDockManager::_dock_move_right() { + if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) { + return; + } + Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab()); + Control *next_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() + 1); + if (!current_ctl || !next_ctl) { + return; + } + dock_slot[dock_popup_selected_idx]->move_child(next_ctl, current_ctl->get_index(false)); + dock_select->queue_redraw(); + _edit_current(); + emit_signal(SNAME("layout_changed")); +} + +void EditorDockManager::_dock_select_input(const Ref<InputEvent> &p_input) { + Ref<InputEventMouse> me = p_input; + + if (me.is_valid()) { + Vector2 point = me->get_position(); + + int nrect = -1; + for (int i = 0; i < DOCK_SLOT_MAX; i++) { + if (dock_select_rect[i].has_point(point)) { + nrect = i; + break; + } + } + + if (nrect != dock_select_rect_over_idx) { + dock_select->queue_redraw(); + dock_select_rect_over_idx = nrect; + } + + if (nrect == -1) { + return; + } + + Ref<InputEventMouseButton> mb = me; + + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && dock_popup_selected_idx != nrect) { + dock_slot[nrect]->move_tab_from_tab_container(dock_slot[dock_popup_selected_idx], dock_slot[dock_popup_selected_idx]->get_current_tab(), dock_slot[nrect]->get_tab_count()); + + if (dock_slot[dock_popup_selected_idx]->get_tab_count() == 0) { + dock_slot[dock_popup_selected_idx]->hide(); + } else { + dock_slot[dock_popup_selected_idx]->set_current_tab(0); + } + + dock_popup_selected_idx = nrect; + dock_slot[nrect]->show(); + dock_select->queue_redraw(); + + update_dock_slots_visibility(true); + + _edit_current(); + emit_signal(SNAME("layout_changed")); + } + } +} + +void EditorDockManager::_dock_select_draw() { + Size2 s = dock_select->get_size(); + s.y /= 2.0; + s.x /= 6.0; + + Color used = Color(0.6, 0.6, 0.6, 0.8); + Color used_selected = Color(0.8, 0.8, 0.8, 0.8); + Color tab_selected = dock_select->get_theme_color(SNAME("mono_color"), EditorStringName(Editor)); + Color unused = used; + unused.a = 0.4; + Color unusable = unused; + unusable.a = 0.1; + + Rect2 unr(s.x * 2, 0, s.x * 2, s.y * 2); + unr.position += Vector2(2, 5); + unr.size -= Vector2(4, 7); + + dock_select->draw_rect(unr, unusable); + + dock_tab_move_left->set_disabled(true); + dock_tab_move_right->set_disabled(true); + + if (dock_popup_selected_idx != -1 && dock_slot[dock_popup_selected_idx]->get_tab_count()) { + dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() == 0); + dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() >= dock_slot[dock_popup_selected_idx]->get_tab_count() - 1); + } + + for (int i = 0; i < DOCK_SLOT_MAX; i++) { + Vector2 ofs; + + switch (i) { + case DOCK_SLOT_LEFT_UL: { + } break; + case DOCK_SLOT_LEFT_BL: { + ofs.y += s.y; + } break; + case DOCK_SLOT_LEFT_UR: { + ofs.x += s.x; + } break; + case DOCK_SLOT_LEFT_BR: { + ofs += s; + } break; + case DOCK_SLOT_RIGHT_UL: { + ofs.x += s.x * 4; + } break; + case DOCK_SLOT_RIGHT_BL: { + ofs.x += s.x * 4; + ofs.y += s.y; + + } break; + case DOCK_SLOT_RIGHT_UR: { + ofs.x += s.x * 4; + ofs.x += s.x; + + } break; + case DOCK_SLOT_RIGHT_BR: { + ofs.x += s.x * 4; + ofs += s; + + } break; + } + + Rect2 r(ofs, s); + dock_select_rect[i] = r; + r.position += Vector2(2, 5); + r.size -= Vector2(4, 7); + + if (i == dock_select_rect_over_idx) { + dock_select->draw_rect(r, used_selected); + } else if (dock_slot[i]->get_tab_count() == 0) { + dock_select->draw_rect(r, unused); + } else { + dock_select->draw_rect(r, used); + } + + for (int j = 0; j < MIN(3, dock_slot[i]->get_tab_count()); j++) { + int xofs = (r.size.width / 3) * j; + Color c = used; + if (i == dock_popup_selected_idx && (dock_slot[i]->get_current_tab() > 3 || dock_slot[i]->get_current_tab() == j)) { + c = tab_selected; + } + dock_select->draw_rect(Rect2(2 + ofs.x + xofs, ofs.y, r.size.width / 3 - 1, 3), c); + } + } +} + +void EditorDockManager::_dock_split_dragged(int p_offset) { + EditorNode::get_singleton()->save_editor_layout_delayed(); +} + +void EditorDockManager::_dock_tab_changed(int p_tab) { + // Update visibility but don't set current tab. + update_dock_slots_visibility(true); +} + +void EditorDockManager::_edit_current() { + EditorNode::get_singleton()->edit_current(); +} + +void EditorDockManager::_dock_floating_close_request(WindowWrapper *p_wrapper) { + int dock_slot_num = p_wrapper->get_meta("dock_slot"); + int dock_slot_index = p_wrapper->get_meta("dock_index"); + + // Give back the dock to the original owner. + Control *dock = p_wrapper->release_wrapped_control(); + + int target_index = MIN(dock_slot_index, dock_slot[dock_slot_num]->get_tab_count()); + dock_slot[dock_slot_num]->add_child(dock); + dock_slot[dock_slot_num]->move_child(dock, target_index); + dock_slot[dock_slot_num]->set_current_tab(target_index); + + floating_docks.erase(p_wrapper); + p_wrapper->queue_free(); + + update_dock_slots_visibility(true); + + _edit_current(); +} + +void EditorDockManager::_dock_make_selected_float() { + Control *dock = dock_slot[dock_popup_selected_idx]->get_current_tab_control(); + _dock_make_float(dock, dock_popup_selected_idx); + + dock_select_popup->hide(); + _edit_current(); +} + +void EditorDockManager::_dock_make_float(Control *p_dock, int p_slot_index, bool p_show_window) { + ERR_FAIL_NULL(p_dock); + + Size2 borders = Size2(4, 4) * EDSCALE; + // Remember size and position before removing it from the main window. + Size2 dock_size = p_dock->get_size() + borders * 2; + Point2 dock_screen_pos = p_dock->get_screen_position(); + + int dock_index = p_dock->get_index() - 1; + dock_slot[p_slot_index]->remove_child(p_dock); + + WindowWrapper *wrapper = memnew(WindowWrapper); + wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), p_dock->get_name())); + wrapper->set_margins_enabled(true); + + EditorNode::get_singleton()->get_gui_base()->add_child(wrapper); + + wrapper->set_wrapped_control(p_dock); + wrapper->set_meta("dock_slot", p_slot_index); + wrapper->set_meta("dock_index", dock_index); + wrapper->set_meta("dock_name", p_dock->get_name().operator String()); + p_dock->show(); + + wrapper->connect("window_close_requested", callable_mp(this, &EditorDockManager::_dock_floating_close_request).bind(wrapper)); + + dock_select_popup->hide(); + + if (p_show_window) { + wrapper->restore_window(Rect2i(dock_screen_pos, dock_size), EditorNode::get_singleton()->get_gui_base()->get_window()->get_current_screen()); + } + + update_dock_slots_visibility(true); + + floating_docks.push_back(wrapper); + + _edit_current(); +} + +void EditorDockManager::_restore_floating_dock(const Dictionary &p_dock_dump, Control *p_dock, int p_slot_index) { + WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(p_dock); + if (!wrapper) { + _dock_make_float(p_dock, p_slot_index, false); + wrapper = floating_docks[floating_docks.size() - 1]; + } + + wrapper->restore_window_from_saved_position( + p_dock_dump.get("window_rect", Rect2i()), + p_dock_dump.get("window_screen", -1), + p_dock_dump.get("window_screen_rect", Rect2i())); +} + +void EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const { + for (int i = 0; i < DOCK_SLOT_MAX; i++) { + String names; + for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) { + String name = dock_slot[i]->get_tab_control(j)->get_name(); + if (!names.is_empty()) { + names += ","; + } + names += name; + } + + String config_key = "dock_" + itos(i + 1); + + if (p_layout->has_section_key(p_section, config_key)) { + p_layout->erase_section_key(p_section, config_key); + } + + if (!names.is_empty()) { + p_layout->set_value(p_section, config_key, names); + } + + int selected_tab_idx = dock_slot[i]->get_current_tab(); + if (selected_tab_idx >= 0) { + p_layout->set_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx", selected_tab_idx); + } + } + + Dictionary floating_docks_dump; + + for (WindowWrapper *wrapper : floating_docks) { + Control *dock = wrapper->get_wrapped_control(); + + Dictionary dock_dump; + dock_dump["window_rect"] = wrapper->get_window_rect(); + + int screen = wrapper->get_window_screen(); + dock_dump["window_screen"] = wrapper->get_window_screen(); + dock_dump["window_screen_rect"] = DisplayServer::get_singleton()->screen_get_usable_rect(screen); + + String name = dock->get_name(); + floating_docks_dump[name] = dock_dump; + + int dock_slot_id = wrapper->get_meta("dock_slot"); + String config_key = "dock_" + itos(dock_slot_id + 1); + + String names = p_layout->get_value(p_section, config_key, ""); + if (names.is_empty()) { + names = name; + } else { + names += "," + name; + } + p_layout->set_value(p_section, config_key, names); + } + + p_layout->set_value(p_section, "dock_floating", floating_docks_dump); + + for (int i = 0; i < vsplits.size(); i++) { + if (vsplits[i]->is_visible_in_tree()) { + p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset()); + } + } + + for (int i = 0; i < hsplits.size(); i++) { + p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset()); + } + + FileSystemDock::get_singleton()->save_layout_to_config(p_layout, p_section); +} + +void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section) { + Dictionary floating_docks_dump = p_layout->get_value(p_section, "dock_floating", Dictionary()); + + bool restore_window_on_load = EDITOR_GET("interface/multi_window/restore_windows_on_load"); + + for (int i = 0; i < DOCK_SLOT_MAX; i++) { + if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1))) { + continue; + } + + Vector<String> names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(","); + + for (int j = names.size() - 1; j >= 0; j--) { + String name = names[j]; + + // FIXME: Find it, in a horribly inefficient way. + int atidx = -1; + Control *node = nullptr; + for (int k = 0; k < DOCK_SLOT_MAX; k++) { + if (!dock_slot[k]->has_node(name)) { + continue; + } + node = Object::cast_to<Control>(dock_slot[k]->get_node(name)); + if (!node) { + continue; + } + atidx = k; + break; + } + + if (atidx == -1) { + // Try floating docks. + for (WindowWrapper *wrapper : floating_docks) { + if (wrapper->get_meta("dock_name") == name) { + if (restore_window_on_load && floating_docks_dump.has(name)) { + _restore_floating_dock(floating_docks_dump[name], wrapper, i); + } else { + atidx = wrapper->get_meta("dock_slot"); + node = wrapper->get_wrapped_control(); + wrapper->set_window_enabled(false); + } + break; + } + } + } + if (!node) { + // Well, it's not anywhere. + continue; + } + + if (atidx == i) { + dock_slot[i]->move_child(node, 0); + } else if (atidx != -1) { + dock_slot[i]->set_block_signals(true); + dock_slot[atidx]->set_block_signals(true); + dock_slot[i]->move_tab_from_tab_container(dock_slot[atidx], dock_slot[atidx]->get_tab_idx_from_control(node), 0); + dock_slot[i]->set_block_signals(false); + dock_slot[atidx]->set_block_signals(false); + } + + WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(node); + if (restore_window_on_load && floating_docks_dump.has(name)) { + if (!dock_slot[i]->is_tab_hidden(dock_slot[i]->get_tab_idx_from_control(node))) { + _restore_floating_dock(floating_docks_dump[name], node, i); + } + } else if (wrapper) { + wrapper->set_window_enabled(false); + } + } + + if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx")) { + continue; + } + + int selected_tab_idx = p_layout->get_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx"); + if (selected_tab_idx >= 0 && selected_tab_idx < dock_slot[i]->get_tab_count()) { + callable_mp(dock_slot[i], &TabContainer::set_current_tab).call_deferred(selected_tab_idx); + } + } + + for (int i = 0; i < vsplits.size(); i++) { + if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1))) { + continue; + } + + int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1)); + vsplits[i]->set_split_offset(ofs); + } + + for (int i = 0; i < hsplits.size(); i++) { + if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1))) { + continue; + } + int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1)); + hsplits[i]->set_split_offset(ofs); + } + + update_dock_slots_visibility(false); + + FileSystemDock::get_singleton()->load_layout_from_config(p_layout, p_section); +} + +void EditorDockManager::update_dock_slots_visibility(bool p_keep_selected_tabs) { + if (!docks_visible) { + for (int i = 0; i < DOCK_SLOT_MAX; i++) { + dock_slot[i]->hide(); + } + } else { + for (int i = 0; i < DOCK_SLOT_MAX; i++) { + int first_tab_visible = -1; + for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) { + if (!dock_slot[i]->is_tab_hidden(j)) { + first_tab_visible = j; + break; + } + } + if (first_tab_visible >= 0) { + dock_slot[i]->show(); + if (p_keep_selected_tabs) { + int current_tab = dock_slot[i]->get_current_tab(); + if (dock_slot[i]->is_tab_hidden(current_tab)) { + dock_slot[i]->set_block_signals(true); + dock_slot[i]->select_next_available(); + dock_slot[i]->set_block_signals(false); + } + } else { + dock_slot[i]->set_block_signals(true); + dock_slot[i]->set_current_tab(first_tab_visible); + dock_slot[i]->set_block_signals(false); + } + } else { + dock_slot[i]->hide(); + } + } + } +} + +void EditorDockManager::close_all_floating_docks() { + for (WindowWrapper *wrapper : floating_docks) { + wrapper->set_window_enabled(false); + } +} + +void EditorDockManager::add_control_to_dock(DockSlot p_slot, Control *p_control, const String &p_name) { + ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX); + dock_slot[p_slot]->add_child(p_control); + if (!p_name.is_empty()) { + dock_slot[p_slot]->set_tab_title(dock_slot[p_slot]->get_tab_idx_from_control(p_control), p_name); + } +} + +void EditorDockManager::remove_control_from_dock(Control *p_control) { + // If the dock is floating, close it first. + for (WindowWrapper *wrapper : floating_docks) { + if (p_control == wrapper->get_wrapped_control()) { + wrapper->set_window_enabled(false); + break; + } + } + + Control *dock = nullptr; + for (int i = 0; i < DOCK_SLOT_MAX; i++) { + if (p_control->get_parent() == dock_slot[i]) { + dock = dock_slot[i]; + break; + } + } + + ERR_FAIL_NULL_MSG(dock, "Control is not in a dock."); + + dock->remove_child(p_control); + update_dock_slots_visibility(); +} + +void EditorDockManager::set_docks_visible(bool p_show) { + docks_visible = p_show; + update_dock_slots_visibility(true); +} + +bool EditorDockManager::are_docks_visible() const { + return docks_visible; +} + +void EditorDockManager::add_vsplit(DockSplitContainer *p_split) { + vsplits.push_back(p_split); + p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged)); +} + +void EditorDockManager::add_hsplit(DockSplitContainer *p_split) { + hsplits.push_back(p_split); + p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged)); +} + +void EditorDockManager::register_dock_slot(DockSlot p_dock_slot, TabContainer *p_tab_container) { + ERR_FAIL_NULL(p_tab_container); + ERR_FAIL_INDEX(p_dock_slot, DOCK_SLOT_MAX); + + dock_slot[p_dock_slot] = p_tab_container; + + p_tab_container->set_custom_minimum_size(Size2(170, 0) * EDSCALE); + p_tab_container->set_v_size_flags(Control::SIZE_EXPAND_FILL); + p_tab_container->set_popup(dock_select_popup); + p_tab_container->connect("pre_popup_pressed", callable_mp(this, &EditorDockManager::_dock_pre_popup).bind(p_dock_slot)); + p_tab_container->set_drag_to_rearrange_enabled(true); + p_tab_container->set_tabs_rearrange_group(1); + p_tab_container->connect("tab_changed", callable_mp(this, &EditorDockManager::_dock_tab_changed)); + p_tab_container->set_use_hidden_tabs_for_min_size(true); +} + +int EditorDockManager::get_vsplit_count() const { + return vsplits.size(); +} + +void EditorDockManager::_bind_methods() { + ADD_SIGNAL(MethodInfo("layout_changed")); +} + +EditorDockManager::EditorDockManager() { + singleton = this; + + dock_select_popup = memnew(PopupPanel); + EditorNode::get_singleton()->get_gui_base()->add_child(dock_select_popup); + VBoxContainer *dock_vb = memnew(VBoxContainer); + dock_select_popup->add_child(dock_vb); + dock_select_popup->connect("theme_changed", callable_mp(this, &EditorDockManager::_dock_select_popup_theme_changed)); + + HBoxContainer *dock_hb = memnew(HBoxContainer); + dock_tab_move_left = memnew(Button); + dock_tab_move_left->set_flat(true); + dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE); + dock_tab_move_left->connect("pressed", callable_mp(this, &EditorDockManager::_dock_move_left)); + dock_hb->add_child(dock_tab_move_left); + + Label *dock_label = memnew(Label); + dock_label->set_text(TTR("Dock Position")); + dock_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); + dock_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); + dock_hb->add_child(dock_label); + + dock_tab_move_right = memnew(Button); + dock_tab_move_right->set_flat(true); + dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE); + dock_tab_move_right->connect("pressed", callable_mp(this, &EditorDockManager::_dock_move_right)); + + dock_hb->add_child(dock_tab_move_right); + dock_vb->add_child(dock_hb); + + dock_select = memnew(Control); + dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE); + dock_select->connect("gui_input", callable_mp(this, &EditorDockManager::_dock_select_input)); + dock_select->connect("draw", callable_mp(this, &EditorDockManager::_dock_select_draw)); + dock_select->connect("mouse_exited", callable_mp(this, &EditorDockManager::_dock_popup_exit)); + dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL); + dock_vb->add_child(dock_select); + + if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && !EDITOR_GET("interface/editor/single_window_mode") && EDITOR_GET("interface/multi_window/enable")) { + dock_float = memnew(Button); + dock_float->set_text(TTR("Make Floating")); + dock_float->set_focus_mode(Control::FOCUS_NONE); + dock_float->set_h_size_flags(Control::SIZE_SHRINK_CENTER); + dock_float->connect("pressed", callable_mp(this, &EditorDockManager::_dock_make_selected_float)); + + dock_vb->add_child(dock_float); + } + + dock_select_popup->reset_size(); +} diff --git a/editor/editor_dock_manager.h b/editor/editor_dock_manager.h new file mode 100644 index 0000000000..e685fe1380 --- /dev/null +++ b/editor/editor_dock_manager.h @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* editor_dock_manager.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef EDITOR_DOCK_MANAGER_H +#define EDITOR_DOCK_MANAGER_H + +#include "scene/gui/split_container.h" + +class Button; +class ConfigFile; +class Control; +class PopupPanel; +class TabContainer; +class WindowWrapper; + +class DockSplitContainer : public SplitContainer { + GDCLASS(DockSplitContainer, SplitContainer); + +private: + bool is_updating = false; + +protected: + void _update_visibility(); + + virtual void add_child_notify(Node *p_child) override; + virtual void remove_child_notify(Node *p_child) override; +}; + +class EditorDockManager : public Object { + GDCLASS(EditorDockManager, Object); + +public: + enum DockSlot { + DOCK_SLOT_LEFT_UL, + DOCK_SLOT_LEFT_BL, + DOCK_SLOT_LEFT_UR, + DOCK_SLOT_LEFT_BR, + DOCK_SLOT_RIGHT_UL, + DOCK_SLOT_RIGHT_BL, + DOCK_SLOT_RIGHT_UR, + DOCK_SLOT_RIGHT_BR, + DOCK_SLOT_MAX + }; + +private: + static EditorDockManager *singleton; + + // To access splits easily by index. + Vector<DockSplitContainer *> vsplits; + Vector<DockSplitContainer *> hsplits; + + Vector<WindowWrapper *> floating_docks; + TabContainer *dock_slot[DOCK_SLOT_MAX]; + bool docks_visible = true; + + PopupPanel *dock_select_popup = nullptr; + Button *dock_float = nullptr; + Button *dock_tab_move_left = nullptr; + Button *dock_tab_move_right = nullptr; + Control *dock_select = nullptr; + Rect2 dock_select_rect[DOCK_SLOT_MAX]; + int dock_select_rect_over_idx = -1; + int dock_popup_selected_idx = -1; + + void _dock_select_popup_theme_changed(); + void _dock_popup_exit(); + void _dock_pre_popup(int p_dock_slot); + void _dock_move_left(); + void _dock_move_right(); + void _dock_select_input(const Ref<InputEvent> &p_input); + void _dock_select_draw(); + void _dock_split_dragged(int p_offset); + + void _dock_tab_changed(int p_tab); + void _edit_current(); + + void _dock_floating_close_request(WindowWrapper *p_wrapper); + void _dock_make_selected_float(); + void _dock_make_float(Control *p_control, int p_slot_index, bool p_show_window = true); + void _restore_floating_dock(const Dictionary &p_dock_dump, Control *p_wrapper, int p_slot_index); + +protected: + static void _bind_methods(); + +public: + static EditorDockManager *get_singleton() { return singleton; } + + void add_vsplit(DockSplitContainer *p_split); + void add_hsplit(DockSplitContainer *p_split); + void register_dock_slot(DockSlot p_dock_slot, TabContainer *p_tab_container); + int get_vsplit_count() const; + + void save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const; + void load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section); + void update_dock_slots_visibility(bool p_keep_selected_tabs = false); + + void close_all_floating_docks(); + + void set_docks_visible(bool p_show); + bool are_docks_visible() const; + + void add_control_to_dock(DockSlot p_slot, Control *p_control, const String &p_name = ""); + void remove_control_from_dock(Control *p_control); + + EditorDockManager(); +}; + +#endif // EDITOR_DOCK_MANAGER_H diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 5a44ae1aba..aa44ea380b 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -35,10 +35,10 @@ #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = { TTRC("3D Editor"), @@ -503,7 +503,7 @@ void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const S bool disabled_editor = edited->is_class_editor_disabled(p_class); bool disabled_properties = edited->has_class_properties_disabled(p_class); if (disabled) { - class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + class_item->set_custom_color(0, class_list->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } else if (disabled_editor && disabled_properties) { text += " " + TTR("(Editor Disabled, Properties Disabled)"); } else if (disabled_properties) { diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 807f0c8eb7..9fbe7ba655 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -257,7 +257,7 @@ void EditorFileSystem::_scan_filesystem() { if (l.begins_with("::")) { Vector<String> split = l.split("::"); ERR_CONTINUE(split.size() != 3); - String name = split[1]; + const String &name = split[1]; cpath = name; @@ -290,7 +290,7 @@ void EditorFileSystem::_scan_filesystem() { if (deps.length()) { Vector<String> dp = deps.split("<>"); for (int i = 0; i < dp.size(); i++) { - String path = dp[i]; + const String &path = dp[i]; fc.deps.push_back(path); } } @@ -2354,7 +2354,11 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) { reimport_files.sort(); +#ifdef THREADS_ENABLED bool use_multiple_threads = GLOBAL_GET("editor/import/use_multiple_threads"); +#else + bool use_multiple_threads = false; +#endif int from = 0; for (int i = 0; i < reimport_files.size(); i++) { @@ -2436,7 +2440,13 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) { Error EditorFileSystem::reimport_append(const String &p_file, const HashMap<StringName, Variant> &p_custom_options, const String &p_custom_importer, Variant p_generator_parameters) { ERR_FAIL_COND_V_MSG(!importing, ERR_INVALID_PARAMETER, "Can only append files to import during a current reimport process."); - return _reimport_file(p_file, p_custom_options, p_custom_importer, &p_generator_parameters); + Error ret = _reimport_file(p_file, p_custom_options, p_custom_importer, &p_generator_parameters); + + // Emit the resource_reimported signal for the single file we just reimported. + Vector<String> reloads; + reloads.append(p_file); + emit_signal(SNAME("resources_reimported"), reloads); + return ret; } Error EditorFileSystem::_resource_import(const String &p_path) { @@ -2674,6 +2684,10 @@ void EditorFileSystem::remove_import_format_support_query(Ref<EditorFileSystemIm } EditorFileSystem::EditorFileSystem() { +#ifdef THREADS_ENABLED + use_threads = true; +#endif + ResourceLoader::import = _resource_import; reimport_on_missing_imported_files = GLOBAL_GET("editor/import/reimport_missing_imported_files"); singleton = this; @@ -2687,7 +2701,7 @@ EditorFileSystem::EditorFileSystem() { using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT"); scan_total = 0; - MessageQueue::get_singleton()->push_callable(callable_mp(ResourceUID::get_singleton(), &ResourceUID::clear)); // Will be updated on scan. + callable_mp(ResourceUID::get_singleton(), &ResourceUID::clear).call_deferred(); // Will be updated on scan. ResourceSaver::set_get_resource_id_for_path(_resource_saver_get_resource_id_for_path); } diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 2a34c06b0d..2f5cd88a55 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -165,7 +165,7 @@ class EditorFileSystem : public Node { EditorFileSystemDirectory::FileInfo *new_file = nullptr; }; - bool use_threads = true; + bool use_threads = false; Thread thread; static void _thread_func(void *_userdata); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 2b1ab4ca02..f0f7f87711 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -35,14 +35,14 @@ #include "core/object/script_language.h" #include "core/os/keyboard.h" #include "core/version.h" -#include "doc_data_compressed.gen.h" +#include "editor/doc_data_compressed.gen.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/line_edit.h" #define CONTRIBUTE_URL vformat("%s/contributing/documentation/updating_the_class_reference.html", VERSION_DOCS_URL) @@ -812,35 +812,25 @@ void EditorHelp::_update_doc() { class_desc->add_newline(); } - // Descendents - if (cd.is_script_doc || ClassDB::class_exists(cd.name)) { - bool found = false; - bool prev = false; - + // Descendants + if ((cd.is_script_doc || ClassDB::class_exists(cd.name)) && doc->inheriting.has(cd.name)) { _push_normal_font(); - for (const KeyValue<String, DocData::ClassDoc> &E : doc->class_list) { - if (E.value.inherits == cd.name) { - if (!found) { - class_desc->push_color(theme_cache.title_color); - class_desc->add_text(TTR("Inherited by:") + " "); - found = true; - } + class_desc->push_color(theme_cache.title_color); + class_desc->add_text(TTR("Inherited by:") + " "); - if (prev) { - class_desc->add_text(" , "); - } - _add_type_icon(E.value.name, theme_cache.doc_font_size, "ArrowRight"); - class_desc->add_text(non_breaking_space); // Otherwise icon borrows hyperlink from _add_type(). - _add_type(E.value.name); - prev = true; + for (RBSet<String, NaturalNoCaseComparator>::Element *itr = doc->inheriting[cd.name].front(); itr; itr = itr->next()) { + if (itr->prev()) { + class_desc->add_text(" , "); } + + _add_type_icon(itr->get(), theme_cache.doc_font_size, "ArrowRight"); + class_desc->add_text(non_breaking_space); // Otherwise icon borrows hyperlink from _add_type(). + _add_type(itr->get()); } _pop_normal_font(); - if (found) { - class_desc->pop(); - class_desc->add_newline(); - } + class_desc->pop(); + class_desc->add_newline(); } // Note if deprecated. @@ -1966,7 +1956,7 @@ void EditorHelp::_help_callback(const String &p_topic) { } if (class_desc->is_ready()) { - class_desc->call_deferred(SNAME("scroll_to_paragraph"), line); + callable_mp(class_desc, &RichTextLabel::scroll_to_paragraph).call_deferred(line); } else { scroll_to = line; } @@ -2867,10 +2857,10 @@ void EditorHelpTooltip::parse_tooltip(const String &p_text) { PackedStringArray slices = p_text.split("|", true, 3); ERR_FAIL_COND_MSG(slices.size() < 4, "Invalid tooltip formatting. The expect string should be formatted as 'type|class|property|args'."); - String type = slices[0]; - String class_name = slices[1]; - String property_name = slices[2]; - String property_args = slices[3]; + const String &type = slices[0]; + const String &class_name = slices[1]; + const String &property_name = slices[2]; + const String &property_args = slices[3]; String title; String description; diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 44698d93f6..229eb79e11 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -33,9 +33,9 @@ #include "core/os/keyboard.h" #include "editor/editor_feature_profile.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" void EditorHelpSearch::_update_results() { String term = search_box->get_text(); @@ -48,7 +48,7 @@ void EditorHelpSearch::_update_results() { search_flags |= SEARCH_SHOW_HIERARCHY; } - search = Ref<Runner>(memnew(Runner(results_tree, results_tree, term, search_flags))); + search = Ref<Runner>(memnew(Runner(results_tree, results_tree, &tree_cache, term, search_flags))); set_process(true); } @@ -96,7 +96,8 @@ void EditorHelpSearch::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { if (!is_visible()) { - results_tree->call_deferred(SNAME("clear")); // Wait for the Tree's mouse event propagation. + tree_cache.clear(); + callable_mp(results_tree, &Tree::clear).call_deferred(); // Wait for the Tree's mouse event propagation. get_ok_button()->set_disabled(true); EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "search_help", Rect2(get_position(), get_size())); } @@ -258,6 +259,13 @@ EditorHelpSearch::EditorHelpSearch() { vbox->add_child(results_tree, true); } +void EditorHelpSearch::TreeCache::clear() { + for (const KeyValue<String, TreeItem *> &E : item_cache) { + memdelete(E.value); + } + item_cache.clear(); +} + bool EditorHelpSearch::Runner::_is_class_disabled_by_feature_profile(const StringName &p_class) { Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile(); if (profile.is_null()) { @@ -317,7 +325,13 @@ bool EditorHelpSearch::Runner::_slice() { } bool EditorHelpSearch::Runner::_phase_match_classes_init() { - iterator_doc = EditorHelp::get_doc_data()->class_list.begin(); + iterator_doc = nullptr; + iterator_stack.clear(); + if (search_flags & SEARCH_SHOW_HIERARCHY) { + iterator_stack.push_back(EditorHelp::get_doc_data()->inheriting[""].front()); + } else { + iterator_doc = EditorHelp::get_doc_data()->class_list.begin(); + } matches.clear(); matched_item = nullptr; match_highest_score = 0; @@ -331,88 +345,141 @@ bool EditorHelpSearch::Runner::_phase_match_classes_init() { } bool EditorHelpSearch::Runner::_phase_match_classes() { - if (!iterator_doc) { + if (!iterator_doc && iterator_stack.is_empty()) { return true; } - DocData::ClassDoc &class_doc = iterator_doc->value; - if (class_doc.name.is_empty()) { - ++iterator_doc; - return false; + DocData::ClassDoc *class_doc = nullptr; + if (iterator_doc) { + class_doc = &iterator_doc->value; + } else if (!iterator_stack.is_empty() && iterator_stack[iterator_stack.size() - 1]) { + class_doc = EditorHelp::get_doc_data()->class_list.getptr(iterator_stack[iterator_stack.size() - 1]->get()); + } + + if (class_doc && class_doc->name.is_empty()) { + class_doc = nullptr; } - if (!_is_class_disabled_by_feature_profile(class_doc.name)) { + if (class_doc && !_is_class_disabled_by_feature_profile(class_doc->name)) { ClassMatch match; - match.doc = &class_doc; + match.doc = class_doc; // Match class name. if (search_flags & SEARCH_CLASSES) { // If the search term is empty, add any classes which are not script docs or which don't start with // a double-quotation. This will ensure that only C++ classes and explicitly named classes will // be added. - match.name = (term.is_empty() && (!class_doc.is_script_doc || class_doc.name[0] != '\"')) || _match_string(term, class_doc.name); + match.name = (term.is_empty() && (!class_doc->is_script_doc || class_doc->name[0] != '\"')) || _match_string(term, class_doc->name); } // Match members only if the term is long enough, to avoid slow performance from building a large tree. // Make an exception for annotations, since there are not that many of them. if (term.length() > 1 || term == "@") { if (search_flags & SEARCH_CONSTRUCTORS) { - _match_method_name_and_push_back(class_doc.constructors, &match.constructors); + _match_method_name_and_push_back(class_doc->constructors, &match.constructors); } if (search_flags & SEARCH_METHODS) { - _match_method_name_and_push_back(class_doc.methods, &match.methods); + _match_method_name_and_push_back(class_doc->methods, &match.methods); } if (search_flags & SEARCH_OPERATORS) { - _match_method_name_and_push_back(class_doc.operators, &match.operators); + _match_method_name_and_push_back(class_doc->operators, &match.operators); } if (search_flags & SEARCH_SIGNALS) { - for (int i = 0; i < class_doc.signals.size(); i++) { - if (_all_terms_in_name(class_doc.signals[i].name)) { - match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc.signals[i])); + for (int i = 0; i < class_doc->signals.size(); i++) { + if (_all_terms_in_name(class_doc->signals[i].name)) { + match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc->signals[i])); } } } if (search_flags & SEARCH_CONSTANTS) { - for (int i = 0; i < class_doc.constants.size(); i++) { - if (_all_terms_in_name(class_doc.constants[i].name)) { - match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc.constants[i])); + for (int i = 0; i < class_doc->constants.size(); i++) { + if (_all_terms_in_name(class_doc->constants[i].name)) { + match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc->constants[i])); } } } if (search_flags & SEARCH_PROPERTIES) { - for (int i = 0; i < class_doc.properties.size(); i++) { - if (_all_terms_in_name(class_doc.properties[i].name)) { - match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.properties[i])); + for (int i = 0; i < class_doc->properties.size(); i++) { + if (_all_terms_in_name(class_doc->properties[i].name)) { + match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc->properties[i])); } } } if (search_flags & SEARCH_THEME_ITEMS) { - for (int i = 0; i < class_doc.theme_properties.size(); i++) { - if (_all_terms_in_name(class_doc.theme_properties[i].name)) { - match.theme_properties.push_back(const_cast<DocData::ThemeItemDoc *>(&class_doc.theme_properties[i])); + for (int i = 0; i < class_doc->theme_properties.size(); i++) { + if (_all_terms_in_name(class_doc->theme_properties[i].name)) { + match.theme_properties.push_back(const_cast<DocData::ThemeItemDoc *>(&class_doc->theme_properties[i])); } } } if (search_flags & SEARCH_ANNOTATIONS) { - for (int i = 0; i < class_doc.annotations.size(); i++) { - if (_match_string(term, class_doc.annotations[i].name)) { - match.annotations.push_back(const_cast<DocData::MethodDoc *>(&class_doc.annotations[i])); + for (int i = 0; i < class_doc->annotations.size(); i++) { + if (_match_string(term, class_doc->annotations[i].name)) { + match.annotations.push_back(const_cast<DocData::MethodDoc *>(&class_doc->annotations[i])); } } } } - matches[class_doc.name] = match; + matches[class_doc->name] = match; } - ++iterator_doc; - return !iterator_doc; + if (iterator_doc) { + ++iterator_doc; + return !iterator_doc; + } + + if (!iterator_stack.is_empty()) { + if (iterator_stack[iterator_stack.size() - 1]) { + iterator_stack[iterator_stack.size() - 1] = iterator_stack[iterator_stack.size() - 1]->next(); + } + if (!iterator_stack[iterator_stack.size() - 1]) { + iterator_stack.resize(iterator_stack.size() - 1); + } + } + + if (class_doc && EditorHelp::get_doc_data()->inheriting.has(class_doc->name)) { + iterator_stack.push_back(EditorHelp::get_doc_data()->inheriting[class_doc->name].front()); + } + + return iterator_stack.is_empty(); +} + +void EditorHelpSearch::Runner::_populate_cache() { + root_item = results_tree->get_root(); + + if (root_item) { + LocalVector<TreeItem *> stack; + + // Add children of root item to stack. + for (TreeItem *child = root_item->get_first_child(); child; child = child->get_next()) { + stack.push_back(child); + } + + // Traverse stack and cache items. + while (!stack.is_empty()) { + TreeItem *cur_item = stack[stack.size() - 1]; + stack.resize(stack.size() - 1); + + // Add to the cache. + tree_cache->item_cache.insert(cur_item->get_metadata(0).operator String(), cur_item); + + // Add any children to the stack. + for (TreeItem *child = cur_item->get_first_child(); child; child = child->get_next()) { + stack.push_back(child); + } + + // Remove from parent. + cur_item->get_parent()->remove_child(cur_item); + } + } else { + root_item = results_tree->create_item(); + } } bool EditorHelpSearch::Runner::_phase_class_items_init() { iterator_match = matches.begin(); - results_tree->clear(); - root_item = results_tree->create_item(); + _populate_cache(); class_items.clear(); return true; @@ -590,27 +657,54 @@ TreeItem *EditorHelpSearch::Runner::_create_class_hierarchy(const ClassMatch &p_ return class_item; } +bool EditorHelpSearch::Runner::_find_or_create_item(TreeItem *p_parent, const String &p_item_meta, TreeItem *&r_item) { + // Attempt to find in cache. + if (tree_cache->item_cache.has(p_item_meta)) { + r_item = tree_cache->item_cache[p_item_meta]; + + // Remove from cache. + tree_cache->item_cache.erase(p_item_meta); + + // Add to tree. + p_parent->add_child(r_item); + + return false; + } else { + // Otherwise create item. + r_item = results_tree->create_item(p_parent); + + return true; + } +} + TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray) { String tooltip = DTR(p_doc->brief_description.strip_edges()); - TreeItem *item = results_tree->create_item(p_parent); - item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_doc->name)); - item->set_text(0, p_doc->name); - item->set_text(1, TTR("Class")); - item->set_tooltip_text(0, tooltip); - item->set_tooltip_text(1, tooltip); - item->set_metadata(0, "class_name:" + p_doc->name); + const String item_meta = "class_name:" + p_doc->name; + + TreeItem *item = nullptr; + if (_find_or_create_item(p_parent, item_meta, item)) { + item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_doc->name)); + item->set_text(0, p_doc->name); + item->set_text(1, TTR("Class")); + item->set_tooltip_text(0, tooltip); + item->set_tooltip_text(1, tooltip); + item->set_metadata(0, item_meta); + if (p_doc->is_deprecated) { + Ref<Texture2D> error_icon = ui_service->get_editor_theme_icon(SNAME("StatusError")); + item->add_button(0, error_icon, 0, false, TTR("This class is marked as deprecated.")); + } else if (p_doc->is_experimental) { + Ref<Texture2D> warning_icon = ui_service->get_editor_theme_icon(SNAME("NodeWarning")); + item->add_button(0, warning_icon, 0, false, TTR("This class is marked as experimental.")); + } + } + if (p_gray) { item->set_custom_color(0, disabled_color); item->set_custom_color(1, disabled_color); - } - - if (p_doc->is_deprecated) { - Ref<Texture2D> error_icon = ui_service->get_editor_theme_icon("StatusError"); - item->add_button(0, error_icon, 0, false, TTR("This class is marked as deprecated.")); - } else if (p_doc->is_experimental) { - Ref<Texture2D> warning_icon = ui_service->get_editor_theme_icon("NodeWarning"); - item->add_button(0, warning_icon, 0, false, TTR("This class is marked as experimental.")); + } else { + item->clear_custom_color(0); + item->clear_custom_color(1); } _match_item(item, p_doc->name); @@ -651,30 +745,29 @@ TreeItem *EditorHelpSearch::Runner::_create_theme_property_item(TreeItem *p_pare } TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_text, const String &p_type, const String &p_metatype, const String &p_tooltip, bool is_deprecated, bool is_experimental) { - Ref<Texture2D> icon; - String text; - if (search_flags & SEARCH_SHOW_HIERARCHY) { - icon = ui_service->get_editor_theme_icon(p_icon); - text = p_text; - } else { - icon = ui_service->get_editor_theme_icon(p_icon); - text = p_class_name + "." + p_text; + const String item_meta = "class_" + p_metatype + ":" + p_class_name + ":" + p_name; + + TreeItem *item = nullptr; + if (_find_or_create_item(p_parent, item_meta, item)) { + item->set_icon(0, ui_service->get_editor_theme_icon(p_icon)); + item->set_text(1, TTRGET(p_type)); + item->set_tooltip_text(0, p_tooltip); + item->set_tooltip_text(1, p_tooltip); + item->set_metadata(0, item_meta); + + if (is_deprecated) { + Ref<Texture2D> error_icon = ui_service->get_editor_theme_icon(SNAME("StatusError")); + item->add_button(0, error_icon, 0, false, TTR("This member is marked as deprecated.")); + } else if (is_experimental) { + Ref<Texture2D> warning_icon = ui_service->get_editor_theme_icon(SNAME("NodeWarning")); + item->add_button(0, warning_icon, 0, false, TTR("This member is marked as experimental.")); + } } - TreeItem *item = results_tree->create_item(p_parent); - item->set_icon(0, icon); - item->set_text(0, text); - item->set_text(1, TTRGET(p_type)); - item->set_tooltip_text(0, p_tooltip); - item->set_tooltip_text(1, p_tooltip); - item->set_metadata(0, "class_" + p_metatype + ":" + p_class_name + ":" + p_name); - - if (is_deprecated) { - Ref<Texture2D> error_icon = ui_service->get_editor_theme_icon("StatusError"); - item->add_button(0, error_icon, 0, false, TTR("This member is marked as deprecated.")); - } else if (is_experimental) { - Ref<Texture2D> warning_icon = ui_service->get_editor_theme_icon("NodeWarning"); - item->add_button(0, warning_icon, 0, false, TTR("This member is marked as experimental.")); + if (search_flags & SEARCH_SHOW_HIERARCHY) { + item->set_text(0, p_text); + } else { + item->set_text(0, p_class_name + "." + p_text); } _match_item(item, p_name); @@ -693,10 +786,11 @@ bool EditorHelpSearch::Runner::work(uint64_t slot) { return true; } -EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, const String &p_term, int p_search_flags) : +EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, TreeCache *p_tree_cache, const String &p_term, int p_search_flags) : ui_service(p_icon_service), results_tree(p_results_tree), + tree_cache(p_tree_cache), term((p_search_flags & SEARCH_CASE_SENSITIVE) == 0 ? p_term.strip_edges().to_lower() : p_term.strip_edges()), search_flags(p_search_flags), - disabled_color(ui_service->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))) { + disabled_color(ui_service->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))) { } diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h index 30a783a628..e4980d6ff7 100644 --- a/editor/editor_help_search.h +++ b/editor/editor_help_search.h @@ -67,6 +67,16 @@ class EditorHelpSearch : public ConfirmationDialog { class Runner; Ref<Runner> search; + struct TreeCache { + HashMap<String, TreeItem *> item_cache; + + void clear(); + + ~TreeCache() { + clear(); + } + } tree_cache; + void _update_results(); void _search_box_gui_input(const Ref<InputEvent> &p_event); @@ -117,6 +127,7 @@ class EditorHelpSearch::Runner : public RefCounted { Control *ui_service = nullptr; Tree *results_tree = nullptr; + TreeCache *tree_cache = nullptr; String term; Vector<String> terms; int search_flags; @@ -124,6 +135,7 @@ class EditorHelpSearch::Runner : public RefCounted { Color disabled_color; HashMap<String, DocData::ClassDoc>::Iterator iterator_doc; + LocalVector<RBSet<String, NaturalNoCaseComparator>::Element *> iterator_stack; HashMap<String, ClassMatch> matches; HashMap<String, ClassMatch>::Iterator iterator_match; TreeItem *root_item = nullptr; @@ -133,6 +145,9 @@ class EditorHelpSearch::Runner : public RefCounted { bool _is_class_disabled_by_feature_profile(const StringName &p_class); + void _populate_cache(); + bool _find_or_create_item(TreeItem *p_parent, const String &p_item_meta, TreeItem *&r_item); + bool _slice(); bool _phase_match_classes_init(); bool _phase_match_classes(); @@ -161,7 +176,7 @@ class EditorHelpSearch::Runner : public RefCounted { public: bool work(uint64_t slot = 100000); - Runner(Control *p_icon_service, Tree *p_results_tree, const String &p_term, int p_search_flags); + Runner(Control *p_icon_service, Tree *p_results_tree, TreeCache *p_tree_cache, const String &p_term, int p_search_flags); }; #endif // EDITOR_HELP_SEARCH_H diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 59816a0eca..a3530fc9ab 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -35,14 +35,14 @@ #include "editor/editor_feature_profile.h" #include "editor/editor_node.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_validation_panel.h" #include "editor/inspector_dock.h" +#include "editor/multi_node_edit.h" #include "editor/plugins/script_editor_plugin.h" -#include "multi_node_edit.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/spin_box.h" #include "scene/gui/texture_rect.h" #include "scene/property_utils.h" @@ -695,15 +695,14 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { new_coords.y++; } if (new_coords.x < int64_t(object->get("hframes")) && new_coords.y < int64_t(object->get("vframes"))) { - call_deferred(SNAME("emit_changed"), property, new_coords, "", false); + callable_mp(this, &EditorProperty::emit_changed).call_deferred(property, new_coords, "", false); } } else { if (int64_t(object->get(property)) + 1 < (int64_t(object->get("hframes")) * int64_t(object->get("vframes")))) { - call_deferred(SNAME("emit_changed"), property, object->get(property).operator int64_t() + 1, "", false); + callable_mp(this, &EditorProperty::emit_changed).call_deferred(property, object->get(property).operator int64_t() + 1, "", false); } } - - call_deferred(SNAME("update_property")); + callable_mp(this, &EditorProperty::update_property).call_deferred(); } } if (delete_rect.has_point(mpos)) { @@ -1358,7 +1357,7 @@ void EditorInspectorSection::_notification(int p_what) { Ref<Font> light_font = get_theme_font(SNAME("main"), EditorStringName(EditorFonts)); int light_font_size = get_theme_font_size(SNAME("main_size"), EditorStringName(EditorFonts)); - Color light_font_color = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)); + Color light_font_color = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)); // Can we fit the long version of the revertable count text? num_revertable_str = vformat(TTRN("(%d change)", "(%d changes)", revertable_properties.size()), revertable_properties.size()); @@ -3021,7 +3020,7 @@ void EditorInspector::update_tree() { Vector<String> components = path.split("/"); for (int i = 0; i < components.size(); i++) { - String component = components[i]; + const String &component = components[i]; acc_path += (i > 0) ? "/" + component : component; if (!vbox_per_path[root_vbox].has(acc_path)) { @@ -3980,7 +3979,7 @@ void EditorInspector::_notification(int p_what) { case NOTIFICATION_PROCESS: { if (update_scroll_request >= 0) { - get_v_scroll_bar()->call_deferred(SNAME("set_value"), update_scroll_request); + callable_mp((Range *)get_v_scroll_bar(), &Range::set_value).call_deferred(update_scroll_request); update_scroll_request = -1; } if (update_tree_pending) { @@ -4209,6 +4208,7 @@ EditorInspector::EditorInspector() { main_vbox->add_theme_constant_override("separation", 0); add_child(main_vbox); set_horizontal_scroll_mode(SCROLL_MODE_DISABLED); + set_follow_focus(true); changing = 0; search_box = nullptr; diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp index e179a0e18a..bad28ff43d 100644 --- a/editor/editor_interface.cpp +++ b/editor/editor_interface.cpp @@ -35,13 +35,13 @@ #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" #include "editor/gui/editor_run_bar.h" #include "editor/inspector_dock.h" #include "editor/plugins/node_3d_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "main/main.h" #include "scene/gui/box_container.h" #include "scene/gui/control.h" @@ -127,7 +127,7 @@ Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh Vector<Ref<Texture2D>> textures; for (int i = 0; i < p_meshes.size(); i++) { - Ref<Mesh> mesh = p_meshes[i]; + const Ref<Mesh> &mesh = p_meshes[i]; if (!mesh.is_valid()) { textures.push_back(Ref<Texture2D>()); continue; @@ -400,6 +400,21 @@ bool EditorInterface::is_movie_maker_enabled() const { } // Base. +void EditorInterface::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + String pf = p_function; + if (p_idx == 0) { + if (pf == "set_main_screen_editor") { + for (String E : { "\"2D\"", "\"3D\"", "\"Script\"", "\"AssetLib\"" }) { + r_options->push_back(E); + } + } else if (pf == "get_editor_viewport_3d") { + for (uint32_t i = 0; i < Node3DEditor::VIEWPORTS_COUNT; i++) { + r_options->push_back(String::num_int64(i)); + } + } + } + Object::get_argument_options(p_function, p_idx, r_options); +} void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("restart_editor", "save"), &EditorInterface::restart_editor, DEFVAL(true)); diff --git a/editor/editor_interface.h b/editor/editor_interface.h index 079fc169f2..73e89ae2f2 100644 --- a/editor/editor_interface.h +++ b/editor/editor_interface.h @@ -152,6 +152,8 @@ public: // Base. + virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; + static void create(); static void free(); diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp index dce61f66d3..e1b370f44a 100644 --- a/editor/editor_layouts_dialog.cpp +++ b/editor/editor_layouts_dialog.cpp @@ -33,8 +33,8 @@ #include "core/io/config_file.h" #include "core/object/class_db.h" #include "core/os/keyboard.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/item_list.h" #include "scene/gui/line_edit.h" @@ -114,6 +114,7 @@ EditorLayoutsDialog::EditorLayoutsDialog() { add_child(makevb); layout_names = memnew(ItemList); + layout_names->set_auto_translate(false); layout_names->set_auto_height(true); layout_names->set_custom_minimum_size(Size2(300 * EDSCALE, 50 * EDSCALE)); layout_names->set_visible(true); diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp index 13b4a8c128..f1d82557fd 100644 --- a/editor/editor_locale_dialog.cpp +++ b/editor/editor_locale_dialog.cpp @@ -31,8 +31,8 @@ #include "editor_locale_dialog.h" #include "core/config/project_settings.h" -#include "editor/editor_scale.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_button.h" #include "scene/gui/line_edit.h" #include "scene/gui/option_button.h" diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index c58a0a7572..c0c26bbfeb 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -35,9 +35,9 @@ #include "core/version.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/center_container.h" #include "scene/gui/separator.h" #include "scene/resources/font.h" @@ -192,6 +192,10 @@ void EditorLog::_load_state() { is_loading_state = false; } +void EditorLog::_meta_clicked(const String &p_meta) { + OS::get_singleton()->shell_open(p_meta); +} + void EditorLog::_clear_request() { log->clear(); messages.clear(); @@ -407,6 +411,7 @@ EditorLog::EditorLog() { log->set_v_size_flags(SIZE_EXPAND_FILL); log->set_h_size_flags(SIZE_EXPAND_FILL); log->set_deselect_on_focus_loss_enabled(false); + log->connect("meta_clicked", callable_mp(this, &EditorLog::_meta_clicked)); vb_left->add_child(log); // Search box diff --git a/editor/editor_log.h b/editor/editor_log.h index 07f3a25c3e..03a0a071c6 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -157,6 +157,7 @@ private: Thread::ID current; //void _dragged(const Point2& p_ofs); + void _meta_clicked(const String &p_meta); void _clear_request(); void _copy_request(); static void _undo_redo_cbk(void *p_self, const String &p_name); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bd09019671..521477d470 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -38,7 +38,6 @@ #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/object/class_db.h" -#include "core/object/message_queue.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/os/time.h" @@ -80,6 +79,7 @@ #include "editor/editor_build_profile.h" #include "editor/editor_command_palette.h" #include "editor/editor_data.h" +#include "editor/editor_dock_manager.h" #include "editor/editor_feature_profile.h" #include "editor/editor_folding.h" #include "editor/editor_help.h" @@ -96,10 +96,8 @@ #include "editor/editor_resource_preview.h" #include "editor/editor_run.h" #include "editor/editor_run_native.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_settings_dialog.h" -#include "editor/editor_themes.h" #include "editor/editor_translation_parser.h" #include "editor/editor_undo_redo_manager.h" #include "editor/export/editor_export.h" @@ -113,9 +111,12 @@ #include "editor/gui/editor_title_bar.h" #include "editor/gui/editor_toaster.h" #include "editor/history_dock.h" +#include "editor/import/3d/editor_import_collada.h" +#include "editor/import/3d/resource_importer_obj.h" +#include "editor/import/3d/resource_importer_scene.h" +#include "editor/import/3d/scene_import_settings.h" #include "editor/import/audio_stream_import_settings.h" #include "editor/import/dynamic_font_import_settings.h" -#include "editor/import/editor_import_collada.h" #include "editor/import/resource_importer_bitmask.h" #include "editor/import/resource_importer_bmfont.h" #include "editor/import/resource_importer_csv_translation.h" @@ -123,12 +124,10 @@ #include "editor/import/resource_importer_image.h" #include "editor/import/resource_importer_imagefont.h" #include "editor/import/resource_importer_layered_texture.h" -#include "editor/import/resource_importer_obj.h" #include "editor/import/resource_importer_shader_file.h" #include "editor/import/resource_importer_texture.h" #include "editor/import/resource_importer_texture_atlas.h" #include "editor/import/resource_importer_wav.h" -#include "editor/import/scene_import_settings.h" #include "editor/import_dock.h" #include "editor/inspector_dock.h" #include "editor/multi_node_edit.h" @@ -157,6 +156,8 @@ #include "editor/register_exporters.h" #include "editor/scene_tree_dock.h" #include "editor/surface_upgrade_tool.h" +#include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme_manager.h" #include "editor/window_wrapper.h" #include <stdio.h> @@ -177,7 +178,7 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto Vector<RBSet<int>> index_sets; HashMap<String, int> scene_name_to_set_index; for (int i = 0; i < r_filenames.size(); i++) { - String scene_name = r_filenames[i]; + const String &scene_name = r_filenames[i]; if (!scene_name_to_set_index.has(scene_name)) { index_sets.append(RBSet<int>()); scene_name_to_set_index.insert(r_filenames[i], index_sets.size() - 1); @@ -233,7 +234,7 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto if (E->get() == F) { continue; } - String other_scene_name = r_filenames[F]; + const String &other_scene_name = r_filenames[F]; if (other_scene_name == scene_name) { duplicate_found = true; break; @@ -468,7 +469,7 @@ void EditorNode::_select_default_main_screen_plugin() { void EditorNode::_update_theme(bool p_skip_creation) { if (!p_skip_creation) { - theme = create_custom_theme(theme); + theme = EditorThemeManager::generate_theme(theme); DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor))); } @@ -507,14 +508,6 @@ void EditorNode::_update_theme(bool p_skip_creation) { distraction_free->set_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons))); bottom_panel_raise->set_icon(theme->get_icon(SNAME("ExpandBottomDock"), EditorStringName(EditorIcons))); - if (gui_base->is_layout_rtl()) { - dock_tab_move_left->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons))); - dock_tab_move_right->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons))); - } else { - dock_tab_move_left->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons))); - dock_tab_move_right->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons))); - } - help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons))); help_menu->set_item_icon(help_menu->get_item_index(HELP_DOCS), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons))); help_menu->set_item_icon(help_menu->get_item_index(HELP_QA), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons))); @@ -667,7 +660,7 @@ void EditorNode::_notification(int p_what) { command_palette->register_shortcuts_as_command(); - MessageQueue::get_singleton()->push_callable(callable_mp(this, &EditorNode::_begin_first_scan)); + callable_mp(this, &EditorNode::_begin_first_scan).call_deferred(); /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; @@ -771,19 +764,7 @@ void EditorNode::_notification(int p_what) { EditorFileDialog::set_default_show_hidden_files(EDITOR_GET("filesystem/file_dialog/show_hidden_files")); EditorFileDialog::set_default_display_mode((EditorFileDialog::DisplayMode)EDITOR_GET("filesystem/file_dialog/display_mode").operator int()); - bool theme_changed = - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") || - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/font") || - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/main_font") || - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/code_font") || - EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") || - EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") || - EditorSettings::get_singleton()->check_changed_settings_in_group("filesystem/file_dialog/thumbnail_size") || - EditorSettings::get_singleton()->check_changed_settings_in_group("run/output/font_size") || - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") || - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles"); - - if (theme_changed) { + if (EditorThemeManager::is_generated_theme_outdated()) { _update_theme(); } @@ -1106,7 +1087,7 @@ void EditorNode::_scan_external_changes() { } if (need_reload) { - disk_changed->call_deferred(SNAME("popup_centered_ratio"), 0.3); + callable_mp((Window *)disk_changed, &Window::popup_centered_ratio).call_deferred(0.3); } } @@ -2095,7 +2076,7 @@ void EditorNode::_dialog_action(String p_file) { return; } - _save_docks_to_config(config, p_file); + editor_dock_manager->save_docks_to_config(config, p_file); config->save(EditorSettings::get_singleton()->get_editor_layouts_config()); @@ -3012,6 +2993,16 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case SET_RENDERER_NAME_SAVE_AND_RESTART: { ProjectSettings::get_singleton()->set("rendering/renderer/rendering_method", renderer_request); + if (renderer_request == "mobile" || renderer_request == "gl_compatibility") { + // Also change the mobile override if changing to a compatible rendering method. + // This prevents visual discrepancies between desktop and mobile platforms. + ProjectSettings::get_singleton()->set("rendering/renderer/rendering_method.mobile", renderer_request); + } else if (renderer_request == "forward_plus") { + // Use the equivalent mobile rendering method. This prevents the rendering method from staying + // on its old choice if moving from `gl_compatibility` to `forward_plus`. + ProjectSettings::get_singleton()->set("rendering/renderer/rendering_method.mobile", "mobile"); + } + ProjectSettings::get_singleton()->save(); save_all_scenes(); @@ -3696,7 +3687,7 @@ void EditorNode::_set_current_scene_nocheck(int p_idx) { callable_mp(scene_tabs, &EditorSceneTabs::update_scene_tabs).call_deferred(); if (tabs_to_close.is_empty()) { - call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // Do after everything else is done setting up. + callable_mp(this, &EditorNode::_set_main_scene_state).call_deferred(state, get_edited_scene()); // Do after everything else is done setting up. } } @@ -4086,7 +4077,7 @@ bool EditorNode::has_previous_scenes() const { void EditorNode::edit_foreign_resource(Ref<Resource> p_resource) { load_scene(p_resource->get_path().get_slice("::", 0)); - InspectorDock::get_singleton()->call_deferred("edit_resource", p_resource); + callable_mp(InspectorDock::get_singleton(), &InspectorDock::edit_resource).call_deferred(p_resource); } bool EditorNode::is_resource_read_only(Ref<Resource> p_resource, bool p_foreign_resources_are_writable) { @@ -4165,7 +4156,7 @@ void EditorNode::_add_to_recent_scenes(const String &p_scene) { void EditorNode::_open_recent_scene(int p_idx) { if (p_idx == recent_scenes->get_item_count() - 1) { EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", Array()); - call_deferred(SNAME("_update_recent_scenes")); + callable_mp(this, &EditorNode::_update_recent_scenes).call_deferred(); } else { Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array()); ERR_FAIL_INDEX(p_idx, rc.size()); @@ -4198,7 +4189,7 @@ void EditorNode::_quick_opened() { bool open_scene_dialog = quick_open->get_base_type() == "PackedScene"; for (int i = 0; i < files.size(); i++) { - String res_path = files[i]; + const String &res_path = files[i]; if (open_scene_dialog || ClassDB::is_parent_class(ResourceLoader::get_resource_type(res_path), "PackedScene")) { open_request(res_path); } else { @@ -4596,8 +4587,8 @@ String EditorNode::_get_system_info() const { } graphics += rendering_device_name; if (video_adapter_driver_info.size() == 2) { // This vector is always either of length 0 or 2. - String vad_name = video_adapter_driver_info[0]; - String vad_version = video_adapter_driver_info[1]; // Version could be potentially empty on Linux/BSD. + const String &vad_name = video_adapter_driver_info[0]; + const String &vad_version = video_adapter_driver_info[1]; // Version could be potentially empty on Linux/BSD. if (!vad_version.is_empty()) { graphics += vformat(" (%s; %s)", vad_name, vad_version); } else { @@ -4728,240 +4719,6 @@ void EditorNode::_copy_warning(const String &p_str) { DisplayServer::get_singleton()->clipboard_set(warning->get_text()); } -void EditorNode::_dock_floating_close_request(WindowWrapper *p_wrapper) { - int dock_slot_num = p_wrapper->get_meta("dock_slot"); - int dock_slot_index = p_wrapper->get_meta("dock_index"); - - // Give back the dock to the original owner. - Control *dock = p_wrapper->release_wrapped_control(); - - int target_index = MIN(dock_slot_index, dock_slot[dock_slot_num]->get_tab_count()); - dock_slot[dock_slot_num]->add_child(dock); - dock_slot[dock_slot_num]->move_child(dock, target_index); - dock_slot[dock_slot_num]->set_current_tab(target_index); - - floating_docks.erase(p_wrapper); - p_wrapper->queue_free(); - - _update_dock_slots_visibility(true); - - _edit_current(); -} - -void EditorNode::_dock_make_selected_float() { - Control *dock = dock_slot[dock_popup_selected_idx]->get_current_tab_control(); - _dock_make_float(dock, dock_popup_selected_idx); - - dock_select_popup->hide(); - _edit_current(); -} - -void EditorNode::_dock_make_float(Control *p_dock, int p_slot_index, bool p_show_window) { - ERR_FAIL_NULL(p_dock); - - Size2 borders = Size2(4, 4) * EDSCALE; - // Remember size and position before removing it from the main window. - Size2 dock_size = p_dock->get_size() + borders * 2; - Point2 dock_screen_pos = p_dock->get_screen_position(); - - int dock_index = p_dock->get_index() - 1; - dock_slot[p_slot_index]->remove_child(p_dock); - - WindowWrapper *wrapper = memnew(WindowWrapper); - wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), p_dock->get_name())); - wrapper->set_margins_enabled(true); - - gui_base->add_child(wrapper); - - wrapper->set_wrapped_control(p_dock); - wrapper->set_meta("dock_slot", p_slot_index); - wrapper->set_meta("dock_index", dock_index); - wrapper->set_meta("dock_name", p_dock->get_name().operator String()); - p_dock->show(); - - wrapper->connect("window_close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request).bind(wrapper)); - - dock_select_popup->hide(); - - if (p_show_window) { - wrapper->restore_window(Rect2i(dock_screen_pos, dock_size), get_window()->get_current_screen()); - } - - _update_dock_slots_visibility(true); - - floating_docks.push_back(wrapper); - - _edit_current(); -} - -void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { - Ref<InputEventMouse> me = p_input; - - if (me.is_valid()) { - Vector2 point = me->get_position(); - - int nrect = -1; - for (int i = 0; i < DOCK_SLOT_MAX; i++) { - if (dock_select_rect[i].has_point(point)) { - nrect = i; - break; - } - } - - if (nrect != dock_select_rect_over_idx) { - dock_select->queue_redraw(); - dock_select_rect_over_idx = nrect; - } - - if (nrect == -1) { - return; - } - - Ref<InputEventMouseButton> mb = me; - - if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && dock_popup_selected_idx != nrect) { - dock_slot[nrect]->move_tab_from_tab_container(dock_slot[dock_popup_selected_idx], dock_slot[dock_popup_selected_idx]->get_current_tab(), dock_slot[nrect]->get_tab_count()); - - if (dock_slot[dock_popup_selected_idx]->get_tab_count() == 0) { - dock_slot[dock_popup_selected_idx]->hide(); - } else { - dock_slot[dock_popup_selected_idx]->set_current_tab(0); - } - - dock_popup_selected_idx = nrect; - dock_slot[nrect]->show(); - dock_select->queue_redraw(); - - _update_dock_slots_visibility(true); - - _edit_current(); - _save_editor_layout(); - } - } -} - -void EditorNode::_dock_popup_exit() { - dock_select_rect_over_idx = -1; - dock_select->queue_redraw(); -} - -void EditorNode::_dock_pre_popup(int p_which) { - dock_popup_selected_idx = p_which; -} - -void EditorNode::_dock_move_left() { - if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) { - return; - } - Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab()); - Control *prev_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() - 1); - if (!current_ctl || !prev_ctl) { - return; - } - dock_slot[dock_popup_selected_idx]->move_child(current_ctl, prev_ctl->get_index(false)); - dock_select->queue_redraw(); - _edit_current(); - _save_editor_layout(); -} - -void EditorNode::_dock_move_right() { - Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab()); - Control *next_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() + 1); - if (!current_ctl || !next_ctl) { - return; - } - dock_slot[dock_popup_selected_idx]->move_child(next_ctl, current_ctl->get_index(false)); - dock_select->queue_redraw(); - _edit_current(); - _save_editor_layout(); -} - -void EditorNode::_dock_select_draw() { - Size2 s = dock_select->get_size(); - s.y /= 2.0; - s.x /= 6.0; - - Color used = Color(0.6, 0.6, 0.6, 0.8); - Color used_selected = Color(0.8, 0.8, 0.8, 0.8); - Color tab_selected = theme->get_color(SNAME("mono_color"), EditorStringName(Editor)); - Color unused = used; - unused.a = 0.4; - Color unusable = unused; - unusable.a = 0.1; - - Rect2 unr(s.x * 2, 0, s.x * 2, s.y * 2); - unr.position += Vector2(2, 5); - unr.size -= Vector2(4, 7); - - dock_select->draw_rect(unr, unusable); - - dock_tab_move_left->set_disabled(true); - dock_tab_move_right->set_disabled(true); - - if (dock_popup_selected_idx != -1 && dock_slot[dock_popup_selected_idx]->get_tab_count()) { - dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() == 0); - dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() >= dock_slot[dock_popup_selected_idx]->get_tab_count() - 1); - } - - for (int i = 0; i < DOCK_SLOT_MAX; i++) { - Vector2 ofs; - - switch (i) { - case DOCK_SLOT_LEFT_UL: { - } break; - case DOCK_SLOT_LEFT_BL: { - ofs.y += s.y; - } break; - case DOCK_SLOT_LEFT_UR: { - ofs.x += s.x; - } break; - case DOCK_SLOT_LEFT_BR: { - ofs += s; - } break; - case DOCK_SLOT_RIGHT_UL: { - ofs.x += s.x * 4; - } break; - case DOCK_SLOT_RIGHT_BL: { - ofs.x += s.x * 4; - ofs.y += s.y; - - } break; - case DOCK_SLOT_RIGHT_UR: { - ofs.x += s.x * 4; - ofs.x += s.x; - - } break; - case DOCK_SLOT_RIGHT_BR: { - ofs.x += s.x * 4; - ofs += s; - - } break; - } - - Rect2 r(ofs, s); - dock_select_rect[i] = r; - r.position += Vector2(2, 5); - r.size -= Vector2(4, 7); - - if (i == dock_select_rect_over_idx) { - dock_select->draw_rect(r, used_selected); - } else if (dock_slot[i]->get_tab_count() == 0) { - dock_select->draw_rect(r, unused); - } else { - dock_select->draw_rect(r, used); - } - - for (int j = 0; j < MIN(3, dock_slot[i]->get_tab_count()); j++) { - int xofs = (r.size.width / 3) * j; - Color c = used; - if (i == dock_popup_selected_idx && (dock_slot[i]->get_current_tab() > 3 || dock_slot[i]->get_current_tab() == j)) { - c = tab_selected; - } - dock_select->draw_rect(Rect2(2 + ofs.x + xofs, ofs.y, r.size.width / 3 - 1, 3), c); - } - } -} - void EditorNode::_save_editor_layout() { if (waiting_for_first_scan) { return; // Scanning, do not touch docks. @@ -4971,7 +4728,7 @@ void EditorNode::_save_editor_layout() { // Load and amend existing config if it exists. config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); - _save_docks_to_config(config, "docks"); + editor_dock_manager->save_docks_to_config(config, "docks"); _save_open_scenes_to_config(config); _save_central_editor_layout_to_config(config); editor_data.get_plugin_window_layout(config); @@ -4979,84 +4736,6 @@ void EditorNode::_save_editor_layout() { config->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); } -void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) { - for (int i = 0; i < DOCK_SLOT_MAX; i++) { - String names; - for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) { - String name = dock_slot[i]->get_tab_control(j)->get_name(); - if (!names.is_empty()) { - names += ","; - } - names += name; - } - - String config_key = "dock_" + itos(i + 1); - - if (p_layout->has_section_key(p_section, config_key)) { - p_layout->erase_section_key(p_section, config_key); - } - - if (!names.is_empty()) { - p_layout->set_value(p_section, config_key, names); - } - - int selected_tab_idx = dock_slot[i]->get_current_tab(); - if (selected_tab_idx >= 0) { - p_layout->set_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx", selected_tab_idx); - } - } - - Dictionary floating_docks_dump; - - for (WindowWrapper *wrapper : floating_docks) { - Control *dock = wrapper->get_wrapped_control(); - - Dictionary dock_dump; - dock_dump["window_rect"] = wrapper->get_window_rect(); - - int screen = wrapper->get_window_screen(); - dock_dump["window_screen"] = wrapper->get_window_screen(); - dock_dump["window_screen_rect"] = DisplayServer::get_singleton()->screen_get_usable_rect(screen); - - String name = dock->get_name(); - floating_docks_dump[name] = dock_dump; - - int dock_slot_id = wrapper->get_meta("dock_slot"); - String config_key = "dock_" + itos(dock_slot_id + 1); - - String names = p_layout->get_value(p_section, config_key, ""); - if (names.is_empty()) { - names = name; - } else { - names += "," + name; - } - p_layout->set_value(p_section, config_key, names); - } - - p_layout->set_value(p_section, "dock_floating", floating_docks_dump); - - for (int i = 0; i < vsplits.size(); i++) { - if (vsplits[i]->is_visible_in_tree()) { - p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset()); - } - } - - for (int i = 0; i < hsplits.size(); i++) { - p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset()); - } - - // Save FileSystemDock state. - - p_layout->set_value(p_section, "dock_filesystem_split", FileSystemDock::get_singleton()->get_split_offset()); - p_layout->set_value(p_section, "dock_filesystem_display_mode", FileSystemDock::get_singleton()->get_display_mode()); - p_layout->set_value(p_section, "dock_filesystem_file_sort", FileSystemDock::get_singleton()->get_file_sort()); - p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", FileSystemDock::get_singleton()->get_file_list_display_mode()); - PackedStringArray selected_files = FileSystemDock::get_singleton()->get_selected_paths(); - p_layout->set_value(p_section, "dock_filesystem_selected_paths", selected_files); - Vector<String> uncollapsed_paths = FileSystemDock::get_singleton()->get_uncollapsed_paths(); - p_layout->set_value(p_section, "dock_filesystem_uncollapsed_paths", uncollapsed_paths); -} - void EditorNode::_save_open_scenes_to_config(Ref<ConfigFile> p_layout) { PackedStringArray scenes; for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { @@ -5076,10 +4755,6 @@ void EditorNode::save_editor_layout_delayed() { editor_layout_save_delay_timer->start(); } -void EditorNode::_dock_split_dragged(int ofs) { - editor_layout_save_delay_timer->start(); -} - void EditorNode::_load_editor_layout() { Ref<ConfigFile> config; config.instantiate(); @@ -5102,222 +4777,13 @@ void EditorNode::_load_editor_layout() { return; } - _load_docks_from_config(config, "docks"); + editor_dock_manager->load_docks_from_config(config, "docks"); _load_open_scenes_from_config(config); _load_central_editor_layout_from_config(config); editor_data.set_plugin_window_layout(config); } -void EditorNode::_update_dock_slots_visibility(bool p_keep_selected_tabs) { - if (!docks_visible) { - for (int i = 0; i < DOCK_SLOT_MAX; i++) { - dock_slot[i]->hide(); - } - - for (int i = 0; i < vsplits.size(); i++) { - vsplits[i]->hide(); - } - - right_hsplit->hide(); - } else { - for (int i = 0; i < DOCK_SLOT_MAX; i++) { - int first_tab_visible = -1; - for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) { - if (!dock_slot[i]->is_tab_hidden(j)) { - first_tab_visible = j; - break; - } - } - if (first_tab_visible >= 0) { - dock_slot[i]->show(); - if (p_keep_selected_tabs) { - int current_tab = dock_slot[i]->get_current_tab(); - if (dock_slot[i]->is_tab_hidden(current_tab)) { - dock_slot[i]->set_block_signals(true); - dock_slot[i]->select_next_available(); - dock_slot[i]->set_block_signals(false); - } - } else { - dock_slot[i]->set_block_signals(true); - dock_slot[i]->set_current_tab(first_tab_visible); - dock_slot[i]->set_block_signals(false); - } - } else { - dock_slot[i]->hide(); - } - } - - for (int i = 0; i < vsplits.size(); i++) { - bool in_use = dock_slot[i * 2 + 0]->is_visible() || dock_slot[i * 2 + 1]->is_visible(); - vsplits[i]->set_visible(in_use); - } - - right_hsplit->set_visible(right_l_vsplit->is_visible() || right_r_vsplit->is_visible()); - } -} - -void EditorNode::_dock_tab_changed(int p_tab) { - // Update visibility but don't set current tab. - _update_dock_slots_visibility(true); -} - -void EditorNode::_restore_floating_dock(const Dictionary &p_dock_dump, Control *p_dock, int p_slot_index) { - WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(p_dock); - if (!wrapper) { - _dock_make_float(p_dock, p_slot_index, false); - wrapper = floating_docks[floating_docks.size() - 1]; - } - - wrapper->restore_window_from_saved_position( - p_dock_dump.get("window_rect", Rect2i()), - p_dock_dump.get("window_screen", -1), - p_dock_dump.get("window_screen_rect", Rect2i())); -} - -void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section) { - Dictionary floating_docks_dump = p_layout->get_value(p_section, "dock_floating", Dictionary()); - - bool restore_window_on_load = EDITOR_GET("interface/multi_window/restore_windows_on_load"); - - for (int i = 0; i < DOCK_SLOT_MAX; i++) { - if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1))) { - continue; - } - - Vector<String> names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(","); - - for (int j = names.size() - 1; j >= 0; j--) { - String name = names[j]; - - // FIXME: Find it, in a horribly inefficient way. - int atidx = -1; - Control *node = nullptr; - for (int k = 0; k < DOCK_SLOT_MAX; k++) { - if (!dock_slot[k]->has_node(name)) { - continue; - } - node = Object::cast_to<Control>(dock_slot[k]->get_node(name)); - if (!node) { - continue; - } - atidx = k; - break; - } - - if (atidx == -1) { - // Try floating docks. - for (WindowWrapper *wrapper : floating_docks) { - if (wrapper->get_meta("dock_name") == name) { - if (restore_window_on_load && floating_docks_dump.has(name)) { - _restore_floating_dock(floating_docks_dump[name], wrapper, i); - } else { - atidx = wrapper->get_meta("dock_slot"); - node = wrapper->get_wrapped_control(); - wrapper->set_window_enabled(false); - } - break; - } - } - } - if (!node) { - // Well, it's not anywhere. - continue; - } - - if (atidx == i) { - dock_slot[i]->move_child(node, 0); - } else if (atidx != -1) { - dock_slot[i]->move_tab_from_tab_container(dock_slot[atidx], dock_slot[atidx]->get_tab_idx_from_control(node), 0); - } - - WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(node); - if (restore_window_on_load && floating_docks_dump.has(name)) { - if (!dock_slot[i]->is_tab_hidden(dock_slot[i]->get_tab_idx_from_control(node))) { - _restore_floating_dock(floating_docks_dump[name], node, i); - } - } else if (wrapper) { - wrapper->set_window_enabled(false); - } - } - - if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx")) { - continue; - } - - int selected_tab_idx = p_layout->get_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx"); - if (selected_tab_idx >= 0 && selected_tab_idx < dock_slot[i]->get_tab_count()) { - dock_slot[i]->call_deferred("set_current_tab", selected_tab_idx); - } - } - - for (int i = 0; i < vsplits.size(); i++) { - if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1))) { - continue; - } - - int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1)); - vsplits[i]->set_split_offset(ofs); - } - - for (int i = 0; i < hsplits.size(); i++) { - if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1))) { - continue; - } - int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1)); - hsplits[i]->set_split_offset(ofs); - } - - _update_dock_slots_visibility(false); - - // FileSystemDock. - - if (p_layout->has_section_key(p_section, "dock_filesystem_split")) { - int fs_split_ofs = p_layout->get_value(p_section, "dock_filesystem_split"); - FileSystemDock::get_singleton()->set_split_offset(fs_split_ofs); - } - - if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) { - FileSystemDock::DisplayMode dock_filesystem_display_mode = FileSystemDock::DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode"))); - FileSystemDock::get_singleton()->set_display_mode(dock_filesystem_display_mode); - } - - if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) { - FileSystemDock::FileSortOption dock_filesystem_file_sort = FileSystemDock::FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort"))); - FileSystemDock::get_singleton()->set_file_sort(dock_filesystem_file_sort); - } - - if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) { - FileSystemDock::FileListDisplayMode dock_filesystem_file_list_display_mode = FileSystemDock::FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode"))); - FileSystemDock::get_singleton()->set_file_list_display_mode(dock_filesystem_file_list_display_mode); - } - - if (p_layout->has_section_key(p_section, "dock_filesystem_selected_paths")) { - PackedStringArray dock_filesystem_selected_paths = p_layout->get_value(p_section, "dock_filesystem_selected_paths"); - for (int i = 0; i < dock_filesystem_selected_paths.size(); i++) { - FileSystemDock::get_singleton()->select_file(dock_filesystem_selected_paths[i]); - } - } - - // Restore collapsed state of FileSystemDock. - PackedStringArray uncollapsed_tis; - if (p_layout->has_section_key(p_section, "dock_filesystem_uncollapsed_paths")) { - uncollapsed_tis = p_layout->get_value(p_section, "dock_filesystem_uncollapsed_paths"); - } else { - uncollapsed_tis = { "res://" }; - } - - if (!uncollapsed_tis.is_empty()) { - for (int i = 0; i < uncollapsed_tis.size(); i++) { - TreeItem *uncollapsed_ti = FileSystemDock::get_singleton()->get_tree_control()->get_item_with_metadata(uncollapsed_tis[i], 0); - if (uncollapsed_ti) { - uncollapsed_ti->set_collapsed(false); - } - } - FileSystemDock::get_singleton()->get_tree_control()->queue_redraw(); - } -} - void EditorNode::_save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file) { // Bottom panel. @@ -5566,7 +5032,7 @@ void EditorNode::_layout_menu_option(int p_id) { layout_dialog->popup_centered(); } break; case SETTINGS_LAYOUT_DEFAULT: { - _load_docks_from_config(default_layout, "docks"); + editor_dock_manager->load_docks_from_config(default_layout, "docks"); _save_editor_layout(); } break; default: { @@ -5577,7 +5043,7 @@ void EditorNode::_layout_menu_option(int p_id) { return; // No config. } - _load_docks_from_config(config, editor_layouts->get_item_text(p_id)); + editor_dock_manager->load_docks_from_config(config, editor_layouts->get_item_text(p_id)); _save_editor_layout(); } } @@ -5787,15 +5253,6 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { } } -void EditorNode::set_docks_visible(bool p_show) { - docks_visible = p_show; - _update_dock_slots_visibility(true); -} - -bool EditorNode::get_docks_visible() const { - return docks_visible; -} - void EditorNode::_toggle_distraction_free_mode() { if (EDITOR_GET("interface/editor/separate_distraction_mode")) { int screen = -1; @@ -5822,11 +5279,11 @@ void EditorNode::set_distraction_free_mode(bool p_enter) { distraction_free->set_pressed(p_enter); if (p_enter) { - if (docks_visible) { - set_docks_visible(false); + if (editor_dock_manager->are_docks_visible()) { + editor_dock_manager->set_docks_visible(false); } } else { - set_docks_visible(true); + editor_dock_manager->set_docks_visible(true); } } @@ -5834,35 +5291,6 @@ bool EditorNode::is_distraction_free_mode_enabled() const { return distraction_free->is_pressed(); } -void EditorNode::add_control_to_dock(DockSlot p_slot, Control *p_control) { - ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX); - dock_slot[p_slot]->add_child(p_control); - _update_dock_slots_visibility(); -} - -void EditorNode::remove_control_from_dock(Control *p_control) { - // If the dock is floating, close it first. - for (WindowWrapper *wrapper : floating_docks) { - if (p_control == wrapper->get_wrapped_control()) { - wrapper->set_window_enabled(false); - break; - } - } - - Control *dock = nullptr; - for (int i = 0; i < DOCK_SLOT_MAX; i++) { - if (p_control->get_parent() == dock_slot[i]) { - dock = dock_slot[i]; - break; - } - } - - ERR_FAIL_NULL_MSG(dock, "Control was not in dock."); - - dock->remove_child(p_control); - _update_dock_slots_visibility(); -} - Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) { Control *drag_control = memnew(Control); TextureRect *drag_preview = memnew(TextureRect); @@ -6004,7 +5432,7 @@ void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, Str ERR_FAIL_COND(dir.is_null()); for (int i = 0; i < p_files.size(); i++) { - String from = p_files[i]; + const String &from = p_files[i]; String to = to_path.path_join(from.get_file()); if (dir->dir_exists(from)) { @@ -6153,7 +5581,8 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins if (edited_scene_map.size() > 0) { // Reload the new instance. Error err; - Ref<PackedScene> instance_scene_packed_scene = ResourceLoader::load(p_instance_path, "", ResourceFormatLoader::CACHE_MODE_REPLACE, &err); + Ref<PackedScene> instance_scene_packed_scene = ResourceLoader::load(p_instance_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE, &err); + instance_scene_packed_scene->set_path(p_instance_path, true); ERR_FAIL_COND(err != OK); ERR_FAIL_COND(instance_scene_packed_scene.is_null()); @@ -6260,7 +5689,8 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins // be properly updated. for (String path : required_load_paths) { if (!local_scene_cache.find(path)) { - current_packed_scene = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REPLACE, &err); + current_packed_scene = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_IGNORE, &err); + current_packed_scene->set_path(path, true); local_scene_cache[path] = current_packed_scene; } else { current_packed_scene = local_scene_cache[path]; @@ -6548,6 +5978,7 @@ void EditorNode::_bottom_panel_raise_toggled(bool p_pressed) { void EditorNode::_update_renderer_color() { String rendering_method = renderer->get_selected_metadata(); + // TODO: Use theme colors instead of hardcoded values. if (rendering_method == "forward_plus") { renderer->add_theme_color_override("font_color", Color::hex(0x5d8c3fff)); } @@ -6569,6 +6000,9 @@ void EditorNode::_renderer_selected(int p_which) { } renderer_request = rendering_method; + video_restart_dialog->set_text( + vformat(TTR("Changing the renderer requires restarting the editor.\n\nChoosing Save & Restart will change the rendering method to:\n- Desktop platforms: %s\n- Mobile platforms: %s\n- Web platform: gl_compatibility"), + renderer_request, renderer_request.replace("forward_plus", "mobile"))); video_restart_dialog->popup_centered(); renderer->select(renderer_current); _update_renderer_color(); @@ -6611,9 +6045,7 @@ void EditorNode::_resource_loaded(Ref<Resource> p_resource, const String &p_path void EditorNode::_feature_profile_changed() { Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile(); // FIXME: Close all floating docks to avoid crash. - for (WindowWrapper *wrapper : floating_docks) { - wrapper->set_window_enabled(false); - } + editor_dock_manager->close_all_floating_docks(); TabContainer *import_tabs = cast_to<TabContainer>(ImportDock::get_singleton()->get_parent()); TabContainer *node_tabs = cast_to<TabContainer>(NodeDock::get_singleton()->get_parent()); TabContainer *fs_tabs = cast_to<TabContainer>(FileSystemDock::get_singleton()->get_parent()); @@ -6648,22 +6080,16 @@ void EditorNode::_feature_profile_changed() { } } - _update_dock_slots_visibility(); + editor_dock_manager->update_dock_slots_visibility(); } void EditorNode::_bind_methods() { ClassDB::bind_method(D_METHOD("push_item", "object", "property", "inspector_only"), &EditorNode::push_item, DEFVAL(""), DEFVAL(false)); ClassDB::bind_method("set_edited_scene", &EditorNode::set_edited_scene); - ClassDB::bind_method("open_request", &EditorNode::open_request); - ClassDB::bind_method("edit_foreign_resource", &EditorNode::edit_foreign_resource); - ClassDB::bind_method("is_resource_read_only", &EditorNode::is_resource_read_only); ClassDB::bind_method("stop_child_process", &EditorNode::stop_child_process); - ClassDB::bind_method("_set_main_scene_state", &EditorNode::_set_main_scene_state); - ClassDB::bind_method("_update_recent_scenes", &EditorNode::_update_recent_scenes); - ADD_SIGNAL(MethodInfo("request_help_search")); ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "args"))); ADD_SIGNAL(MethodInfo("resource_saved", PropertyInfo(Variant::OBJECT, "obj"))); @@ -7001,9 +6427,8 @@ EditorNode::EditorNode() { add_child(editor_export); // Exporters might need the theme. - EditorColorMap::create(); - EditorTheme::initialize(); - theme = create_custom_theme(); + EditorThemeManager::initialize(); + theme = EditorThemeManager::generate_theme(); DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor))); register_exporters(); @@ -7064,127 +6489,96 @@ EditorNode::EditorNode() { title_bar = memnew(EditorTitleBar); main_vbox->add_child(title_bar); - left_l_hsplit = memnew(HSplitContainer); + left_l_hsplit = memnew(DockSplitContainer); + left_l_hsplit->set_name("DockHSplitLeftL"); main_vbox->add_child(left_l_hsplit); left_l_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL); - left_l_vsplit = memnew(VSplitContainer); + left_l_vsplit = memnew(DockSplitContainer); + left_l_vsplit->set_name("DockVSplitLeftL"); + left_l_vsplit->set_vertical(true); left_l_hsplit->add_child(left_l_vsplit); - dock_slot[DOCK_SLOT_LEFT_UL] = memnew(TabContainer); - left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]); - dock_slot[DOCK_SLOT_LEFT_BL] = memnew(TabContainer); - left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]); - left_r_hsplit = memnew(HSplitContainer); + TabContainer *dock_slot[EditorDockManager::DOCK_SLOT_MAX]; + dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL] = memnew(TabContainer); + dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL]->set_name("DockSlotLeftUL"); + left_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL]); + dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL] = memnew(TabContainer); + dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL]->set_name("DockSlotLeftBL"); + left_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL]); + + left_r_hsplit = memnew(DockSplitContainer); + left_r_hsplit->set_name("DockHSplitLeftR"); left_l_hsplit->add_child(left_r_hsplit); - left_r_vsplit = memnew(VSplitContainer); + left_r_vsplit = memnew(DockSplitContainer); + left_r_vsplit->set_name("DockVSplitLeftR"); + left_r_vsplit->set_vertical(true); left_r_hsplit->add_child(left_r_vsplit); - dock_slot[DOCK_SLOT_LEFT_UR] = memnew(TabContainer); - left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UR]); - dock_slot[DOCK_SLOT_LEFT_BR] = memnew(TabContainer); - left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BR]); - - main_hsplit = memnew(HSplitContainer); + dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR] = memnew(TabContainer); + dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR]->set_name("DockSlotLeftUR"); + left_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR]); + dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR] = memnew(TabContainer); + dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR]->set_name("DockSlotLeftBR"); + left_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR]); + + main_hsplit = memnew(DockSplitContainer); + main_hsplit->set_name("DockHSplitMain"); left_r_hsplit->add_child(main_hsplit); VBoxContainer *center_vb = memnew(VBoxContainer); main_hsplit->add_child(center_vb); + center_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); - center_split = memnew(VSplitContainer); + center_split = memnew(DockSplitContainer); + center_split->set_name("DockVSplitCenter"); + center_split->set_vertical(true); center_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); center_split->set_collapsed(false); center_vb->add_child(center_split); - right_hsplit = memnew(HSplitContainer); + right_hsplit = memnew(DockSplitContainer); + right_hsplit->set_name("DockHSplitRight"); main_hsplit->add_child(right_hsplit); - right_l_vsplit = memnew(VSplitContainer); + right_l_vsplit = memnew(DockSplitContainer); + right_l_vsplit->set_name("DockVSplitRightL"); + right_l_vsplit->set_vertical(true); right_hsplit->add_child(right_l_vsplit); - dock_slot[DOCK_SLOT_RIGHT_UL] = memnew(TabContainer); - right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UL]); - dock_slot[DOCK_SLOT_RIGHT_BL] = memnew(TabContainer); - right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BL]); - - right_r_vsplit = memnew(VSplitContainer); + dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL] = memnew(TabContainer); + dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL]->set_name("DockSlotRightUL"); + right_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL]); + dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL] = memnew(TabContainer); + dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL]->set_name("DockSlotRightBL"); + right_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL]); + + right_r_vsplit = memnew(DockSplitContainer); + right_r_vsplit->set_name("DockVSplitRightR"); + right_r_vsplit->set_vertical(true); right_hsplit->add_child(right_r_vsplit); - dock_slot[DOCK_SLOT_RIGHT_UR] = memnew(TabContainer); - right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]); - dock_slot[DOCK_SLOT_RIGHT_BR] = memnew(TabContainer); - right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]); - - // Store them for easier access. - vsplits.push_back(left_l_vsplit); - vsplits.push_back(left_r_vsplit); - vsplits.push_back(right_l_vsplit); - vsplits.push_back(right_r_vsplit); - - hsplits.push_back(left_l_hsplit); - hsplits.push_back(left_r_hsplit); - hsplits.push_back(main_hsplit); - hsplits.push_back(right_hsplit); - - for (int i = 0; i < vsplits.size(); i++) { - vsplits[i]->connect("dragged", callable_mp(this, &EditorNode::_dock_split_dragged)); - hsplits[i]->connect("dragged", callable_mp(this, &EditorNode::_dock_split_dragged)); - } - - dock_select_popup = memnew(PopupPanel); - gui_base->add_child(dock_select_popup); - VBoxContainer *dock_vb = memnew(VBoxContainer); - dock_select_popup->add_child(dock_vb); - - HBoxContainer *dock_hb = memnew(HBoxContainer); - dock_tab_move_left = memnew(Button); - dock_tab_move_left->set_flat(true); - dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE); - dock_tab_move_left->connect("pressed", callable_mp(this, &EditorNode::_dock_move_left)); - dock_hb->add_child(dock_tab_move_left); - - Label *dock_label = memnew(Label); - dock_label->set_text(TTR("Dock Position")); - dock_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); - dock_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); - dock_hb->add_child(dock_label); - - dock_tab_move_right = memnew(Button); - dock_tab_move_right->set_flat(true); - dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE); - dock_tab_move_right->connect("pressed", callable_mp(this, &EditorNode::_dock_move_right)); - - dock_hb->add_child(dock_tab_move_right); - dock_vb->add_child(dock_hb); - - dock_select = memnew(Control); - dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE); - dock_select->connect("gui_input", callable_mp(this, &EditorNode::_dock_select_input)); - dock_select->connect("draw", callable_mp(this, &EditorNode::_dock_select_draw)); - dock_select->connect("mouse_exited", callable_mp(this, &EditorNode::_dock_popup_exit)); - dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL); - dock_vb->add_child(dock_select); - - if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && !EDITOR_GET("interface/editor/single_window_mode") && EDITOR_GET("interface/multi_window/enable")) { - dock_float = memnew(Button); - dock_float->set_icon(theme->get_icon("MakeFloating", EditorStringName(EditorIcons))); - dock_float->set_text(TTR("Make Floating")); - dock_float->set_focus_mode(Control::FOCUS_NONE); - dock_float->set_h_size_flags(Control::SIZE_SHRINK_CENTER); - dock_float->connect("pressed", callable_mp(this, &EditorNode::_dock_make_selected_float)); - - dock_vb->add_child(dock_float); - } - - dock_select_popup->reset_size(); - - for (int i = 0; i < DOCK_SLOT_MAX; i++) { - dock_slot[i]->set_custom_minimum_size(Size2(170, 0) * EDSCALE); - dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL); - dock_slot[i]->set_popup(dock_select_popup); - dock_slot[i]->connect("pre_popup_pressed", callable_mp(this, &EditorNode::_dock_pre_popup).bind(i)); - dock_slot[i]->set_drag_to_rearrange_enabled(true); - dock_slot[i]->set_tabs_rearrange_group(1); - dock_slot[i]->connect("tab_changed", callable_mp(this, &EditorNode::_dock_tab_changed)); - dock_slot[i]->set_use_hidden_tabs_for_min_size(true); + dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR] = memnew(TabContainer); + dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR]->set_name("DockSlotRightUR"); + right_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR]); + dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR] = memnew(TabContainer); + dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR]->set_name("DockSlotRightBR"); + right_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR]); + + editor_dock_manager = memnew(EditorDockManager); + editor_dock_manager->connect("layout_changed", callable_mp(this, &EditorNode::_save_editor_layout)); + + // Save the splits for easier access. + editor_dock_manager->add_vsplit(left_l_vsplit); + editor_dock_manager->add_vsplit(left_r_vsplit); + editor_dock_manager->add_vsplit(right_l_vsplit); + editor_dock_manager->add_vsplit(right_r_vsplit); + + editor_dock_manager->add_hsplit(left_l_hsplit); + editor_dock_manager->add_hsplit(left_r_hsplit); + editor_dock_manager->add_hsplit(main_hsplit); + editor_dock_manager->add_hsplit(right_hsplit); + + for (int i = 0; i < EditorDockManager::DOCK_SLOT_MAX; i++) { + editor_dock_manager->register_dock_slot((EditorDockManager::DockSlot)i, dock_slot[i]); } editor_layout_save_delay_timer = memnew(Timer); @@ -7546,7 +6940,7 @@ EditorNode::EditorNode() { renderer->set_focus_mode(Control::FOCUS_NONE); renderer->add_theme_font_override("font", theme->get_font(SNAME("bold"), EditorStringName(EditorFonts))); renderer->add_theme_font_size_override("font_size", theme->get_font_size(SNAME("bold_size"), EditorStringName(EditorFonts))); - renderer->set_tooltip_text(TTR("Choose a renderer.")); + renderer->set_tooltip_text(TTR("Choose a rendering method.\n\nNotes:\n- On mobile platforms, the Mobile rendering method is used if Forward+ is selected here.\n- On the web platform, the Compatibility rendering method is always used.")); right_menu_hb->add_child(renderer); @@ -7588,7 +6982,6 @@ EditorNode::EditorNode() { _update_renderer_color(); video_restart_dialog = memnew(ConfirmationDialog); - video_restart_dialog->set_text(TTR("Changing the renderer requires restarting the editor.")); video_restart_dialog->set_ok_button_text(TTR("Save & Restart")); video_restart_dialog->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(SET_RENDERER_NAME_SAVE_AND_RESTART)); gui_base->add_child(video_restart_dialog); @@ -7628,37 +7021,22 @@ EditorNode::EditorNode() { history_dock = memnew(HistoryDock); // Scene: Top left. - dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton()); - dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(SceneTreeDock::get_singleton()), TTR("Scene")); + editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_UR, SceneTreeDock::get_singleton(), TTR("Scene")); // Import: Top left, behind Scene. - dock_slot[DOCK_SLOT_LEFT_UR]->add_child(ImportDock::get_singleton()); - dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(ImportDock::get_singleton()), TTR("Import")); + editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_UR, ImportDock::get_singleton(), TTR("Import")); // FileSystem: Bottom left. - dock_slot[DOCK_SLOT_LEFT_BR]->add_child(FileSystemDock::get_singleton()); - dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_BR]->get_tab_idx_from_control(FileSystemDock::get_singleton()), TTR("FileSystem")); + editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_BR, FileSystemDock::get_singleton(), TTR("FileSystem")); // Inspector: Full height right. - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(InspectorDock::get_singleton()); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(InspectorDock::get_singleton()), TTR("Inspector")); + editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, InspectorDock::get_singleton(), TTR("Inspector")); // Node: Full height right, behind Inspector. - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(NodeDock::get_singleton()); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(NodeDock::get_singleton()), TTR("Node")); + editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, NodeDock::get_singleton(), TTR("Node")); // History: Full height right, behind Node. - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(history_dock); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(history_dock), TTR("History")); - - // Hide unused dock slots and vsplits. - dock_slot[DOCK_SLOT_LEFT_UL]->hide(); - dock_slot[DOCK_SLOT_LEFT_BL]->hide(); - dock_slot[DOCK_SLOT_RIGHT_BL]->hide(); - dock_slot[DOCK_SLOT_RIGHT_UR]->hide(); - dock_slot[DOCK_SLOT_RIGHT_BR]->hide(); - left_l_vsplit->hide(); - right_r_vsplit->hide(); + editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, history_dock, TTR("History")); // Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize. left_r_hsplit->set_split_offset(270 * EDSCALE); @@ -7673,7 +7051,8 @@ EditorNode::EditorNode() { default_layout->set_value(docks_section, "dock_4", "FileSystem"); default_layout->set_value(docks_section, "dock_5", "Inspector,Node,History"); - for (int i = 0; i < vsplits.size(); i++) { + // There are 4 vsplits and 4 hsplits. + for (int i = 0; i < editor_dock_manager->get_vsplit_count(); i++) { default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0); } default_layout->set_value(docks_section, "dock_hsplit_1", 0); @@ -7803,6 +7182,7 @@ EditorNode::EditorNode() { file = memnew(EditorFileDialog); gui_base->add_child(file); file->set_current_dir("res://"); + file->set_transient_to_focused(true); file_export_lib = memnew(EditorFileDialog); file_export_lib->set_title(TTR("Export Library")); @@ -8105,10 +7485,10 @@ EditorNode::~EditorNode() { memdelete(editor_plugins_force_input_forwarding); memdelete(progress_hb); memdelete(surface_upgrade_tool); + memdelete(editor_dock_manager); EditorSettings::destroy(); - EditorColorMap::finish(); - EditorTheme::finalize(); + EditorThemeManager::finalize(); GDExtensionEditorPlugins::editor_node_add_plugin = nullptr; GDExtensionEditorPlugins::editor_node_remove_plugin = nullptr; diff --git a/editor/editor_node.h b/editor/editor_node.h index c72a8f9324..f1dea0c11e 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -73,10 +73,12 @@ class AudioStreamPreviewGenerator; class BackgroundProgress; class DependencyEditor; class DependencyErrorDialog; +class DockSplitContainer; class DynamicFontImportSettingsDialog; class EditorAbout; class EditorBuildProfileManager; class EditorCommandPalette; +class EditorDockManager; class EditorExport; class EditorExtensionManager; class EditorFeatureProfileManager; @@ -121,18 +123,6 @@ class EditorNode : public Node { GDCLASS(EditorNode, Node); public: - enum DockSlot { - DOCK_SLOT_LEFT_UL, - DOCK_SLOT_LEFT_BL, - DOCK_SLOT_LEFT_UR, - DOCK_SLOT_LEFT_BR, - DOCK_SLOT_RIGHT_UL, - DOCK_SLOT_RIGHT_BL, - DOCK_SLOT_RIGHT_UR, - DOCK_SLOT_RIGHT_BR, - DOCK_SLOT_MAX - }; - enum EditorTable { EDITOR_2D = 0, EDITOR_3D, @@ -310,18 +300,15 @@ private: String renderer_request; // Split containers. - HSplitContainer *left_l_hsplit = nullptr; - VSplitContainer *left_l_vsplit = nullptr; - HSplitContainer *left_r_hsplit = nullptr; - VSplitContainer *left_r_vsplit = nullptr; - HSplitContainer *main_hsplit = nullptr; - HSplitContainer *right_hsplit = nullptr; - VSplitContainer *right_l_vsplit = nullptr; - VSplitContainer *right_r_vsplit = nullptr; - VSplitContainer *center_split = nullptr; - // To access those easily by index. - Vector<VSplitContainer *> vsplits; - Vector<HSplitContainer *> hsplits; + DockSplitContainer *left_l_hsplit = nullptr; + DockSplitContainer *left_l_vsplit = nullptr; + DockSplitContainer *left_r_hsplit = nullptr; + DockSplitContainer *left_r_vsplit = nullptr; + DockSplitContainer *main_hsplit = nullptr; + DockSplitContainer *right_hsplit = nullptr; + DockSplitContainer *right_l_vsplit = nullptr; + DockSplitContainer *right_r_vsplit = nullptr; + DockSplitContainer *center_split = nullptr; // Main tabs. EditorSceneTabs *scene_tabs = nullptr; @@ -426,20 +413,8 @@ private: Button *new_inherited_button = nullptr; String open_import_request; - Vector<WindowWrapper *> floating_docks; - - Button *dock_float = nullptr; - Button *dock_tab_move_left = nullptr; - Button *dock_tab_move_right = nullptr; - Control *dock_select = nullptr; - PopupPanel *dock_select_popup = nullptr; - Rect2 dock_select_rect[DOCK_SLOT_MAX]; - TabContainer *dock_slot[DOCK_SLOT_MAX]; + EditorDockManager *editor_dock_manager = nullptr; Timer *editor_layout_save_delay_timer = nullptr; - bool docks_visible = true; - int dock_popup_selected_idx = -1; - int dock_select_rect_over_idx = -1; - Button *distraction_free = nullptr; Vector<BottomPanelItem> bottom_panel_items; @@ -634,17 +609,6 @@ private: bool _find_scene_in_use(Node *p_node, const String &p_path) const; - void _dock_select_input(const Ref<InputEvent> &p_input); - void _dock_move_left(); - void _dock_move_right(); - void _dock_select_draw(); - void _dock_pre_popup(int p_which); - void _dock_split_dragged(int ofs); - void _dock_popup_exit(); - void _dock_floating_close_request(WindowWrapper *p_wrapper); - void _dock_make_selected_float(); - void _dock_make_float(Control *p_control, int p_slot_index, bool p_show_window = true); - void _proceed_closing_scene_tabs(); bool _is_closing_editor() const; @@ -655,11 +619,6 @@ private: void _save_editor_layout(); void _load_editor_layout(); - void _save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section); - void _restore_floating_dock(const Dictionary &p_dock_dump, Control *p_wrapper, int p_slot_index); - void _load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section); - void _update_dock_slots_visibility(bool p_keep_selected_tabs = false); - void _dock_tab_changed(int p_tab); void _save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file); void _load_central_editor_layout_from_config(Ref<ConfigFile> p_config_file); @@ -772,15 +731,9 @@ public: void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE, false); } - void set_docks_visible(bool p_show); - bool get_docks_visible() const; - void set_distraction_free_mode(bool p_enter); bool is_distraction_free_mode_enabled() const; - void add_control_to_dock(DockSlot p_slot, Control *p_control); - void remove_control_from_dock(Control *p_control); - void set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed = false); bool is_addon_plugin_enabled(const String &p_addon) const; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 94a49166b8..f0044edff2 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -31,6 +31,7 @@ #include "editor_plugin.h" #include "editor/debugger/editor_debugger_node.h" +#include "editor/editor_dock_manager.h" #include "editor/editor_file_system.h" #include "editor/editor_inspector.h" #include "editor/editor_interface.h" @@ -39,8 +40,8 @@ #include "editor/editor_undo_redo_manager.h" #include "editor/export/editor_export.h" #include "editor/gui/editor_title_bar.h" +#include "editor/import/3d/resource_importer_scene.h" #include "editor/import/editor_import_plugin.h" -#include "editor/import/resource_importer_scene.h" #include "editor/inspector_dock.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/editor_debugger_plugin.h" @@ -84,12 +85,12 @@ Button *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const Stri void EditorPlugin::add_control_to_dock(DockSlot p_slot, Control *p_control) { ERR_FAIL_NULL(p_control); - EditorNode::get_singleton()->add_control_to_dock(EditorNode::DockSlot(p_slot), p_control); + EditorDockManager::get_singleton()->add_control_to_dock(EditorDockManager::DockSlot(p_slot), p_control); } void EditorPlugin::remove_control_from_docks(Control *p_control) { ERR_FAIL_NULL(p_control); - EditorNode::get_singleton()->remove_control_from_dock(p_control); + EditorDockManager::get_singleton()->remove_control_from_dock(p_control); } void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) { @@ -402,13 +403,13 @@ void EditorPlugin::remove_translation_parser_plugin(const Ref<EditorTranslationP void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer, bool p_first_priority) { ERR_FAIL_COND(!p_importer.is_valid()); ResourceFormatImporter::get_singleton()->add_importer(p_importer, p_first_priority); - EditorFileSystem::get_singleton()->call_deferred(SNAME("scan")); + callable_mp(EditorFileSystem::get_singleton(), &EditorFileSystem::scan).call_deferred(); } void EditorPlugin::remove_import_plugin(const Ref<EditorImportPlugin> &p_importer) { ERR_FAIL_COND(!p_importer.is_valid()); ResourceFormatImporter::get_singleton()->remove_importer(p_importer); - EditorFileSystem::get_singleton()->call_deferred(SNAME("scan")); + callable_mp(EditorFileSystem::get_singleton(), &EditorFileSystem::scan).call_deferred(); } void EditorPlugin::add_export_plugin(const Ref<EditorExportPlugin> &p_exporter) { diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index ef8730cabf..d22e60d7b4 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -36,7 +36,7 @@ #include "core/io/file_access.h" #include "core/os/main_loop.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/margin_container.h" #include "scene/gui/tree.h" @@ -64,7 +64,7 @@ void EditorPluginSettings::update_plugins() { for (int i = 0; i < plugins.size(); i++) { Ref<ConfigFile> cf; cf.instantiate(); - const String path = plugins[i]; + const String &path = plugins[i]; Error err2 = cf->load(path); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 27530dc641..f237649c5d 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -37,7 +37,6 @@ #include "editor/editor_properties_array_dict.h" #include "editor/editor_properties_vector.h" #include "editor/editor_resource_picker.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" @@ -48,6 +47,7 @@ #include "editor/project_settings_editor.h" #include "editor/property_selector.h" #include "editor/scene_tree_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/gpu_particles_2d.h" #include "scene/3d/fog_volume.h" #include "scene/3d/gpu_particles_3d.h" @@ -992,12 +992,12 @@ void EditorPropertyLayersGrid::_notification(int p_what) { const int bsize = (grid_size.height * 80 / 100) / 2; const int h = bsize * 2 + 1; - Color color = get_theme_color(read_only ? SNAME("disabled_highlight_color") : SNAME("highlight_color"), EditorStringName(Editor)); + Color color = get_theme_color(read_only ? SNAME("highlight_disabled_color") : SNAME("highlight_color"), EditorStringName(Editor)); - Color text_color = get_theme_color(read_only ? SNAME("disabled_font_color") : SNAME("font_color"), EditorStringName(Editor)); + Color text_color = get_theme_color(read_only ? SNAME("font_disabled_color") : SNAME("font_color"), EditorStringName(Editor)); text_color.a *= 0.5; - Color text_color_on = get_theme_color(read_only ? SNAME("disabled_font_color") : SNAME("font_hover_color"), EditorStringName(Editor)); + Color text_color_on = get_theme_color(read_only ? SNAME("font_disabled_color") : SNAME("font_hover_color"), EditorStringName(Editor)); text_color_on.a *= 0.7; const int vofs = (grid_size.height - h) / 2; @@ -2073,7 +2073,7 @@ void EditorPropertyQuaternion::_notification(int p_what) { euler[i]->add_theme_color_override("label_color", colors[i]); } edit_button->set_icon(get_editor_theme_icon(SNAME("Edit"))); - euler_label->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("property_color"), EditorStringName(Editor))); + euler_label->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("property_color"), SNAME("EditorProperty"))); warning->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); warning->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); } break; @@ -3013,7 +3013,7 @@ void EditorPropertyResource::_resource_selected(const Ref<Resource> &p_resource, if (extensions.find(parent.get_extension()) && (!EditorNode::get_singleton()->get_edited_scene() || EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path() != parent)) { // If the resource belongs to another (non-imported) scene, edit it in that scene instead. if (!FileAccess::exists(parent + ".import")) { - EditorNode::get_singleton()->call_deferred("edit_foreign_resource", p_resource); + callable_mp(EditorNode::get_singleton(), &EditorNode::edit_foreign_resource).call_deferred(p_resource); return; } } diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 0a9d35fe64..f5b8d04444 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -34,11 +34,11 @@ #include "core/io/marshalls.h" #include "editor/editor_properties.h" #include "editor/editor_properties_vector.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_spin_slider.h" #include "editor/inspector_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/resources/packed_scene.h" @@ -202,22 +202,16 @@ void EditorPropertyArray::_property_changed(const String &p_property, Variant p_ p_value = Variant(); // `EditorResourcePicker` resets to `Ref<Resource>()`. See GH-82716. } - int index; - if (p_property.begins_with("metadata/")) { - index = p_property.get_slice("/", 2).to_int(); - } else { - index = p_property.get_slice("/", 1).to_int(); - } + int index = p_property.get_slice("/", 1).to_int(); Variant array = object->get_array().duplicate(); array.set(index, p_value); - object->set_array(array); - emit_changed(get_edited_property(), array, "", true); + emit_changed(get_edited_property(), array, p_name, p_changing); } -void EditorPropertyArray::_change_type(Object *p_button, int p_index) { +void EditorPropertyArray::_change_type(Object *p_button, int p_slot_index) { Button *button = Object::cast_to<Button>(p_button); - changing_type_index = p_index; + changing_type_index = slots[p_slot_index].index; Rect2 rect = button->get_screen_rect(); change_type->reset_size(); change_type->set_position(rect.get_end() - Vector2(change_type->get_contents_minimum_size().x, 0)); @@ -244,6 +238,48 @@ void EditorPropertyArray::_object_id_selected(const StringName &p_property, Obje emit_signal(SNAME("object_id_selected"), p_property, p_id); } +void EditorPropertyArray::create_new_property_slot() { + int idx = slots.size(); + HBoxContainer *hbox = memnew(HBoxContainer); + + Button *reorder_button = memnew(Button); + reorder_button->set_icon(get_editor_theme_icon(SNAME("TripleBar"))); + reorder_button->set_default_cursor_shape(Control::CURSOR_MOVE); + reorder_button->set_disabled(is_read_only()); + reorder_button->connect(SNAME("gui_input"), callable_mp(this, &EditorPropertyArray::_reorder_button_gui_input)); + reorder_button->connect(SNAME("button_up"), callable_mp(this, &EditorPropertyArray::_reorder_button_up)); + reorder_button->connect(SNAME("button_down"), callable_mp(this, &EditorPropertyArray::_reorder_button_down).bind(idx)); + + hbox->add_child(reorder_button); + EditorProperty *prop = memnew(EditorPropertyNil); + hbox->add_child(prop); + + bool is_untyped_array = object->get_array().get_type() == Variant::ARRAY && subtype == Variant::NIL; + + if (is_untyped_array) { + Button *edit_btn = memnew(Button); + edit_btn->set_icon(get_editor_theme_icon(SNAME("Edit"))); + edit_btn->set_disabled(is_read_only()); + edit_btn->connect("pressed", callable_mp(this, &EditorPropertyArray::_change_type).bind(edit_btn, idx)); + hbox->add_child(edit_btn); + } else { + Button *remove_btn = memnew(Button); + remove_btn->set_icon(get_editor_theme_icon(SNAME("Remove"))); + remove_btn->set_disabled(is_read_only()); + remove_btn->connect("pressed", callable_mp(this, &EditorPropertyArray::_remove_pressed).bind(idx)); + hbox->add_child(remove_btn); + } + property_vbox->add_child(hbox); + + Slot slot; + slot.prop = prop; + slot.object = object; + slot.container = hbox; + slot.reorder_button = reorder_button; + slot.set_index(idx + page_index * page_length); + slots.push_back(slot); +} + void EditorPropertyArray::update_property() { Variant array = get_edited_property_value(); @@ -276,7 +312,6 @@ void EditorPropertyArray::update_property() { int size = array.call("size"); int max_page = MAX(0, size - 1) / page_length; page_index = MIN(page_index, max_page); - int offset = page_index * page_length; edit->set_text(vformat(TTR("%s (size %s)"), array_type_name, itos(size))); @@ -326,16 +361,9 @@ void EditorPropertyArray::update_property() { paginator = memnew(EditorPaginator); paginator->connect("page_changed", callable_mp(this, &EditorPropertyArray::_page_changed)); vbox->add_child(paginator); - } else { - // Bye bye children of the box. - for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) { - Node *child = property_vbox->get_child(i); - if (child == reorder_selected_element_hbox) { - continue; // Don't remove the property that the user is moving. - } - child->queue_free(); // Button still needed after pressed is called. - property_vbox->remove_child(child); + for (int i = 0; i < page_length; i++) { + create_new_property_slot(); } } @@ -345,81 +373,46 @@ void EditorPropertyArray::update_property() { paginator->update(page_index, max_page); paginator->set_visible(max_page > 0); - int amount = MIN(size - offset, page_length); - for (int i = 0; i < amount; i++) { - bool reorder_is_from_current_page = reorder_from_index / page_length == page_index; - if (reorder_is_from_current_page && i == reorder_from_index % page_length) { - // Don't duplicate the property that the user is moving. - continue; - } - if (!reorder_is_from_current_page && i == reorder_to_index % page_length) { - // Don't create the property the moving property will take the place of, - // e.g. (if page_length == 20) don't create element 20 if dragging an item from - // the first page to the second page because element 20 would become element 19. + for (Slot &slot : slots) { + bool slot_visible = &slot != &reorder_slot && slot.index < size; + slot.container->set_visible(slot_visible); + // If not visible no need to update it + if (!slot_visible) { continue; } - HBoxContainer *hbox = memnew(HBoxContainer); - property_vbox->add_child(hbox); - - Button *reorder_button = memnew(Button); - reorder_button->set_icon(get_editor_theme_icon(SNAME("TripleBar"))); - reorder_button->set_default_cursor_shape(Control::CURSOR_MOVE); - reorder_button->set_disabled(is_read_only()); - reorder_button->connect("gui_input", callable_mp(this, &EditorPropertyArray::_reorder_button_gui_input)); - reorder_button->connect("button_down", callable_mp(this, &EditorPropertyArray::_reorder_button_down).bind(i + offset)); - reorder_button->connect("button_up", callable_mp(this, &EditorPropertyArray::_reorder_button_up)); - hbox->add_child(reorder_button); - - String prop_name = "indices/" + itos(i + offset); + int idx = slot.index; + Variant::Type value_type = subtype; - EditorProperty *prop = nullptr; - Variant value = array.get(i + offset); - Variant::Type value_type = value.get_type(); - - if (value_type == Variant::NIL && subtype != Variant::NIL) { - value_type = subtype; + if (value_type == Variant::NIL) { + value_type = array.get(idx).get_type(); } - if (value_type == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(value)) { - EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID); - editor->setup("Object"); - prop = editor; - } else { - prop = EditorInspector::instantiate_property_editor(nullptr, value_type, "", subtype_hint, subtype_hint_string, PROPERTY_USAGE_NONE); - } - - prop->set_object_and_property(object.ptr(), prop_name); - prop->set_label(itos(i + offset)); - prop->set_selectable(false); - prop->set_use_folding(is_using_folding()); - prop->connect("property_changed", callable_mp(this, &EditorPropertyArray::_property_changed)); - prop->connect("object_id_selected", callable_mp(this, &EditorPropertyArray::_object_id_selected)); - prop->set_h_size_flags(SIZE_EXPAND_FILL); - prop->set_read_only(is_read_only()); - hbox->add_child(prop); - - bool is_untyped_array = array.get_type() == Variant::ARRAY && subtype == Variant::NIL; - - if (is_untyped_array) { - Button *edit_btn = memnew(Button); - edit_btn->set_icon(get_editor_theme_icon(SNAME("Edit"))); - hbox->add_child(edit_btn); - edit_btn->set_disabled(is_read_only()); - edit_btn->connect("pressed", callable_mp(this, &EditorPropertyArray::_change_type).bind(edit_btn, i + offset)); - } else { - Button *remove_btn = memnew(Button); - remove_btn->set_icon(get_editor_theme_icon(SNAME("Remove"))); - remove_btn->set_disabled(is_read_only()); - remove_btn->connect("pressed", callable_mp(this, &EditorPropertyArray::_remove_pressed).bind(i + offset)); - hbox->add_child(remove_btn); + // Check if the editor property needs to be updated. + bool value_as_id = Object::cast_to<EncodedObjectAsID>(array.get(idx)); + if (value_type != slot.type || (value_type == Variant::OBJECT && (value_as_id != slot.as_id))) { + slot.as_id = value_as_id; + slot.type = value_type; + EditorProperty *new_prop = nullptr; + if (value_type == Variant::OBJECT && value_as_id) { + EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID); + editor->setup("Object"); + new_prop = editor; + } else { + new_prop = EditorInspector::instantiate_property_editor(nullptr, value_type, "", subtype_hint, subtype_hint_string, PROPERTY_USAGE_NONE); + } + new_prop->set_selectable(false); + new_prop->set_use_folding(is_using_folding()); + new_prop->connect(SNAME("property_changed"), callable_mp(this, &EditorPropertyArray::_property_changed)); + new_prop->connect(SNAME("object_id_selected"), callable_mp(this, &EditorPropertyArray::_object_id_selected)); + new_prop->set_h_size_flags(SIZE_EXPAND_FILL); + new_prop->set_read_only(is_read_only()); + slot.prop->add_sibling(new_prop, false); + slot.prop->queue_free(); + slot.prop = new_prop; + slot.set_index(idx); } - - prop->update_property(); - } - - if (reorder_to_index % page_length > 0) { - property_vbox->move_child(property_vbox->get_child(0), reorder_to_index % page_length); + slot.prop->update_property(); } updating = false; @@ -430,13 +423,14 @@ void EditorPropertyArray::update_property() { memdelete(container); button_add_item = nullptr; container = nullptr; + slots.clear(); } } } -void EditorPropertyArray::_remove_pressed(int p_index) { +void EditorPropertyArray::_remove_pressed(int p_slot_index) { Variant array = object->get_array().duplicate(); - array.call("remove_at", p_index); + array.call("remove_at", slots[p_slot_index].index); emit_changed(get_edited_property(), array, "", false); update_property(); @@ -468,7 +462,7 @@ bool EditorPropertyArray::_is_drop_valid(const Dictionary &p_drag_data) const { Vector<String> files = drag_data["files"]; for (int i = 0; i < files.size(); i++) { - String file = files[i]; + const String &file = files[i]; String ftype = EditorFileSystem::get_singleton()->get_file_type(file); for (int j = 0; j < allowed_type.get_slice_count(","); j++) { @@ -510,7 +504,7 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d // Loop the file array and add to existing array. for (int i = 0; i < files.size(); i++) { - String file = files[i]; + const String &file = files[i]; Ref<Resource> res = ResourceLoader::load(file); if (res.is_valid()) { @@ -579,6 +573,27 @@ void EditorPropertyArray::_page_changed(int p_page) { return; } page_index = p_page; + int i = p_page * page_length; + + if (reorder_slot.index < 0) { + for (Slot &slot : slots) { + slot.set_index(i); + i++; + } + } else { + int reorder_from_page = reorder_slot.index / page_length; + if (reorder_from_page < p_page) { + i++; + } + for (Slot &slot : slots) { + if (slot.index != reorder_slot.index) { + slot.set_index(i); + i++; + } else if (i == reorder_slot.index) { + i++; + } + } + } update_property(); } @@ -620,7 +635,7 @@ void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint } void EditorPropertyArray::_reorder_button_gui_input(const Ref<InputEvent> &p_event) { - if (reorder_from_index < 0 || is_read_only()) { + if (reorder_slot.index < 0 || is_read_only()) { return; } @@ -645,26 +660,25 @@ void EditorPropertyArray::_reorder_button_gui_input(const Ref<InputEvent> &p_eve reorder_mouse_y_delta -= required_y_distance * direction; reorder_to_index += direction; + + property_vbox->move_child(reorder_slot.container, reorder_to_index % page_length); + if ((direction < 0 && reorder_to_index % page_length == page_length - 1) || (direction > 0 && reorder_to_index % page_length == 0)) { // Automatically move to the next/previous page. _page_changed(page_index + direction); } - property_vbox->move_child(reorder_selected_element_hbox, reorder_to_index % page_length); // Ensure the moving element is visible. - InspectorDock::get_inspector_singleton()->ensure_control_visible(reorder_selected_element_hbox); + InspectorDock::get_inspector_singleton()->ensure_control_visible(reorder_slot.container); } } } -void EditorPropertyArray::_reorder_button_down(int p_index) { +void EditorPropertyArray::_reorder_button_down(int p_slot_index) { if (is_read_only()) { return; } - - reorder_from_index = p_index; - reorder_to_index = p_index; - reorder_selected_element_hbox = Object::cast_to<HBoxContainer>(property_vbox->get_child(p_index % page_length)); - reorder_selected_button = Object::cast_to<Button>(reorder_selected_element_hbox->get_child(0)); + reorder_slot = slots[p_slot_index]; + reorder_to_index = reorder_slot.index; // Ideally it'd to be able to show the mouse but I had issues with // Control's `mouse_exit()`/`mouse_entered()` signals not getting called. Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); @@ -675,29 +689,27 @@ void EditorPropertyArray::_reorder_button_up() { return; } - if (reorder_from_index != reorder_to_index) { + if (reorder_slot.index != reorder_to_index) { // Move the element. Variant array = object->get_array().duplicate(); - Variant value_to_move = array.get(reorder_from_index); - array.call("remove_at", reorder_from_index); + property_vbox->move_child(reorder_slot.container, reorder_slot.index % page_length); + Variant value_to_move = array.get(reorder_slot.index); + array.call("remove_at", reorder_slot.index); array.call("insert", reorder_to_index, value_to_move); + reorder_slot.index = reorder_slot.index % page_length + page_index * page_length; emit_changed(get_edited_property(), array, "", false); - update_property(); } - reorder_from_index = -1; - reorder_to_index = -1; - reorder_mouse_y_delta = 0.0f; - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); - ERR_FAIL_NULL(reorder_selected_button); - reorder_selected_button->warp_mouse(reorder_selected_button->get_size() / 2.0f); - - reorder_selected_element_hbox = nullptr; - reorder_selected_button = nullptr; + ERR_FAIL_NULL(reorder_slot.reorder_button); + reorder_slot.reorder_button->warp_mouse(reorder_slot.reorder_button->get_size() / 2.0f); + reorder_to_index = -1; + reorder_mouse_y_delta = 0.0f; + reorder_slot = Slot(); + _page_changed(page_index); } void EditorPropertyArray::_bind_methods() { diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h index 2ca1931f85..f157da00c2 100644 --- a/editor/editor_properties_array_dict.h +++ b/editor/editor_properties_array_dict.h @@ -81,6 +81,23 @@ public: class EditorPropertyArray : public EditorProperty { GDCLASS(EditorPropertyArray, EditorProperty); + struct Slot { + Ref<EditorPropertyArrayObject> object; + HBoxContainer *container = nullptr; + int index = -1; + Variant::Type type = Variant::VARIANT_MAX; + bool as_id = false; + EditorProperty *prop = nullptr; + Button *reorder_button = nullptr; + + void set_index(int p_idx) { + String prop_name = "indices/" + itos(p_idx); + prop->set_object_and_property(object.ptr(), prop_name); + prop->set_label(itos(p_idx)); + index = p_idx; + } + }; + PopupMenu *change_type = nullptr; int page_length = 20; @@ -96,13 +113,11 @@ class EditorPropertyArray : public EditorProperty { Variant::Type subtype; PropertyHint subtype_hint; String subtype_hint_string; + LocalVector<Slot> slots; - int reorder_from_index = -1; + Slot reorder_slot; int reorder_to_index = -1; float reorder_mouse_y_delta = 0.0f; - HBoxContainer *reorder_selected_element_hbox = nullptr; - Button *reorder_selected_button = nullptr; - void initialize_array(Variant &p_array); void _page_changed(int p_page); @@ -110,6 +125,7 @@ class EditorPropertyArray : public EditorProperty { void _reorder_button_gui_input(const Ref<InputEvent> &p_event); void _reorder_button_down(int p_index); void _reorder_button_up(); + void create_new_property_slot(); protected: Ref<EditorPropertyArrayObject> object; @@ -124,7 +140,7 @@ protected: virtual void _length_changed(double p_page); virtual void _edit_pressed(); virtual void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false); - virtual void _change_type(Object *p_button, int p_index); + virtual void _change_type(Object *p_button, int p_slot_index); virtual void _change_type_menu(int p_index); virtual void _object_id_selected(const StringName &p_property, ObjectID p_id); diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp index b9144375bc..2c9c2f1ab2 100644 --- a/editor/editor_property_name_processor.cpp +++ b/editor/editor_property_name_processor.cpp @@ -224,6 +224,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { //capitalize_string_remaps["msec"] = "(msec)"; // Unit. capitalize_string_remaps["navmesh"] = "NavMesh"; capitalize_string_remaps["nfc"] = "NFC"; + capitalize_string_remaps["oidn"] = "OIDN"; capitalize_string_remaps["ok"] = "OK"; capitalize_string_remaps["opengl"] = "OpenGL"; capitalize_string_remaps["opentype"] = "OpenType"; diff --git a/editor/editor_quick_open.cpp b/editor/editor_quick_open.cpp index 965d0269d6..f39872ba2c 100644 --- a/editor/editor_quick_open.cpp +++ b/editor/editor_quick_open.cpp @@ -32,7 +32,7 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" Rect2i EditorQuickOpen::prev_rect = Rect2i(); bool EditorQuickOpen::was_showed = false; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index ed20e50685..27ce27591f 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -34,7 +34,6 @@ #include "editor/editor_node.h" #include "editor/editor_quick_open.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/filesystem_dock.h" @@ -42,6 +41,7 @@ #include "editor/plugins/editor_resource_conversion_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/scene_tree_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/gui/texture_rect.h" #include "scene/resources/gradient_texture.h" @@ -487,38 +487,16 @@ void EditorResourcePicker::set_create_options(Object *p_menu_node) { HashSet<StringName> allowed_types; _get_allowed_types(false, &allowed_types); - Vector<EditorData::CustomType> custom_resources; - if (EditorNode::get_editor_data().get_custom_types().has("Resource")) { - custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; - } - for (const StringName &E : allowed_types) { const String &t = E; - bool is_custom_resource = false; - Ref<Texture2D> icon; - if (!custom_resources.is_empty()) { - for (int j = 0; j < custom_resources.size(); j++) { - if (custom_resources[j].name == t) { - is_custom_resource = true; - if (custom_resources[j].icon.is_valid()) { - icon = custom_resources[j].icon; - } - break; - } - } - } - - if (!is_custom_resource && !ClassDB::can_instantiate(t)) { + if (!ClassDB::can_instantiate(t)) { continue; } inheritors_array.push_back(t); - if (!icon.is_valid()) { - icon = get_editor_theme_icon(has_theme_icon(t, EditorStringName(EditorIcons)) ? t : String("Object")); - } - + Ref<Texture2D> icon = EditorNode::get_singleton()->get_class_icon(t, "Object"); int id = TYPE_BASE_ID + idx; edit_menu->add_icon_item(icon, vformat(TTR("New %s"), t), id); @@ -675,7 +653,7 @@ bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const { return false; } -bool EditorResourcePicker::_is_type_valid(const String p_type_name, HashSet<StringName> p_allowed_types) const { +bool EditorResourcePicker::_is_type_valid(const String p_type_name, const HashSet<StringName> &p_allowed_types) const { for (const StringName &E : p_allowed_types) { String at = E; if (p_type_name == at || ClassDB::is_parent_class(p_type_name, at) || EditorNode::get_editor_data().script_class_is_parent(p_type_name, at)) { @@ -804,7 +782,12 @@ void EditorResourcePicker::_notification(int p_what) { [[fallthrough]]; } case NOTIFICATION_THEME_CHANGED: { - assign_button->add_theme_constant_override("icon_max_width", get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor))); + const int icon_width = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)); + assign_button->add_theme_constant_override("icon_max_width", icon_width); + if (edit_menu) { + edit_menu->add_theme_constant_override("icon_max_width", icon_width); + } + edit_button->set_icon(get_theme_icon(SNAME("select_arrow"), SNAME("Tree"))); } break; @@ -940,6 +923,7 @@ void EditorResourcePicker::_ensure_resource_menu() { return; } edit_menu = memnew(PopupMenu); + edit_menu->add_theme_constant_override("icon_max_width", get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor))); add_child(edit_menu); edit_menu->connect("id_pressed", callable_mp(this, &EditorResourcePicker::_edit_menu_cbk)); edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed).bind(false)); diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h index 35703bcbeb..fb54455e89 100644 --- a/editor/editor_resource_picker.h +++ b/editor/editor_resource_picker.h @@ -99,7 +99,7 @@ class EditorResourcePicker : public HBoxContainer { String _get_resource_type(const Ref<Resource> &p_resource) const; void _get_allowed_types(bool p_with_convert, HashSet<StringName> *p_vector) const; bool _is_drop_valid(const Dictionary &p_drag_data) const; - bool _is_type_valid(const String p_type_name, HashSet<StringName> p_allowed_types) const; + bool _is_type_valid(const String p_type_name, const HashSet<StringName> &p_allowed_types) const; Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index b3340dffc1..1702277ebc 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -34,14 +34,14 @@ #include "core/io/file_access.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" -#include "core/object/message_queue.h" #include "core/variant/variant_utility.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/image_texture.h" +#include "servers/rendering/rendering_server_default.h" bool EditorResourcePreviewGenerator::handles(const String &p_type) const { bool success = false; @@ -123,7 +123,7 @@ void EditorResourcePreview::_preview_ready(const String &p_path, int p_hash, con cache[p_path] = item; } - MessageQueue::get_singleton()->push_call(id, p_func, p_path, p_texture, p_small_texture, p_ud); + Callable(id, p_func).call_deferred(p_path, p_texture, p_small_texture, p_ud); } void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base, Dictionary &p_metadata) { @@ -339,6 +339,20 @@ void EditorResourcePreview::_thread() { exited.set(); } +void EditorResourcePreview::_idle_callback() { + if (!singleton) { + // Just in case the shutdown of the editor involves the deletion of the singleton + // happening while additional idle callbacks can happen. + return; + } + + // Process preview tasks, trying to leave a little bit of responsiveness worst case. + uint64_t start = OS::get_singleton()->get_ticks_msec(); + while (!singleton->queue.is_empty() && OS::get_singleton()->get_ticks_msec() - start < 100) { + singleton->_iterate(); + } +} + void EditorResourcePreview::_update_thumbnail_sizes() { if (small_thumbnail_size == -1) { // Kind of a workaround to retrieve the default icon size. @@ -442,27 +456,36 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) { } void EditorResourcePreview::start() { - if (DisplayServer::get_singleton()->get_name() != "headless") { + if (DisplayServer::get_singleton()->get_name() == "headless") { + return; + } + + if (RSG::texture_storage->can_create_resources_async()) { ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started."); thread.start(_thread_func, this); + } else { + SceneTree *st = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop()); + ERR_FAIL_NULL_MSG(st, "Editor's MainLoop is not a SceneTree. This is a bug."); } } void EditorResourcePreview::stop() { - if (thread.is_started()) { - exiting.set(); - preview_sem.post(); + if (RSG::texture_storage->can_create_resources_async()) { + if (thread.is_started()) { + exiting.set(); + preview_sem.post(); - for (int i = 0; i < preview_generators.size(); i++) { - preview_generators.write[i]->abort(); - } + for (int i = 0; i < preview_generators.size(); i++) { + preview_generators.write[i]->abort(); + } - while (!exited.is_set()) { - OS::get_singleton()->delay_usec(10000); - RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on rendering server - } + while (!exited.is_set()) { + OS::get_singleton()->delay_usec(10000); + RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on rendering server + } - thread.wait_to_finish(); + thread.wait_to_finish(); + } } } diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index 324245ba23..bc99372bc2 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -103,7 +103,8 @@ class EditorResourcePreview : public Node { int small_thumbnail_size = -1; static void _thread_func(void *ud); - void _thread(); + void _thread(); // For rendering drivers supporting async texture creation. + static void _idle_callback(); // For other rendering drivers (i.e., OpenGL). void _iterate(); void _write_preview_cache(Ref<FileAccess> p_file, int p_thumbnail_size, bool p_has_small_texture, uint64_t p_modified_time, String p_hash, const Dictionary &p_metadata); diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index 6744e79931..fd6b083c12 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -31,10 +31,10 @@ #include "editor_run_native.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/export/editor_export.h" #include "editor/export/editor_export_platform.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/image_texture.h" void EditorRunNative::_notification(int p_what) { diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp index 7bf88ba94f..8d1f97f6b1 100644 --- a/editor/editor_sectioned_inspector.cpp +++ b/editor/editor_sectioned_inspector.cpp @@ -31,9 +31,9 @@ #include "editor_sectioned_inspector.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" static bool _property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style) { if (p_property_path.findn(p_filter) != -1) { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 98706a10f2..b565431185 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -460,6 +460,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Theme EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/preset", "Default", "Default,Breeze Dark,Godot 2,Gray,Light,Solarized (Dark),Solarized (Light),Black (OLED),Custom") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/spacing_preset", "Default", "Compact,Default,Spacious,Custom") EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/theme/icon_and_font_color", 0, "Auto,Dark,Light") EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/base_color", Color(0.2, 0.23, 0.31), "") EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/accent_color", Color(0.41, 0.61, 0.91), "") @@ -469,7 +470,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/relationship_line_opacity", 0.1, "0.00,1,0.01") EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/border_size", 0, "0,2,1") EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/corner_radius", 3, "0,6,1") - EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/additional_spacing", 0.0, "0,5,0.1") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/base_spacing", 4, "0,8,1") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/additional_spacing", 0, "0,8,1") EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/theme/custom_theme", "", "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) // Touchscreen @@ -500,6 +502,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/external_programs/vector_image_editor", "", "") EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/external_programs/audio_editor", "", "") EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/external_programs/3d_model_editor", "", "") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/external_programs/terminal_emulator", "", "") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_PLACEHOLDER_TEXT, "filesystem/external_programs/terminal_emulator_flags", "", "Call flags with placeholder: {directory}."); // Directories EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/directories/autoscan_project_path", "", "") diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index a5e70c5b6c..becc376cd4 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -38,12 +38,12 @@ #include "editor/editor_log.h" #include "editor/editor_node.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/event_listener_line_edit.h" #include "editor/input_event_configuration_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/margin_container.h" void EditorSettingsDialog::ok_pressed() { @@ -62,8 +62,12 @@ void EditorSettingsDialog::_settings_changed() { void EditorSettingsDialog::_settings_property_edited(const String &p_name) { String full_name = inspector->get_full_item_path(p_name); + // Set theme presets to Custom when controlled settings change. + if (full_name == "interface/theme/accent_color" || full_name == "interface/theme/base_color" || full_name == "interface/theme/contrast" || full_name == "interface/theme/draw_extra_borders") { - EditorSettings::get_singleton()->set_manually("interface/theme/preset", "Custom"); // set preset to Custom + EditorSettings::get_singleton()->set_manually("interface/theme/preset", "Custom"); + } else if (full_name == "interface/theme/base_spacing" || full_name == "interface/theme/additional_spacing") { + EditorSettings::get_singleton()->set_manually("interface/theme/spacing_preset", "Custom"); } else if (full_name.begins_with("text_editor/theme/highlighting")) { EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom"); } @@ -92,9 +96,6 @@ void EditorSettingsDialog::popup_edit_settings() { inspector->edit(EditorSettings::get_singleton()); inspector->get_inspector()->update_tree(); - search_box->select_all(); - search_box->grab_focus(); - _update_shortcuts(); set_process_shortcut_input(true); @@ -762,7 +763,7 @@ EditorSettingsDialog::EditorSettingsDialog() { tab_shortcuts->add_child(top_hbox); shortcut_search_box = memnew(LineEdit); - shortcut_search_box->set_placeholder(TTR("Filter by name...")); + shortcut_search_box->set_placeholder(TTR("Filter by Name")); shortcut_search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); top_hbox->add_child(shortcut_search_box); shortcut_search_box->connect("text_changed", callable_mp(this, &EditorSettingsDialog::_filter_shortcuts)); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp deleted file mode 100644 index ef68554a3d..0000000000 --- a/editor/editor_themes.cpp +++ /dev/null @@ -1,2401 +0,0 @@ -/**************************************************************************/ -/* editor_themes.cpp */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/**************************************************************************/ - -#include "editor_themes.h" - -#include "core/error/error_macros.h" -#include "core/io/resource_loader.h" -#include "editor/editor_fonts.h" -#include "editor/editor_icons.gen.h" -#include "editor/editor_scale.h" -#include "editor/editor_settings.h" -#include "editor/editor_string_names.h" -#include "scene/resources/image_texture.h" -#include "scene/resources/style_box_flat.h" -#include "scene/resources/style_box_line.h" -#include "scene/resources/style_box_texture.h" -#include "scene/theme/theme_db.h" - -#include "modules/modules_enabled.gen.h" // For svg. -#ifdef MODULE_SVG_ENABLED -#include "modules/svg/image_loader_svg.h" -#endif - -HashMap<Color, Color> EditorColorMap::color_conversion_map; -HashSet<StringName> EditorColorMap::color_conversion_exceptions; - -void EditorColorMap::add_conversion_color_pair(const String p_from_color, const String p_to_color) { - color_conversion_map[Color::html(p_from_color)] = Color::html(p_to_color); -} - -void EditorColorMap::add_conversion_exception(const StringName &p_icon_name) { - color_conversion_exceptions.insert(p_icon_name); -} - -void EditorColorMap::create() { - // Some of the colors below are listed for completeness sake. - // This can be a basis for proper palette validation later. - - // Convert: FROM TO - add_conversion_color_pair("#478cbf", "#478cbf"); // Godot Blue - add_conversion_color_pair("#414042", "#414042"); // Godot Gray - - add_conversion_color_pair("#ffffff", "#414141"); // Pure white - add_conversion_color_pair("#fefefe", "#fefefe"); // Forced light color - add_conversion_color_pair("#000000", "#bfbfbf"); // Pure black - add_conversion_color_pair("#010101", "#010101"); // Forced dark color - - // Keep pure RGB colors as is, but list them for explicitness. - add_conversion_color_pair("#ff0000", "#ff0000"); // Pure red - add_conversion_color_pair("#00ff00", "#00ff00"); // Pure green - add_conversion_color_pair("#0000ff", "#0000ff"); // Pure blue - - // GUI Colors - add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Common icon color - add_conversion_color_pair("#808080", "#808080"); // GUI disabled color - add_conversion_color_pair("#b3b3b3", "#363636"); // GUI disabled light color - add_conversion_color_pair("#699ce8", "#699ce8"); // GUI highlight color - add_conversion_color_pair("#f9f9f9", "#606060"); // Scrollbar grabber highlight color - - add_conversion_color_pair("#c38ef1", "#a85de9"); // Animation - add_conversion_color_pair("#8da5f3", "#3d64dd"); // 2D - add_conversion_color_pair("#7582a8", "#6d83c8"); // 2D Abstract - add_conversion_color_pair("#fc7f7f", "#cd3838"); // 3D - add_conversion_color_pair("#b56d6d", "#be6a6a"); // 3D Abstract - add_conversion_color_pair("#8eef97", "#2fa139"); // GUI Control - add_conversion_color_pair("#76ad7b", "#64a66a"); // GUI Control Abstract - - add_conversion_color_pair("#5fb2ff", "#0079f0"); // Selection (blue) - add_conversion_color_pair("#003e7a", "#2b74bb"); // Selection (darker blue) - add_conversion_color_pair("#f7f5cf", "#615f3a"); // Gizmo (yellow) - - // Rainbow - add_conversion_color_pair("#ff4545", "#ff2929"); // Red - add_conversion_color_pair("#ffe345", "#ffe337"); // Yellow - add_conversion_color_pair("#80ff45", "#74ff34"); // Green - add_conversion_color_pair("#45ffa2", "#2cff98"); // Aqua - add_conversion_color_pair("#45d7ff", "#22ccff"); // Blue - add_conversion_color_pair("#8045ff", "#702aff"); // Purple - add_conversion_color_pair("#ff4596", "#ff2781"); // Pink - - // Audio gradients - add_conversion_color_pair("#e1da5b", "#d6cf4b"); // Yellow - - add_conversion_color_pair("#62aeff", "#1678e0"); // Frozen gradient top - add_conversion_color_pair("#75d1e6", "#41acc5"); // Frozen gradient middle - add_conversion_color_pair("#84ffee", "#49ccba"); // Frozen gradient bottom - - add_conversion_color_pair("#f70000", "#c91616"); // Color track red - add_conversion_color_pair("#eec315", "#d58c0b"); // Color track orange - add_conversion_color_pair("#dbee15", "#b7d10a"); // Color track yellow - add_conversion_color_pair("#288027", "#218309"); // Color track green - - // Other objects - add_conversion_color_pair("#ffca5f", "#fea900"); // Mesh resource (orange) - add_conversion_color_pair("#2998ff", "#68b6ff"); // Shape resource (blue) - add_conversion_color_pair("#a2d2ff", "#4998e3"); // Shape resource (light blue) - add_conversion_color_pair("#69c4d4", "#29a3cc"); // Input event highlight (light blue) - - // Animation editor tracks - // The property track icon color is set by the common icon color. - add_conversion_color_pair("#ea7940", "#bd5e2c"); // 3D Position track - add_conversion_color_pair("#ff2b88", "#bd165f"); // 3D Rotation track - add_conversion_color_pair("#eac840", "#bd9d1f"); // 3D Scale track - add_conversion_color_pair("#3cf34e", "#16a827"); // Call Method track - add_conversion_color_pair("#2877f6", "#236be6"); // Bezier Curve track - add_conversion_color_pair("#eae440", "#9f9722"); // Audio Playback track - add_conversion_color_pair("#a448f0", "#9853ce"); // Animation Playback track - add_conversion_color_pair("#5ad5c4", "#0a9c88"); // Blend Shape track - - // Control layouts - add_conversion_color_pair("#d6d6d6", "#474747"); // Highlighted part - add_conversion_color_pair("#474747", "#d6d6d6"); // Background part - add_conversion_color_pair("#919191", "#6e6e6e"); // Border part - - // TileSet editor icons - add_conversion_color_pair("#fce00e", "#aa8d24"); // New Single Tile - add_conversion_color_pair("#0e71fc", "#0350bd"); // New Autotile - add_conversion_color_pair("#c6ced4", "#828f9b"); // New Atlas - - // Variant types - add_conversion_color_pair("#41ecad", "#25e3a0"); // Variant - add_conversion_color_pair("#6f91f0", "#6d8eeb"); // bool - add_conversion_color_pair("#5abbef", "#4fb2e9"); // int/uint - add_conversion_color_pair("#35d4f4", "#27ccf0"); // float - add_conversion_color_pair("#4593ec", "#4690e7"); // String - add_conversion_color_pair("#ee5677", "#ee7991"); // AABB - add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Array - add_conversion_color_pair("#e1ec41", "#b2bb19"); // Basis - add_conversion_color_pair("#54ed9e", "#57e99f"); // Dictionary - add_conversion_color_pair("#417aec", "#6993ec"); // NodePath - add_conversion_color_pair("#55f3e3", "#12d5c3"); // Object - add_conversion_color_pair("#f74949", "#f77070"); // Plane - add_conversion_color_pair("#44bd44", "#46b946"); // Projection - add_conversion_color_pair("#ec418e", "#ec69a3"); // Quaternion - add_conversion_color_pair("#f1738f", "#ee758e"); // Rect2 - add_conversion_color_pair("#41ec80", "#2ce573"); // RID - add_conversion_color_pair("#b9ec41", "#96ce1a"); // Transform2D - add_conversion_color_pair("#f68f45", "#f49047"); // Transform3D - add_conversion_color_pair("#ac73f1", "#ad76ee"); // Vector2 - add_conversion_color_pair("#de66f0", "#dc6aed"); // Vector3 - add_conversion_color_pair("#f066bd", "#ed6abd"); // Vector4 - - // Visual shaders - add_conversion_color_pair("#77ce57", "#67c046"); // Vector funcs - add_conversion_color_pair("#ea686c", "#d95256"); // Vector transforms - add_conversion_color_pair("#eac968", "#d9b64f"); // Textures and cubemaps - add_conversion_color_pair("#cf68ea", "#c050dd"); // Functions and expressions - - // These icons should not be converted. - add_conversion_exception("EditorPivot"); - add_conversion_exception("EditorHandle"); - add_conversion_exception("Editor3DHandle"); - add_conversion_exception("EditorBoneHandle"); - add_conversion_exception("Godot"); - add_conversion_exception("Sky"); - add_conversion_exception("EditorControlAnchor"); - add_conversion_exception("DefaultProjectIcon"); - add_conversion_exception("ZoomMore"); - add_conversion_exception("ZoomLess"); - add_conversion_exception("ZoomReset"); - add_conversion_exception("LockViewport"); - add_conversion_exception("GroupViewport"); - add_conversion_exception("StatusError"); - add_conversion_exception("StatusSuccess"); - add_conversion_exception("StatusWarning"); - add_conversion_exception("OverbrightIndicator"); - add_conversion_exception("MaterialPreviewCube"); - add_conversion_exception("MaterialPreviewSphere"); - add_conversion_exception("MaterialPreviewLight1"); - add_conversion_exception("MaterialPreviewLight2"); - - // GUI - add_conversion_exception("GuiChecked"); - add_conversion_exception("GuiRadioChecked"); - add_conversion_exception("GuiIndeterminate"); - add_conversion_exception("GuiCloseCustomizable"); - add_conversion_exception("GuiGraphNodePort"); - add_conversion_exception("GuiResizer"); - add_conversion_exception("GuiMiniCheckerboard"); - - /// Code Editor. - add_conversion_exception("GuiTab"); - add_conversion_exception("GuiSpace"); - add_conversion_exception("CodeFoldedRightArrow"); - add_conversion_exception("CodeFoldDownArrow"); - add_conversion_exception("CodeRegionFoldedRightArrow"); - add_conversion_exception("CodeRegionFoldDownArrow"); - add_conversion_exception("TextEditorPlay"); - add_conversion_exception("Breakpoint"); -} - -void EditorColorMap::finish() { - color_conversion_map.clear(); - color_conversion_exceptions.clear(); -} - -Vector<StringName> EditorTheme::editor_theme_types; - -// TODO: Refactor these and corresponding Theme methods to use the bool get_xxx(r_value) pattern internally. - -// Keep in sync with Theme::get_color. -Color EditorTheme::get_color(const StringName &p_name, const StringName &p_theme_type) const { - if (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)) { - return color_map[p_theme_type][p_name]; - } else { - if (editor_theme_types.has(p_theme_type)) { - WARN_PRINT(vformat("Trying to access a non-existing editor theme color '%s' in '%s'.", p_name, p_theme_type)); - } - return Color(); - } -} - -// Keep in sync with Theme::get_constant. -int EditorTheme::get_constant(const StringName &p_name, const StringName &p_theme_type) const { - if (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)) { - return constant_map[p_theme_type][p_name]; - } else { - if (editor_theme_types.has(p_theme_type)) { - WARN_PRINT(vformat("Trying to access a non-existing editor theme constant '%s' in '%s'.", p_name, p_theme_type)); - } - return 0; - } -} - -// Keep in sync with Theme::get_font. -Ref<Font> EditorTheme::get_font(const StringName &p_name, const StringName &p_theme_type) const { - if (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) { - return font_map[p_theme_type][p_name]; - } else if (has_default_font()) { - if (editor_theme_types.has(p_theme_type)) { - WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type)); - } - return default_font; - } else { - if (editor_theme_types.has(p_theme_type)) { - WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type)); - } - return ThemeDB::get_singleton()->get_fallback_font(); - } -} - -// Keep in sync with Theme::get_font_size. -int EditorTheme::get_font_size(const StringName &p_name, const StringName &p_theme_type) const { - if (font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name) && (font_size_map[p_theme_type][p_name] > 0)) { - return font_size_map[p_theme_type][p_name]; - } else if (has_default_font_size()) { - if (editor_theme_types.has(p_theme_type)) { - WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type)); - } - return default_font_size; - } else { - if (editor_theme_types.has(p_theme_type)) { - WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type)); - } - return ThemeDB::get_singleton()->get_fallback_font_size(); - } -} - -// Keep in sync with Theme::get_icon. -Ref<Texture2D> EditorTheme::get_icon(const StringName &p_name, const StringName &p_theme_type) const { - if (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) { - return icon_map[p_theme_type][p_name]; - } else { - if (editor_theme_types.has(p_theme_type)) { - WARN_PRINT(vformat("Trying to access a non-existing editor theme icon '%s' in '%s'.", p_name, p_theme_type)); - } - return ThemeDB::get_singleton()->get_fallback_icon(); - } -} - -// Keep in sync with Theme::get_stylebox. -Ref<StyleBox> EditorTheme::get_stylebox(const StringName &p_name, const StringName &p_theme_type) const { - if (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) { - return style_map[p_theme_type][p_name]; - } else { - if (editor_theme_types.has(p_theme_type)) { - WARN_PRINT(vformat("Trying to access a non-existing editor theme stylebox '%s' in '%s'.", p_name, p_theme_type)); - } - return ThemeDB::get_singleton()->get_fallback_stylebox(); - } -} - -void EditorTheme::initialize() { - editor_theme_types.append(EditorStringName(Editor)); - editor_theme_types.append(EditorStringName(EditorFonts)); - editor_theme_types.append(EditorStringName(EditorIcons)); - editor_theme_types.append(EditorStringName(EditorStyles)); -} - -void EditorTheme::finalize() { - editor_theme_types.clear(); -} - -// Editor theme generatior. - -static Ref<StyleBoxTexture> make_stylebox(Ref<Texture2D> p_texture, float p_left, float p_top, float p_right, float p_bottom, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, bool p_draw_center = true) { - Ref<StyleBoxTexture> style(memnew(StyleBoxTexture)); - style->set_texture(p_texture); - style->set_texture_margin_individual(p_left * EDSCALE, p_top * EDSCALE, p_right * EDSCALE, p_bottom * EDSCALE); - style->set_content_margin_individual((p_left + p_margin_left) * EDSCALE, (p_top + p_margin_top) * EDSCALE, (p_right + p_margin_right) * EDSCALE, (p_bottom + p_margin_bottom) * EDSCALE); - style->set_draw_center(p_draw_center); - return style; -} - -static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { - Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); - style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE); - return style; -} - -static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, int p_corner_width = 0) { - Ref<StyleBoxFlat> style(memnew(StyleBoxFlat)); - style->set_bg_color(p_color); - // Adjust level of detail based on the corners' effective sizes. - style->set_corner_detail(Math::ceil(0.8 * p_corner_width * EDSCALE)); - style->set_corner_radius_all(p_corner_width * EDSCALE); - style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE); - // Work around issue about antialiased edges being blurrier (GH-35279). - style->set_anti_aliased(false); - return style; -} - -static Ref<StyleBoxLine> make_line_stylebox(Color p_color, int p_thickness = 1, float p_grow_begin = 1, float p_grow_end = 1, bool p_vertical = false) { - Ref<StyleBoxLine> style(memnew(StyleBoxLine)); - style->set_color(p_color); - style->set_grow_begin(p_grow_begin); - style->set_grow_end(p_grow_end); - style->set_thickness(p_thickness); - style->set_vertical(p_vertical); - return style; -} - -// See also `generate_icon()` in `scene/theme/default_theme.cpp`. -static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float p_saturation, const HashMap<Color, Color> &p_convert_colors = HashMap<Color, Color>()) { - Ref<Image> img = memnew(Image); - -#ifdef MODULE_SVG_ENABLED - // Upsample icon generation only if the editor scale isn't an integer multiplier. - // Generating upsampled icons is slower, and the benefit is hardly visible - // with integer editor scales. - const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale); - Error err = ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors); - ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in editor theme."); - if (p_saturation != 1.0) { - img->adjust_bcs(1.0, 1.0, p_saturation); - } -#else - // If the SVG module is disabled, we can't really display the UI well, but at least we won't crash. - // 16 pixels is used as it's the most common base size for Godot icons. - img = Image::create_empty(16 * p_scale, 16 * p_scale, false, Image::FORMAT_RGBA8); -#endif - - return ImageTexture::create_from_image(img); -} - -float get_gizmo_handle_scale(const String &gizmo_handle_name = "") { - const float scale_gizmo_handles_for_touch = EDITOR_GET("interface/touchscreen/scale_gizmo_handles"); - if (scale_gizmo_handles_for_touch > 1.0f) { - // The names of the icons that require additional scaling. - static HashSet<StringName> gizmo_to_scale; - if (gizmo_to_scale.is_empty()) { - gizmo_to_scale.insert("EditorHandle"); - gizmo_to_scale.insert("EditorHandleAdd"); - gizmo_to_scale.insert("EditorHandleDisabled"); - gizmo_to_scale.insert("EditorCurveHandle"); - gizmo_to_scale.insert("EditorPathSharpHandle"); - gizmo_to_scale.insert("EditorPathSmoothHandle"); - } - - if (gizmo_to_scale.has(gizmo_handle_name)) { - return EDSCALE * scale_gizmo_handles_for_touch; - } - } - - return EDSCALE; -} - -void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs = false) { - const String benchmark_key = vformat("Generate Icons (%s)", (p_only_thumbs ? "Only Thumbs" : "All")); - OS::get_singleton()->benchmark_begin_measure("EditorTheme", benchmark_key); - - // Before we register the icons, we adjust their colors and saturation. - // Most icons follow the standard rules for color conversion to follow the editor - // theme's polarity (dark/light). We also adjust the saturation for most icons, - // following the editor setting. - // Some icons are excluded from this conversion, and instead use the configured - // accent color to replace their innate accent color to match the editor theme. - // And then some icons are completely excluded from the conversion. - - // Standard color conversion map. - HashMap<Color, Color> color_conversion_map; - // Icons by default are set up for the dark theme, so if the theme is light, - // we apply the dark-to-light color conversion map. - if (!p_dark_theme) { - for (KeyValue<Color, Color> &E : EditorColorMap::get_color_conversion_map()) { - color_conversion_map[E.key] = E.value; - } - } - // These colors should be converted even if we are using a dark theme. - const Color error_color = p_theme->get_color(SNAME("error_color"), EditorStringName(Editor)); - const Color success_color = p_theme->get_color(SNAME("success_color"), EditorStringName(Editor)); - const Color warning_color = p_theme->get_color(SNAME("warning_color"), EditorStringName(Editor)); - color_conversion_map[Color::html("#ff5f5f")] = error_color; - color_conversion_map[Color::html("#5fff97")] = success_color; - color_conversion_map[Color::html("#ffdd65")] = warning_color; - - // The names of the icons to exclude from the standard color conversion. - HashSet<StringName> conversion_exceptions = EditorColorMap::get_color_conversion_exceptions(); - - // The names of the icons to exclude when adjusting for saturation. - HashSet<StringName> saturation_exceptions; - saturation_exceptions.insert("DefaultProjectIcon"); - saturation_exceptions.insert("Godot"); - saturation_exceptions.insert("Logo"); - - // Accent color conversion map. - // It is used on some icons (checkbox, radio, toggle, etc.), regardless of the dark - // or light mode. - HashMap<Color, Color> accent_color_map; - HashSet<StringName> accent_color_icons; - - const Color accent_color = p_theme->get_color(SNAME("accent_color"), EditorStringName(Editor)); - accent_color_map[Color::html("699ce8")] = accent_color; - if (accent_color.get_luminance() > 0.75) { - accent_color_map[Color::html("ffffff")] = Color(0.2, 0.2, 0.2); - } - - accent_color_icons.insert("GuiChecked"); - accent_color_icons.insert("GuiRadioChecked"); - accent_color_icons.insert("GuiIndeterminate"); - accent_color_icons.insert("GuiToggleOn"); - accent_color_icons.insert("GuiToggleOnMirrored"); - accent_color_icons.insert("PlayOverlay"); - - // Generate icons. - if (!p_only_thumbs) { - for (int i = 0; i < editor_icons_count; i++) { - Ref<ImageTexture> icon; - - const String &editor_icon_name = editor_icons_names[i]; - if (accent_color_icons.has(editor_icon_name)) { - icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), 1.0, accent_color_map); - } else { - float saturation = p_icon_saturation; - if (saturation_exceptions.has(editor_icon_name)) { - saturation = 1.0; - } - - if (conversion_exceptions.has(editor_icon_name)) { - icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation); - } else { - icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation, color_conversion_map); - } - } - - p_theme->set_icon(editor_icon_name, EditorStringName(EditorIcons), icon); - } - } - - // Generate thumbnail icons with the given thumbnail size. - // See editor\icons\editor_icons_builders.py for the code that determines which icons are thumbnails. - if (p_thumb_size >= 64) { - const float scale = (float)p_thumb_size / 64.0 * EDSCALE; - for (int i = 0; i < editor_bg_thumbs_count; i++) { - const int index = editor_bg_thumbs_indices[i]; - Ref<ImageTexture> icon; - - if (accent_color_icons.has(editor_icons_names[index])) { - icon = editor_generate_icon(index, scale, 1.0, accent_color_map); - } else { - float saturation = p_icon_saturation; - if (saturation_exceptions.has(editor_icons_names[index])) { - saturation = 1.0; - } - - if (conversion_exceptions.has(editor_icons_names[index])) { - icon = editor_generate_icon(index, scale, saturation); - } else { - icon = editor_generate_icon(index, scale, saturation, color_conversion_map); - } - } - - p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon); - } - } else { - const float scale = (float)p_thumb_size / 32.0 * EDSCALE; - for (int i = 0; i < editor_md_thumbs_count; i++) { - const int index = editor_md_thumbs_indices[i]; - Ref<ImageTexture> icon; - - if (accent_color_icons.has(editor_icons_names[index])) { - icon = editor_generate_icon(index, scale, 1.0, accent_color_map); - } else { - float saturation = p_icon_saturation; - if (saturation_exceptions.has(editor_icons_names[index])) { - saturation = 1.0; - } - - if (conversion_exceptions.has(editor_icons_names[index])) { - icon = editor_generate_icon(index, scale, saturation); - } else { - icon = editor_generate_icon(index, scale, saturation, color_conversion_map); - } - } - - p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon); - } - } - OS::get_singleton()->benchmark_end_measure("EditorTheme", benchmark_key); -} - -Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { - OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Editor Theme"); - Ref<EditorTheme> theme = memnew(EditorTheme); - - // Controls may rely on the scale for their internal drawing logic. - theme->set_default_base_scale(EDSCALE); - - // Theme settings - Color accent_color = EDITOR_GET("interface/theme/accent_color"); - Color base_color = EDITOR_GET("interface/theme/base_color"); - float contrast = EDITOR_GET("interface/theme/contrast"); - bool increase_scrollbar_touch_area = EDITOR_GET("interface/touchscreen/increase_scrollbar_touch_area"); - const float gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles"); - bool draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders"); - float icon_saturation = EDITOR_GET("interface/theme/icon_saturation"); - float relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity"); - - String preset = EDITOR_GET("interface/theme/preset"); - - int border_size = EDITOR_GET("interface/theme/border_size"); - int corner_radius = EDITOR_GET("interface/theme/corner_radius"); - - Color preset_accent_color; - Color preset_base_color; - float preset_contrast = 0; - bool preset_draw_extra_borders = false; - - const float default_contrast = 0.3; - - // Please use alphabetical order if you're adding a new theme here - // (after "Custom") - - if (preset == "Custom") { - accent_color = EDITOR_GET("interface/theme/accent_color"); - base_color = EDITOR_GET("interface/theme/base_color"); - contrast = EDITOR_GET("interface/theme/contrast"); - } else if (preset == "Breeze Dark") { - preset_accent_color = Color(0.26, 0.76, 1.00); - preset_base_color = Color(0.24, 0.26, 0.28); - preset_contrast = default_contrast; - } else if (preset == "Godot 2") { - preset_accent_color = Color(0.53, 0.67, 0.89); - preset_base_color = Color(0.24, 0.23, 0.27); - preset_contrast = default_contrast; - } else if (preset == "Gray") { - preset_accent_color = Color(0.44, 0.73, 0.98); - preset_base_color = Color(0.24, 0.24, 0.24); - preset_contrast = default_contrast; - } else if (preset == "Light") { - preset_accent_color = Color(0.18, 0.50, 1.00); - preset_base_color = Color(0.9, 0.9, 0.9); - // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation". - preset_contrast = -0.06; - } else if (preset == "Solarized (Dark)") { - preset_accent_color = Color(0.15, 0.55, 0.82); - preset_base_color = Color(0.04, 0.23, 0.27); - preset_contrast = default_contrast; - } else if (preset == "Solarized (Light)") { - preset_accent_color = Color(0.15, 0.55, 0.82); - preset_base_color = Color(0.89, 0.86, 0.79); - // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation". - preset_contrast = -0.06; - } else if (preset == "Black (OLED)") { - preset_accent_color = Color(0.45, 0.75, 1.0); - preset_base_color = Color(0, 0, 0); - // The contrast rate value is irrelevant on a fully black theme. - preset_contrast = 0.0; - preset_draw_extra_borders = true; - } else { // Default - preset_accent_color = Color(0.44, 0.73, 0.98); - preset_base_color = Color(0.21, 0.24, 0.29); - preset_contrast = default_contrast; - } - - if (preset != "Custom") { - accent_color = preset_accent_color; - base_color = preset_base_color; - contrast = preset_contrast; - draw_extra_borders = preset_draw_extra_borders; - EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", accent_color); - EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", base_color); - EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", contrast); - EditorSettings::get_singleton()->set_initial_value("interface/theme/draw_extra_borders", draw_extra_borders); - } - - EditorSettings::get_singleton()->set_manually("interface/theme/preset", preset); - EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", accent_color); - EditorSettings::get_singleton()->set_manually("interface/theme/base_color", base_color); - EditorSettings::get_singleton()->set_manually("interface/theme/contrast", contrast); - EditorSettings::get_singleton()->set_manually("interface/theme/draw_extra_borders", draw_extra_borders); - - // Colors - bool dark_theme = EditorSettings::get_singleton()->is_dark_theme(); - -#ifdef MODULE_SVG_ENABLED - if (dark_theme) { - ImageLoaderSVG::set_forced_color_map(HashMap<Color, Color>()); - } else { - ImageLoaderSVG::set_forced_color_map(EditorColorMap::get_color_conversion_map()); - } -#endif - - // Ensure base colors are in the 0..1 luminance range to avoid 8-bit integer overflow or text rendering issues. - // Some places in the editor use 8-bit integer colors. - const Color dark_color_1 = base_color.lerp(Color(0, 0, 0, 1), contrast).clamp(); - const Color dark_color_2 = base_color.lerp(Color(0, 0, 0, 1), contrast * 1.5).clamp(); - const Color dark_color_3 = base_color.lerp(Color(0, 0, 0, 1), contrast * 2).clamp(); - - // Only used when the Draw Extra Borders editor setting is enabled. - const Color extra_border_color_1 = Color(0.5, 0.5, 0.5); - const Color extra_border_color_2 = dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7); - - const Color background_color = dark_color_2; - - // White (dark theme) or black (light theme), will be used to generate the rest of the colors - const Color mono_color = dark_theme ? Color(1, 1, 1) : Color(0, 0, 0); - - const Color contrast_color_1 = base_color.lerp(mono_color, MAX(contrast, default_contrast)); - const Color contrast_color_2 = base_color.lerp(mono_color, MAX(contrast * 1.5, default_contrast * 1.5)); - - const Color font_color = mono_color.lerp(base_color, 0.25); - const Color font_hover_color = mono_color.lerp(base_color, 0.125); - const Color font_focus_color = mono_color.lerp(base_color, 0.125); - const Color font_hover_pressed_color = font_hover_color.lerp(accent_color, 0.74); - const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.35); - const Color font_readonly_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.65); - const Color font_placeholder_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.6); - const Color font_outline_color = Color(0, 0, 0, 0); - const Color selection_color = accent_color * Color(1, 1, 1, 0.4); - const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7); - const Color disabled_bg_color = mono_color.inverted().lerp(base_color, 0.9); - - const Color icon_normal_color = Color(1, 1, 1); - Color icon_hover_color = icon_normal_color * (dark_theme ? 1.15 : 1.45); - icon_hover_color.a = 1.0; - Color icon_focus_color = icon_hover_color; - Color icon_disabled_color = Color(icon_normal_color, 0.4); - // Make the pressed icon color overbright because icons are not completely white on a dark theme. - // On a light theme, icons are dark, so we need to modulate them with an even brighter color. - Color icon_pressed_color = accent_color * (dark_theme ? 1.15 : 3.5); - icon_pressed_color.a = 1.0; - - const Color separator_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.1); - const Color highlight_color = Color(accent_color.r, accent_color.g, accent_color.b, 0.275); - const Color disabled_highlight_color = highlight_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5); - - // Can't save single float in theme, so using Color. - theme->set_color("icon_saturation", EditorStringName(Editor), Color(icon_saturation, icon_saturation, icon_saturation)); - theme->set_color("accent_color", EditorStringName(Editor), accent_color); - theme->set_color("highlight_color", EditorStringName(Editor), highlight_color); - theme->set_color("disabled_highlight_color", EditorStringName(Editor), disabled_highlight_color); - theme->set_color("base_color", EditorStringName(Editor), base_color); - theme->set_color("dark_color_1", EditorStringName(Editor), dark_color_1); - theme->set_color("dark_color_2", EditorStringName(Editor), dark_color_2); - theme->set_color("dark_color_3", EditorStringName(Editor), dark_color_3); - theme->set_color("contrast_color_1", EditorStringName(Editor), contrast_color_1); - theme->set_color("contrast_color_2", EditorStringName(Editor), contrast_color_2); - theme->set_color("box_selection_fill_color", EditorStringName(Editor), accent_color * Color(1, 1, 1, 0.3)); - theme->set_color("box_selection_stroke_color", EditorStringName(Editor), accent_color * Color(1, 1, 1, 0.8)); - - theme->set_color("axis_x_color", EditorStringName(Editor), Color(0.96, 0.20, 0.32)); - theme->set_color("axis_y_color", EditorStringName(Editor), Color(0.53, 0.84, 0.01)); - theme->set_color("axis_z_color", EditorStringName(Editor), Color(0.16, 0.55, 0.96)); - theme->set_color("axis_w_color", EditorStringName(Editor), Color(0.55, 0.55, 0.55)); - - const float prop_color_saturation = accent_color.get_s() * 0.75; - const float prop_color_value = accent_color.get_v(); - - theme->set_color("property_color_x", EditorStringName(Editor), Color().from_hsv(0.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); - theme->set_color("property_color_y", EditorStringName(Editor), Color().from_hsv(1.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); - theme->set_color("property_color_z", EditorStringName(Editor), Color().from_hsv(2.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); - theme->set_color("property_color_w", EditorStringName(Editor), Color().from_hsv(1.5 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); - - theme->set_color("font_color", EditorStringName(Editor), font_color); - theme->set_color("highlighted_font_color", EditorStringName(Editor), font_hover_color); - theme->set_color("disabled_font_color", EditorStringName(Editor), font_disabled_color); - theme->set_color("readonly_font_color", EditorStringName(Editor), font_readonly_color); - - theme->set_color("mono_color", EditorStringName(Editor), mono_color); - - Color success_color = Color(0.45, 0.95, 0.5); - Color warning_color = Color(1, 0.87, 0.4); - Color error_color = Color(1, 0.47, 0.42); - Color property_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.5); - Color readonly_color = property_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25); - Color readonly_warning_color = error_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25); - - if (!dark_theme) { - // Darken some colors to be readable on a light background. - success_color = success_color.lerp(mono_color, 0.35); - warning_color = warning_color.lerp(mono_color, 0.35); - error_color = error_color.lerp(mono_color, 0.25); - } - - theme->set_color("success_color", EditorStringName(Editor), success_color); - theme->set_color("warning_color", EditorStringName(Editor), warning_color); - theme->set_color("error_color", EditorStringName(Editor), error_color); - theme->set_color("property_color", EditorStringName(Editor), property_color); - theme->set_color("readonly_color", EditorStringName(Editor), readonly_color); - - if (!dark_theme) { - theme->set_color("highend_color", EditorStringName(Editor), Color::hex(0xad1128ff)); - } else { - theme->set_color("highend_color", EditorStringName(Editor), Color(1.0, 0.0, 0.0)); - } - - const int thumb_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size"); - theme->set_constant("scale", EditorStringName(Editor), EDSCALE); - theme->set_constant("thumb_size", EditorStringName(Editor), thumb_size); - theme->set_constant("class_icon_size", EditorStringName(Editor), 16 * EDSCALE); - theme->set_constant("dark_theme", EditorStringName(Editor), dark_theme); - theme->set_constant("color_picker_button_height", EditorStringName(Editor), 28 * EDSCALE); - theme->set_constant("gizmo_handle_scale", EditorStringName(Editor), gizmo_handle_scale); - theme->set_constant("window_border_margin", EditorStringName(Editor), 8); - theme->set_constant("top_bar_separation", EditorStringName(Editor), 8 * EDSCALE); - - // Register editor icons. - // If the settings are comparable to the old theme, then just copy them over. - // Otherwise, regenerate them. Also check if we need to regenerate "thumb" icons. - bool keep_old_icons = false; - bool regenerate_thumb_icons = true; - if (p_theme != nullptr) { - // We check editor scale, theme dark/light mode, icon saturation, and accent color. - - // That doesn't really work as expected, since theme constants are integers, and scales are floats. - // So this check will never work when changing between 100-199% values. - const float prev_scale = (float)p_theme->get_constant(SNAME("scale"), EditorStringName(Editor)); - const bool prev_dark_theme = (bool)p_theme->get_constant(SNAME("dark_theme"), EditorStringName(Editor)); - const Color prev_accent_color = p_theme->get_color(SNAME("accent_color"), EditorStringName(Editor)); - const float prev_icon_saturation = p_theme->get_color(SNAME("icon_saturation"), EditorStringName(Editor)).r; - const float prev_gizmo_handle_scale = (float)p_theme->get_constant(SNAME("gizmo_handle_scale"), EditorStringName(Editor)); - - keep_old_icons = (Math::is_equal_approx(prev_scale, EDSCALE) && - Math::is_equal_approx(prev_gizmo_handle_scale, gizmo_handle_scale) && - prev_dark_theme == dark_theme && - prev_accent_color == accent_color && - prev_icon_saturation == icon_saturation); - - const double prev_thumb_size = (double)p_theme->get_constant(SNAME("thumb_size"), EditorStringName(Editor)); - - regenerate_thumb_icons = !Math::is_equal_approx(prev_thumb_size, thumb_size); - } - -#ifndef MODULE_SVG_ENABLED - WARN_PRINT("SVG support disabled, editor icons won't be rendered."); -#endif - - if (keep_old_icons) { - for (int i = 0; i < editor_icons_count; i++) { - theme->set_icon(editor_icons_names[i], EditorStringName(EditorIcons), p_theme->get_icon(editor_icons_names[i], EditorStringName(EditorIcons))); - } - } else { - editor_register_and_generate_icons(theme, dark_theme, icon_saturation, thumb_size, false); - } - if (regenerate_thumb_icons) { - editor_register_and_generate_icons(theme, dark_theme, icon_saturation, thumb_size, true); - } - - // Register editor fonts. - editor_register_fonts(theme); - - // Ensure borders are visible when using an editor scale below 100%. - const int border_width = CLAMP(border_size, 0, 2) * MAX(1, EDSCALE); - const int corner_width = CLAMP(corner_radius, 0, 6); - const int default_margin_size = 4; - const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 2); - - // Styleboxes - // This is the most commonly used stylebox, variations should be made as duplicate of this - Ref<StyleBoxFlat> style_default = make_flat_stylebox(base_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size, corner_width); - style_default->set_border_width_all(border_width); - style_default->set_border_color(base_color); - - // Button and widgets - const float extra_spacing = EDITOR_GET("interface/theme/additional_spacing"); - - const Vector2 widget_default_margin = Vector2(extra_spacing + 6, extra_spacing + default_margin_size + 1) * EDSCALE; - - Ref<StyleBoxFlat> style_widget = style_default->duplicate(); - style_widget->set_content_margin_individual(widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y); - style_widget->set_bg_color(dark_color_1); - if (draw_extra_borders) { - style_widget->set_border_width_all(Math::round(EDSCALE)); - style_widget->set_border_color(extra_border_color_1); - } else { - style_widget->set_border_color(dark_color_2); - } - - Ref<StyleBoxFlat> style_widget_disabled = style_widget->duplicate(); - if (draw_extra_borders) { - style_widget_disabled->set_border_color(extra_border_color_2); - } else { - style_widget_disabled->set_border_color(disabled_color); - } - style_widget_disabled->set_bg_color(disabled_bg_color); - - Ref<StyleBoxFlat> style_widget_focus = style_widget->duplicate(); - style_widget_focus->set_draw_center(false); - style_widget_focus->set_border_width_all(Math::round(2 * MAX(1, EDSCALE))); - style_widget_focus->set_border_color(accent_color); - - Ref<StyleBoxFlat> style_widget_pressed = style_widget->duplicate(); - style_widget_pressed->set_bg_color(dark_color_1.darkened(0.125)); - - Ref<StyleBoxFlat> style_widget_hover = style_widget->duplicate(); - style_widget_hover->set_bg_color(mono_color * Color(1, 1, 1, 0.11)); - if (draw_extra_borders) { - style_widget_hover->set_border_color(extra_border_color_1); - } else { - style_widget_hover->set_border_color(mono_color * Color(1, 1, 1, 0.05)); - } - - // Style for windows, popups, etc.. - Ref<StyleBoxFlat> style_popup = style_default->duplicate(); - const int popup_margin_size = default_margin_size * EDSCALE * 3; - style_popup->set_content_margin_all(popup_margin_size); - style_popup->set_border_color(contrast_color_1); - const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1); - style_popup->set_shadow_color(shadow_color); - style_popup->set_shadow_size(4 * EDSCALE); - // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency - // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled). - style_popup->set_corner_radius_all(0); - - Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine)); - style_popup_separator->set_color(separator_color); - style_popup_separator->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); - style_popup_separator->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); - style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), border_width)); - - Ref<StyleBoxLine> style_popup_labeled_separator_left(memnew(StyleBoxLine)); - style_popup_labeled_separator_left->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); - style_popup_labeled_separator_left->set_color(separator_color); - style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), border_width)); - - Ref<StyleBoxLine> style_popup_labeled_separator_right(memnew(StyleBoxLine)); - style_popup_labeled_separator_right->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); - style_popup_labeled_separator_right->set_color(separator_color); - style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), border_width)); - - Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size); - - // TabBar - - Ref<StyleBoxFlat> style_tab_base = style_widget->duplicate(); - - style_tab_base->set_border_width_all(0); - // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel. - // This also makes the top highlight look better. - style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - - // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel. - style_tab_base->set_expand_margin(SIDE_LEFT, -border_width); - - style_tab_base->set_content_margin(SIDE_LEFT, widget_default_margin.x + 5 * EDSCALE); - style_tab_base->set_content_margin(SIDE_RIGHT, widget_default_margin.x + 5 * EDSCALE); - style_tab_base->set_content_margin(SIDE_BOTTOM, widget_default_margin.y); - style_tab_base->set_content_margin(SIDE_TOP, widget_default_margin.y); - - Ref<StyleBoxFlat> style_tab_selected = style_tab_base->duplicate(); - - style_tab_selected->set_bg_color(base_color); - // Add a highlight line at the top of the selected tab. - style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE)); - // Make the highlight line prominent, but not too prominent as to not be distracting. - Color tab_highlight = dark_color_2.lerp(accent_color, 0.75); - style_tab_selected->set_border_color(tab_highlight); - style_tab_selected->set_corner_radius_all(0); - - Ref<StyleBoxFlat> style_tab_hovered = style_tab_base->duplicate(); - - style_tab_hovered->set_bg_color(dark_color_1.lerp(base_color, 0.4)); - // Hovered tab has a subtle highlight between normal and selected states. - style_tab_hovered->set_corner_radius_all(0); - - Ref<StyleBoxFlat> style_tab_unselected = style_tab_base->duplicate(); - style_tab_unselected->set_expand_margin(SIDE_BOTTOM, 0); - style_tab_unselected->set_bg_color(dark_color_1); - // Add some spacing between unselected tabs to make them easier to distinguish from each other - style_tab_unselected->set_border_color(Color(0, 0, 0, 0)); - - Ref<StyleBoxFlat> style_tab_disabled = style_tab_base->duplicate(); - style_tab_disabled->set_expand_margin(SIDE_BOTTOM, 0); - style_tab_disabled->set_bg_color(disabled_bg_color); - style_tab_disabled->set_border_color(disabled_bg_color); - - Ref<StyleBoxFlat> style_tab_focus = style_widget_focus->duplicate(); - - // Editor background - Color background_color_opaque = background_color; - background_color_opaque.a = 1.0; - theme->set_color("background", EditorStringName(Editor), background_color_opaque); - theme->set_stylebox("Background", EditorStringName(EditorStyles), make_flat_stylebox(background_color_opaque, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); - - // Focus - theme->set_stylebox("Focus", EditorStringName(EditorStyles), style_widget_focus); - // Use a less opaque color to be less distracting for the 2D and 3D editor viewports. - Ref<StyleBoxFlat> style_widget_focus_viewport = style_widget_focus->duplicate(); - style_widget_focus_viewport->set_border_color(accent_color * Color(1, 1, 1, 0.5)); - theme->set_stylebox("FocusViewport", EditorStringName(EditorStyles), style_widget_focus_viewport); - - // Menu - Ref<StyleBoxFlat> style_menu = style_widget->duplicate(); - style_menu->set_draw_center(false); - style_menu->set_border_width_all(0); - theme->set_stylebox("panel", "PanelContainer", style_menu); - theme->set_stylebox("MenuPanel", EditorStringName(EditorStyles), style_menu); - - // CanvasItem Editor - Ref<StyleBoxFlat> style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2)); - style_canvas_editor_info->set_expand_margin_all(4 * EDSCALE); - theme->set_stylebox("CanvasItemInfoOverlay", EditorStringName(EditorStyles), style_canvas_editor_info); - - // 2D and 3D contextual toolbar. - // Use a custom stylebox to make contextual menu items stand out from the rest. - // This helps with editor usability as contextual menu items change when selecting nodes, - // even though it may not be immediately obvious at first. - Ref<StyleBoxFlat> toolbar_stylebox = memnew(StyleBoxFlat); - toolbar_stylebox->set_bg_color(accent_color * Color(1, 1, 1, 0.1)); - toolbar_stylebox->set_anti_aliased(false); - // Add an underline to the StyleBox, but prevent its minimum vertical size from changing. - toolbar_stylebox->set_border_color(accent_color); - toolbar_stylebox->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); - toolbar_stylebox->set_content_margin(SIDE_BOTTOM, 0); - toolbar_stylebox->set_expand_margin_individual(4 * EDSCALE, 2 * EDSCALE, 4 * EDSCALE, 4 * EDSCALE); - theme->set_stylebox("ContextualToolbar", EditorStringName(EditorStyles), toolbar_stylebox); - - // Script Editor - theme->set_stylebox("ScriptEditorPanel", EditorStringName(EditorStyles), make_empty_stylebox(default_margin_size, 0, default_margin_size, default_margin_size)); - theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); - - theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); - - // Launch Pad and Play buttons - Ref<StyleBoxFlat> style_launch_pad = make_flat_stylebox(dark_color_1, 2 * EDSCALE, 0, 2 * EDSCALE, 0, corner_width); - style_launch_pad->set_corner_radius_all(corner_radius * EDSCALE); - theme->set_stylebox("LaunchPadNormal", EditorStringName(EditorStyles), style_launch_pad); - Ref<StyleBoxFlat> style_launch_pad_movie = style_launch_pad->duplicate(); - style_launch_pad_movie->set_bg_color(accent_color * Color(1, 1, 1, 0.1)); - style_launch_pad_movie->set_border_color(accent_color); - style_launch_pad_movie->set_border_width_all(Math::round(2 * EDSCALE)); - theme->set_stylebox("LaunchPadMovieMode", EditorStringName(EditorStyles), style_launch_pad_movie); - - theme->set_stylebox("MovieWriterButtonNormal", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); - Ref<StyleBoxFlat> style_write_movie_button = style_widget_pressed->duplicate(); - style_write_movie_button->set_bg_color(accent_color); - style_write_movie_button->set_corner_radius_all(corner_radius * EDSCALE); - style_write_movie_button->set_content_margin(SIDE_TOP, 0); - style_write_movie_button->set_content_margin(SIDE_BOTTOM, 0); - style_write_movie_button->set_content_margin(SIDE_LEFT, 0); - style_write_movie_button->set_content_margin(SIDE_RIGHT, 0); - style_write_movie_button->set_expand_margin(SIDE_RIGHT, 2 * EDSCALE); - theme->set_stylebox("MovieWriterButtonPressed", EditorStringName(EditorStyles), style_write_movie_button); - - // MenuButton - theme->set_stylebox("normal", "MenuButton", style_menu); - theme->set_stylebox("hover", "MenuButton", style_widget_hover); - theme->set_stylebox("pressed", "MenuButton", style_menu); - theme->set_stylebox("focus", "MenuButton", style_menu); - theme->set_stylebox("disabled", "MenuButton", style_menu); - - theme->set_color("font_color", "MenuButton", font_color); - theme->set_color("font_hover_color", "MenuButton", font_hover_color); - theme->set_color("font_hover_pressed_color", "MenuButton", font_hover_pressed_color); - theme->set_color("font_focus_color", "MenuButton", font_focus_color); - theme->set_color("font_outline_color", "MenuButton", font_outline_color); - - theme->set_constant("outline_size", "MenuButton", 0); - - theme->set_stylebox("MenuHover", EditorStringName(EditorStyles), style_widget_hover); - - // Buttons - theme->set_stylebox("normal", "Button", style_widget); - theme->set_stylebox("hover", "Button", style_widget_hover); - theme->set_stylebox("pressed", "Button", style_widget_pressed); - theme->set_stylebox("focus", "Button", style_widget_focus); - theme->set_stylebox("disabled", "Button", style_widget_disabled); - - theme->set_color("font_color", "Button", font_color); - theme->set_color("font_hover_color", "Button", font_hover_color); - theme->set_color("font_hover_pressed_color", "Button", font_hover_pressed_color); - theme->set_color("font_focus_color", "Button", font_focus_color); - theme->set_color("font_pressed_color", "Button", accent_color); - theme->set_color("font_disabled_color", "Button", font_disabled_color); - theme->set_color("font_outline_color", "Button", font_outline_color); - - theme->set_color("icon_normal_color", "Button", icon_normal_color); - theme->set_color("icon_hover_color", "Button", icon_hover_color); - theme->set_color("icon_focus_color", "Button", icon_focus_color); - theme->set_color("icon_pressed_color", "Button", icon_pressed_color); - theme->set_color("icon_disabled_color", "Button", icon_disabled_color); - - theme->set_constant("h_separation", "Button", 4 * EDSCALE); - theme->set_constant("outline_size", "Button", 0); - - // Flat button variations. - - Ref<StyleBoxEmpty> style_flat_button = make_empty_stylebox(); - for (int i = 0; i < 4; i++) { - style_flat_button->set_content_margin((Side)i, style_widget->get_margin((Side)i) + style_widget->get_border_width((Side)i)); - } - - Ref<StyleBoxFlat> style_flat_button_pressed = style_widget_pressed->duplicate(); - Color flat_pressed_color = dark_color_1.lightened(0.24).lerp(accent_color, 0.2) * Color(0.8, 0.8, 0.8, 0.85); - if (dark_theme) { - flat_pressed_color = dark_color_1.lerp(accent_color, 0.12) * Color(0.6, 0.6, 0.6, 0.85); - } - style_flat_button_pressed->set_bg_color(flat_pressed_color); - - theme->set_stylebox("normal", "FlatButton", style_flat_button); - theme->set_stylebox("hover", "FlatButton", style_flat_button); - theme->set_stylebox("pressed", "FlatButton", style_flat_button_pressed); - theme->set_stylebox("disabled", "FlatButton", style_flat_button); - - theme->set_stylebox("normal", "FlatMenuButton", style_flat_button); - theme->set_stylebox("hover", "FlatMenuButton", style_flat_button); - theme->set_stylebox("pressed", "FlatMenuButton", style_flat_button_pressed); - theme->set_stylebox("disabled", "FlatMenuButton", style_flat_button); - - const float ACTION_BUTTON_EXTRA_MARGIN = 32 * EDSCALE; - - theme->set_type_variation("InspectorActionButton", "Button"); - Color color_inspector_action = dark_color_1.lerp(mono_color, 0.12); - color_inspector_action.a = 0.5; - Ref<StyleBoxFlat> style_inspector_action = style_widget->duplicate(); - style_inspector_action->set_bg_color(color_inspector_action); - style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN); - theme->set_stylebox("normal", "InspectorActionButton", style_inspector_action); - style_inspector_action = style_widget_hover->duplicate(); - style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN); - theme->set_stylebox("hover", "InspectorActionButton", style_inspector_action); - style_inspector_action = style_widget_pressed->duplicate(); - style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN); - theme->set_stylebox("pressed", "InspectorActionButton", style_inspector_action); - style_inspector_action = style_widget_disabled->duplicate(); - style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN); - theme->set_stylebox("disabled", "InspectorActionButton", style_inspector_action); - theme->set_constant("h_separation", "InspectorActionButton", ACTION_BUTTON_EXTRA_MARGIN); - - // Variation for Editor Log filter buttons - theme->set_type_variation("EditorLogFilterButton", "Button"); - // When pressed, don't tint the icons with the accent color, just leave them normal. - theme->set_color("icon_pressed_color", "EditorLogFilterButton", icon_normal_color); - // When unpressed, dim the icons. - theme->set_color("icon_normal_color", "EditorLogFilterButton", icon_disabled_color); - // When pressed, add a small bottom border to the buttons to better show their active state, - // similar to active tabs. - - Ref<StyleBoxFlat> editor_log_button_pressed = style_flat_button_pressed->duplicate(); - editor_log_button_pressed->set_border_width(SIDE_BOTTOM, 2 * EDSCALE); - editor_log_button_pressed->set_border_color(accent_color); - theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed); - - // Buttons in material previews - const Color dim_light_color = icon_normal_color.darkened(0.24); - const Color dim_light_highlighted_color = icon_normal_color.darkened(0.18); - Ref<StyleBox> sb_empty_borderless = make_empty_stylebox(); - - theme->set_type_variation("PreviewLightButton", "Button"); - // When pressed, don't use the accent color tint. When unpressed, dim the icon. - theme->set_color("icon_normal_color", "PreviewLightButton", dim_light_color); - theme->set_color("icon_focus_color", "PreviewLightButton", dim_light_color); - theme->set_color("icon_pressed_color", "PreviewLightButton", icon_normal_color); - theme->set_color("icon_hover_pressed_color", "PreviewLightButton", icon_normal_color); - // Unpressed icon is dim, so use a dim highlight. - theme->set_color("icon_hover_color", "PreviewLightButton", dim_light_highlighted_color); - - theme->set_stylebox("normal", "PreviewLightButton", sb_empty_borderless); - theme->set_stylebox("hover", "PreviewLightButton", sb_empty_borderless); - theme->set_stylebox("focus", "PreviewLightButton", sb_empty_borderless); - theme->set_stylebox("pressed", "PreviewLightButton", sb_empty_borderless); - - // ProjectTag - { - theme->set_type_variation("ProjectTag", "Button"); - - Ref<StyleBoxFlat> tag = style_widget->duplicate(); - tag->set_bg_color(dark_theme ? tag->get_bg_color().lightened(0.2) : tag->get_bg_color().darkened(0.2)); - tag->set_corner_radius(CORNER_TOP_LEFT, 0); - tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - tag->set_corner_radius(CORNER_TOP_RIGHT, 4); - tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); - theme->set_stylebox("normal", "ProjectTag", tag); - - tag = style_widget_hover->duplicate(); - tag->set_corner_radius(CORNER_TOP_LEFT, 0); - tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - tag->set_corner_radius(CORNER_TOP_RIGHT, 4); - tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); - theme->set_stylebox("hover", "ProjectTag", tag); - - tag = style_widget_pressed->duplicate(); - tag->set_corner_radius(CORNER_TOP_LEFT, 0); - tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - tag->set_corner_radius(CORNER_TOP_RIGHT, 4); - tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); - theme->set_stylebox("pressed", "ProjectTag", tag); - } - - // MenuBar - theme->set_stylebox("normal", "MenuBar", style_widget); - theme->set_stylebox("hover", "MenuBar", style_widget_hover); - theme->set_stylebox("pressed", "MenuBar", style_widget_pressed); - theme->set_stylebox("disabled", "MenuBar", style_widget_disabled); - - theme->set_color("font_color", "MenuBar", font_color); - theme->set_color("font_hover_color", "MenuBar", font_hover_color); - theme->set_color("font_hover_pressed_color", "MenuBar", font_hover_pressed_color); - theme->set_color("font_focus_color", "MenuBar", font_focus_color); - theme->set_color("font_pressed_color", "MenuBar", accent_color); - theme->set_color("font_disabled_color", "MenuBar", font_disabled_color); - theme->set_color("font_outline_color", "MenuBar", font_outline_color); - - theme->set_color("icon_normal_color", "MenuBar", icon_normal_color); - theme->set_color("icon_hover_color", "MenuBar", icon_hover_color); - theme->set_color("icon_focus_color", "MenuBar", icon_focus_color); - theme->set_color("icon_pressed_color", "MenuBar", icon_pressed_color); - theme->set_color("icon_disabled_color", "MenuBar", icon_disabled_color); - - theme->set_constant("h_separation", "MenuBar", 4 * EDSCALE); - theme->set_constant("outline_size", "MenuBar", 0); - - // OptionButton - Ref<StyleBoxFlat> style_option_button_focus = style_widget_focus->duplicate(); - Ref<StyleBoxFlat> style_option_button_normal = style_widget->duplicate(); - Ref<StyleBoxFlat> style_option_button_hover = style_widget_hover->duplicate(); - Ref<StyleBoxFlat> style_option_button_pressed = style_widget_pressed->duplicate(); - Ref<StyleBoxFlat> style_option_button_disabled = style_widget_disabled->duplicate(); - - style_option_button_focus->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - style_option_button_normal->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - style_option_button_hover->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - style_option_button_pressed->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - style_option_button_disabled->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - - theme->set_stylebox("focus", "OptionButton", style_option_button_focus); - theme->set_stylebox("normal", "OptionButton", style_widget); - theme->set_stylebox("hover", "OptionButton", style_widget_hover); - theme->set_stylebox("pressed", "OptionButton", style_widget_pressed); - theme->set_stylebox("disabled", "OptionButton", style_widget_disabled); - - theme->set_stylebox("normal_mirrored", "OptionButton", style_option_button_normal); - theme->set_stylebox("hover_mirrored", "OptionButton", style_option_button_hover); - theme->set_stylebox("pressed_mirrored", "OptionButton", style_option_button_pressed); - theme->set_stylebox("disabled_mirrored", "OptionButton", style_option_button_disabled); - - theme->set_color("font_color", "OptionButton", font_color); - theme->set_color("font_hover_color", "OptionButton", font_hover_color); - theme->set_color("font_hover_pressed_color", "OptionButton", font_hover_pressed_color); - theme->set_color("font_focus_color", "OptionButton", font_focus_color); - theme->set_color("font_pressed_color", "OptionButton", accent_color); - theme->set_color("font_disabled_color", "OptionButton", font_disabled_color); - theme->set_color("font_outline_color", "OptionButton", font_outline_color); - - theme->set_color("icon_normal_color", "OptionButton", icon_normal_color); - theme->set_color("icon_hover_color", "OptionButton", icon_hover_color); - theme->set_color("icon_focus_color", "OptionButton", icon_focus_color); - theme->set_color("icon_pressed_color", "OptionButton", icon_pressed_color); - theme->set_color("icon_disabled_color", "OptionButton", icon_disabled_color); - - theme->set_icon("arrow", "OptionButton", theme->get_icon(SNAME("GuiOptionArrow"), EditorStringName(EditorIcons))); - theme->set_constant("arrow_margin", "OptionButton", widget_default_margin.x - 2 * EDSCALE); - theme->set_constant("modulate_arrow", "OptionButton", true); - theme->set_constant("h_separation", "OptionButton", 4 * EDSCALE); - theme->set_constant("outline_size", "OptionButton", 0); - - // CheckButton - theme->set_stylebox("normal", "CheckButton", style_menu); - theme->set_stylebox("pressed", "CheckButton", style_menu); - theme->set_stylebox("disabled", "CheckButton", style_menu); - theme->set_stylebox("hover", "CheckButton", style_menu); - theme->set_stylebox("hover_pressed", "CheckButton", style_menu); - - theme->set_icon("checked", "CheckButton", theme->get_icon(SNAME("GuiToggleOn"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked", "CheckButton", theme->get_icon(SNAME("GuiToggleOff"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabled"), EditorStringName(EditorIcons))); - - theme->set_icon("checked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnMirrored"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffMirrored"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), EditorStringName(EditorIcons))); - - theme->set_color("font_color", "CheckButton", font_color); - theme->set_color("font_hover_color", "CheckButton", font_hover_color); - theme->set_color("font_hover_pressed_color", "CheckButton", font_hover_pressed_color); - theme->set_color("font_focus_color", "CheckButton", font_focus_color); - theme->set_color("font_pressed_color", "CheckButton", accent_color); - theme->set_color("font_disabled_color", "CheckButton", font_disabled_color); - theme->set_color("font_outline_color", "CheckButton", font_outline_color); - - theme->set_color("icon_normal_color", "CheckButton", icon_normal_color); - theme->set_color("icon_hover_color", "CheckButton", icon_hover_color); - theme->set_color("icon_focus_color", "CheckButton", icon_focus_color); - theme->set_color("icon_pressed_color", "CheckButton", icon_pressed_color); - theme->set_color("icon_disabled_color", "CheckButton", icon_disabled_color); - - theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE); - theme->set_constant("check_v_offset", "CheckButton", 0); - theme->set_constant("outline_size", "CheckButton", 0); - - // Checkbox - Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate(); - sb_checkbox->set_content_margin_all(default_margin_size * EDSCALE); - - theme->set_stylebox("normal", "CheckBox", sb_checkbox); - theme->set_stylebox("pressed", "CheckBox", sb_checkbox); - theme->set_stylebox("disabled", "CheckBox", sb_checkbox); - theme->set_stylebox("hover", "CheckBox", sb_checkbox); - theme->set_stylebox("hover_pressed", "CheckBox", sb_checkbox); - theme->set_icon("checked", "CheckBox", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked", "CheckBox", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("radio_checked", "CheckBox", theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons))); - theme->set_icon("radio_unchecked", "CheckBox", theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled", "CheckBox", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled", "CheckBox", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("radio_checked_disabled", "CheckBox", theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("radio_unchecked_disabled", "CheckBox", theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons))); - - theme->set_color("font_color", "CheckBox", font_color); - theme->set_color("font_hover_color", "CheckBox", font_hover_color); - theme->set_color("font_hover_pressed_color", "CheckBox", font_hover_pressed_color); - theme->set_color("font_focus_color", "CheckBox", font_focus_color); - theme->set_color("font_pressed_color", "CheckBox", accent_color); - theme->set_color("font_disabled_color", "CheckBox", font_disabled_color); - theme->set_color("font_outline_color", "CheckBox", font_outline_color); - - theme->set_color("icon_normal_color", "CheckBox", icon_normal_color); - theme->set_color("icon_hover_color", "CheckBox", icon_hover_color); - theme->set_color("icon_focus_color", "CheckBox", icon_focus_color); - theme->set_color("icon_pressed_color", "CheckBox", icon_pressed_color); - theme->set_color("icon_disabled_color", "CheckBox", icon_disabled_color); - - theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE); - theme->set_constant("check_v_offset", "CheckBox", 0); - theme->set_constant("outline_size", "CheckBox", 0); - - // PopupDialog - theme->set_stylebox("panel", "PopupDialog", style_popup); - - // PopupMenu - Ref<StyleBoxFlat> style_popup_menu = style_popup->duplicate(); - // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn - // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted, - // and it looks weird. 1px solves this. - style_popup_menu->set_content_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE); - // Always display a border for PopupMenus so they can be distinguished from their background. - style_popup_menu->set_border_width_all(EDSCALE); - if (draw_extra_borders) { - style_popup_menu->set_border_color(extra_border_color_2); - } else { - style_popup_menu->set_border_color(dark_color_2); - } - theme->set_stylebox("panel", "PopupMenu", style_popup_menu); - - Ref<StyleBoxFlat> style_menu_hover = style_widget_hover->duplicate(); - // Don't use rounded corners for hover highlights since the StyleBox touches the PopupMenu's edges. - style_menu_hover->set_corner_radius_all(0); - theme->set_stylebox("hover", "PopupMenu", style_menu_hover); - - theme->set_stylebox("separator", "PopupMenu", style_popup_separator); - theme->set_stylebox("labeled_separator_left", "PopupMenu", style_popup_labeled_separator_left); - theme->set_stylebox("labeled_separator_right", "PopupMenu", style_popup_labeled_separator_right); - - theme->set_color("font_color", "PopupMenu", font_color); - theme->set_color("font_hover_color", "PopupMenu", font_hover_color); - theme->set_color("font_accelerator_color", "PopupMenu", font_disabled_color); - theme->set_color("font_disabled_color", "PopupMenu", font_disabled_color); - theme->set_color("font_separator_color", "PopupMenu", font_disabled_color); - theme->set_color("font_outline_color", "PopupMenu", font_outline_color); - theme->set_icon("checked", "PopupMenu", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked", "PopupMenu", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("radio_checked", "PopupMenu", theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons))); - theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("radio_checked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("radio_unchecked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("submenu", "PopupMenu", theme->get_icon(SNAME("ArrowRight"), EditorStringName(EditorIcons))); - theme->set_icon("submenu_mirrored", "PopupMenu", theme->get_icon(SNAME("ArrowLeft"), EditorStringName(EditorIcons))); - theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityHidden"), EditorStringName(EditorIcons))); - theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons))); - theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityXray"), EditorStringName(EditorIcons))); - - // Force the v_separation to be even so that the spacing on top and bottom is even. - // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided. - // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example). - const int vsep_base = extra_spacing + default_margin_size + 6; - const int force_even_vsep = vsep_base + (vsep_base % 2); - theme->set_constant("v_separation", "PopupMenu", force_even_vsep * EDSCALE); - theme->set_constant("outline_size", "PopupMenu", 0); - theme->set_constant("item_start_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE); - theme->set_constant("item_end_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE); - - // Sub-inspectors - for (int i = 0; i < 16; i++) { - Color si_base_color = accent_color; - - float hue_rotate = (i * 2 % 16) / 16.0; - si_base_color.set_hsv(Math::fmod(float(si_base_color.get_h() + hue_rotate), float(1.0)), si_base_color.get_s(), si_base_color.get_v()); - si_base_color = accent_color.lerp(si_base_color, float(EDITOR_GET("docks/property_editor/subresource_hue_tint"))); - - // Sub-inspector background. - Ref<StyleBoxFlat> sub_inspector_bg = style_default->duplicate(); - sub_inspector_bg->set_bg_color(dark_color_1.lerp(si_base_color, 0.08)); - sub_inspector_bg->set_border_width_all(2 * EDSCALE); - sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8)); - sub_inspector_bg->set_content_margin_all(4 * EDSCALE); - sub_inspector_bg->set_corner_radius(CORNER_TOP_LEFT, 0); - sub_inspector_bg->set_corner_radius(CORNER_TOP_RIGHT, 0); - - theme->set_stylebox("sub_inspector_bg" + itos(i), EditorStringName(Editor), sub_inspector_bg); - - // EditorProperty background while it has a sub-inspector open. - Ref<StyleBoxFlat> bg_color = make_flat_stylebox(si_base_color * Color(0.7, 0.7, 0.7, 0.8), 0, 0, 0, 0, corner_radius); - bg_color->set_anti_aliased(false); - bg_color->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - bg_color->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - - theme->set_stylebox("sub_inspector_property_bg" + itos(i), EditorStringName(Editor), bg_color); - } - - theme->set_color("sub_inspector_property_color", EditorStringName(Editor), dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)); - - // EditorSpinSlider. - theme->set_color("label_color", "EditorSpinSlider", font_color); - theme->set_color("read_only_label_color", "EditorSpinSlider", font_readonly_color); - - Ref<StyleBoxFlat> editor_spin_label_bg = style_default->duplicate(); - editor_spin_label_bg->set_bg_color(dark_color_3); - editor_spin_label_bg->set_border_width_all(0); - theme->set_stylebox("label_bg", "EditorSpinSlider", editor_spin_label_bg); - - // EditorProperty - Ref<StyleBoxFlat> style_property_bg = style_default->duplicate(); - style_property_bg->set_bg_color(highlight_color); - style_property_bg->set_border_width_all(0); - - Ref<StyleBoxFlat> style_property_child_bg = style_default->duplicate(); - style_property_child_bg->set_bg_color(dark_color_2); - style_property_child_bg->set_border_width_all(0); - - theme->set_constant("font_offset", "EditorProperty", 8 * EDSCALE); - theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg); - theme->set_stylebox("bg", "EditorProperty", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); - theme->set_stylebox("child_bg", "EditorProperty", style_property_child_bg); - theme->set_constant("v_separation", "EditorProperty", (extra_spacing + default_margin_size) * EDSCALE); - theme->set_color("warning_color", "EditorProperty", warning_color); - theme->set_color("property_color", "EditorProperty", property_color); - theme->set_color("readonly_color", "EditorProperty", readonly_color); - theme->set_color("readonly_warning_color", "EditorProperty", readonly_warning_color); - - Ref<StyleBoxFlat> style_property_group_note = style_default->duplicate(); - Color property_group_note_color = accent_color; - property_group_note_color.a = 0.1; - style_property_group_note->set_bg_color(property_group_note_color); - theme->set_stylebox("bg_group_note", "EditorProperty", style_property_group_note); - - // EditorInspectorSection - Color inspector_section_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.35); - theme->set_color("font_color", "EditorInspectorSection", inspector_section_color); - - Color inspector_indent_color = accent_color; - inspector_indent_color.a = 0.2; - Ref<StyleBoxFlat> inspector_indent_style = make_flat_stylebox(inspector_indent_color, 2.0 * EDSCALE, 0, 2.0 * EDSCALE, 0); - theme->set_stylebox("indent_box", "EditorInspectorSection", inspector_indent_style); - theme->set_constant("indent_size", "EditorInspectorSection", 6.0 * EDSCALE); - - theme->set_constant("inspector_margin", EditorStringName(Editor), 12 * EDSCALE); - - // Tree & ItemList background - Ref<StyleBoxFlat> style_tree_bg = style_default->duplicate(); - // Make Trees easier to distinguish from other controls by using a darker background color. - style_tree_bg->set_bg_color(dark_color_1.lerp(dark_color_2, 0.5)); - if (draw_extra_borders) { - style_tree_bg->set_border_width_all(Math::round(EDSCALE)); - style_tree_bg->set_border_color(extra_border_color_2); - } else { - style_tree_bg->set_border_color(dark_color_3); - } - - theme->set_stylebox("panel", "Tree", style_tree_bg); - theme->set_stylebox("panel", "EditorValidationPanel", style_tree_bg); - - // Tree - theme->set_icon("checked", "Tree", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled", "Tree", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("indeterminate", "Tree", theme->get_icon(SNAME("GuiIndeterminate"), EditorStringName(EditorIcons))); - theme->set_icon("indeterminate_disabled", "Tree", theme->get_icon(SNAME("GuiIndeterminateDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked", "Tree", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled", "Tree", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("arrow", "Tree", theme->get_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons))); - theme->set_icon("arrow_collapsed", "Tree", theme->get_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons))); - theme->set_icon("arrow_collapsed_mirrored", "Tree", theme->get_icon(SNAME("GuiTreeArrowLeft"), EditorStringName(EditorIcons))); - theme->set_icon("updown", "Tree", theme->get_icon(SNAME("GuiTreeUpdown"), EditorStringName(EditorIcons))); - theme->set_icon("select_arrow", "Tree", theme->get_icon(SNAME("GuiDropdown"), EditorStringName(EditorIcons))); - theme->set_stylebox("focus", "Tree", style_widget_focus); - theme->set_stylebox("custom_button", "Tree", make_empty_stylebox()); - theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox()); - theme->set_stylebox("custom_button_hover", "Tree", style_widget); - theme->set_color("custom_button_font_highlight", "Tree", font_hover_color); - theme->set_color("font_color", "Tree", font_color); - theme->set_color("font_selected_color", "Tree", mono_color); - theme->set_color("font_disabled_color", "Tree", font_disabled_color); - theme->set_color("font_outline_color", "Tree", font_outline_color); - theme->set_color("title_button_color", "Tree", font_color); - theme->set_color("drop_position_color", "Tree", accent_color); - theme->set_constant("v_separation", "Tree", widget_default_margin.y - EDSCALE); - theme->set_constant("h_separation", "Tree", 6 * EDSCALE); - theme->set_constant("guide_width", "Tree", border_width); - theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE); - theme->set_constant("inner_item_margin_bottom", "Tree", (default_margin_size + extra_spacing) * EDSCALE); - theme->set_constant("inner_item_margin_left", "Tree", (default_margin_size + extra_spacing) * EDSCALE); - theme->set_constant("inner_item_margin_right", "Tree", (default_margin_size + extra_spacing) * EDSCALE); - theme->set_constant("inner_item_margin_top", "Tree", (default_margin_size + extra_spacing) * EDSCALE); - theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE); - theme->set_constant("scroll_border", "Tree", 40 * EDSCALE); - theme->set_constant("scroll_speed", "Tree", 12); - theme->set_constant("outline_size", "Tree", 0); - theme->set_constant("scrollbar_margin_left", "Tree", 0); - theme->set_constant("scrollbar_margin_top", "Tree", 0); - theme->set_constant("scrollbar_margin_right", "Tree", 0); - theme->set_constant("scrollbar_margin_bottom", "Tree", 0); - theme->set_constant("scrollbar_h_separation", "Tree", 1 * EDSCALE); - theme->set_constant("scrollbar_v_separation", "Tree", 1 * EDSCALE); - - const Color guide_color = mono_color * Color(1, 1, 1, 0.05); - Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity); - - theme->set_constant("draw_guides", "Tree", relationship_line_opacity < 0.01); - theme->set_color("guide_color", "Tree", guide_color); - - int relationship_line_width = 1; - Color parent_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.45, 0.0, 1.0)); - Color children_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.25, 0.0, 1.0)); - theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01); - theme->set_constant("relationship_line_width", "Tree", relationship_line_width); - theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2); - theme->set_constant("children_hl_line_width", "Tree", relationship_line_width); - theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3); - theme->set_color("relationship_line_color", "Tree", relationship_line_color); - theme->set_color("parent_hl_line_color", "Tree", parent_line_color); - theme->set_color("children_hl_line_color", "Tree", children_line_color); - - Ref<StyleBoxFlat> style_tree_btn = style_default->duplicate(); - style_tree_btn->set_bg_color(highlight_color); - style_tree_btn->set_border_width_all(0); - theme->set_stylebox("button_pressed", "Tree", style_tree_btn); - - Ref<StyleBoxFlat> style_tree_hover = style_default->duplicate(); - style_tree_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.4)); - style_tree_hover->set_border_width_all(0); - theme->set_stylebox("hover", "Tree", style_tree_hover); - - Ref<StyleBoxFlat> style_tree_focus = style_default->duplicate(); - style_tree_focus->set_bg_color(highlight_color); - style_tree_focus->set_border_width_all(0); - theme->set_stylebox("selected_focus", "Tree", style_tree_focus); - - Ref<StyleBoxFlat> style_tree_selected = style_tree_focus->duplicate(); - theme->set_stylebox("selected", "Tree", style_tree_selected); - - Ref<StyleBoxFlat> style_tree_cursor = style_default->duplicate(); - style_tree_cursor->set_draw_center(false); - style_tree_cursor->set_border_width_all(MAX(1, border_width)); - style_tree_cursor->set_border_color(contrast_color_1); - - Ref<StyleBoxFlat> style_tree_title = style_default->duplicate(); - style_tree_title->set_bg_color(dark_color_3); - style_tree_title->set_border_width_all(0); - theme->set_stylebox("cursor", "Tree", style_tree_cursor); - theme->set_stylebox("cursor_unfocused", "Tree", style_tree_cursor); - theme->set_stylebox("title_button_normal", "Tree", style_tree_title); - theme->set_stylebox("title_button_hover", "Tree", style_tree_title); - theme->set_stylebox("title_button_pressed", "Tree", style_tree_title); - - Color prop_category_color = dark_color_1.lerp(mono_color, 0.12); - Color prop_section_color = dark_color_1.lerp(mono_color, 0.09); - Color prop_subsection_color = dark_color_1.lerp(mono_color, 0.06); - theme->set_color("prop_category", EditorStringName(Editor), prop_category_color); - theme->set_color("prop_section", EditorStringName(Editor), prop_section_color); - theme->set_color("prop_subsection", EditorStringName(Editor), prop_subsection_color); - theme->set_color("drop_position_color", "Tree", accent_color); - - // EditorInspectorCategory - Ref<StyleBoxFlat> category_bg = style_default->duplicate(); - category_bg->set_bg_color(prop_category_color); - category_bg->set_border_color(prop_category_color); - theme->set_stylebox("bg", "EditorInspectorCategory", category_bg); - - // ItemList - Ref<StyleBoxFlat> style_itemlist_bg = style_default->duplicate(); - style_itemlist_bg->set_bg_color(dark_color_1); - - if (draw_extra_borders) { - style_itemlist_bg->set_border_width_all(Math::round(EDSCALE)); - style_itemlist_bg->set_border_color(extra_border_color_2); - } else { - style_itemlist_bg->set_border_width_all(border_width); - style_itemlist_bg->set_border_color(dark_color_3); - } - - Ref<StyleBoxFlat> style_itemlist_cursor = style_default->duplicate(); - style_itemlist_cursor->set_draw_center(false); - style_itemlist_cursor->set_border_width_all(border_width); - style_itemlist_cursor->set_border_color(highlight_color); - - Ref<StyleBoxFlat> style_itemlist_hover = style_tree_selected->duplicate(); - style_itemlist_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.3)); - style_itemlist_hover->set_border_width_all(0); - - theme->set_stylebox("panel", "ItemList", style_itemlist_bg); - theme->set_stylebox("focus", "ItemList", style_widget_focus); - theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor); - theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor); - theme->set_stylebox("selected_focus", "ItemList", style_tree_focus); - theme->set_stylebox("selected", "ItemList", style_tree_selected); - theme->set_stylebox("hovered", "ItemList", style_itemlist_hover); - theme->set_color("font_color", "ItemList", font_color); - theme->set_color("font_hovered_color", "ItemList", mono_color); - theme->set_color("font_selected_color", "ItemList", mono_color); - theme->set_color("font_outline_color", "ItemList", font_outline_color); - theme->set_color("guide_color", "ItemList", guide_color); - theme->set_constant("v_separation", "ItemList", force_even_vsep * 0.5 * EDSCALE); - theme->set_constant("h_separation", "ItemList", 6 * EDSCALE); - theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE); - theme->set_constant("line_separation", "ItemList", 3 * EDSCALE); - theme->set_constant("outline_size", "ItemList", 0); - - // TabBar & TabContainer - Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(dark_color_1, 0, 0, 0, 0, corner_radius * EDSCALE); - style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background); - - theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected); - theme->set_stylebox("tab_hovered", "TabContainer", style_tab_hovered); - theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected); - theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled); - theme->set_stylebox("tab_focus", "TabContainer", style_tab_focus); - theme->set_stylebox("tab_selected", "TabBar", style_tab_selected); - theme->set_stylebox("tab_hovered", "TabBar", style_tab_hovered); - theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected); - theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled); - theme->set_stylebox("tab_focus", "TabBar", style_tab_focus); - theme->set_stylebox("button_pressed", "TabBar", style_menu); - theme->set_stylebox("button_highlight", "TabBar", style_menu); - theme->set_color("font_selected_color", "TabContainer", font_color); - theme->set_color("font_hovered_color", "TabContainer", font_color); - theme->set_color("font_unselected_color", "TabContainer", font_disabled_color); - theme->set_color("font_outline_color", "TabContainer", font_outline_color); - theme->set_color("font_selected_color", "TabBar", font_color); - theme->set_color("font_hovered_color", "TabBar", font_color); - theme->set_color("font_unselected_color", "TabBar", font_disabled_color); - theme->set_color("font_outline_color", "TabBar", font_outline_color); - theme->set_color("drop_mark_color", "TabContainer", tab_highlight); - theme->set_color("drop_mark_color", "TabBar", tab_highlight); - theme->set_icon("menu", "TabContainer", theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons))); - theme->set_icon("menu_highlight", "TabContainer", theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons))); - theme->set_icon("close", "TabBar", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); - theme->set_icon("increment", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons))); - theme->set_icon("decrement", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons))); - theme->set_icon("increment", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons))); - theme->set_icon("decrement", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons))); - theme->set_icon("increment_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons))); - theme->set_icon("decrement_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons))); - theme->set_icon("increment_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons))); - theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons))); - theme->set_icon("drop_mark", "TabContainer", theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons))); - theme->set_icon("drop_mark", "TabBar", theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons))); - theme->set_constant("side_margin", "TabContainer", 0); - theme->set_constant("outline_size", "TabContainer", 0); - theme->set_constant("h_separation", "TabBar", 4 * EDSCALE); - theme->set_constant("outline_size", "TabBar", 0); - - // Content of each tab. - Ref<StyleBoxFlat> style_content_panel = style_default->duplicate(); - style_content_panel->set_border_color(dark_color_3); - style_content_panel->set_border_width_all(border_width); - style_content_panel->set_border_width(Side::SIDE_TOP, 0); - style_content_panel->set_corner_radius(CORNER_TOP_LEFT, 0); - style_content_panel->set_corner_radius(CORNER_TOP_RIGHT, 0); - // Compensate for the border. - style_content_panel->set_content_margin_individual(margin_size_extra * EDSCALE, (2 + margin_size_extra) * EDSCALE, margin_size_extra * EDSCALE, margin_size_extra * EDSCALE); - theme->set_stylebox("panel", "TabContainer", style_content_panel); - - // Bottom panel. - Ref<StyleBoxFlat> style_bottom_panel = style_content_panel->duplicate(); - style_bottom_panel->set_corner_radius_all(corner_radius * EDSCALE); - theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel); - - // TabContainerOdd can be used on tabs against the base color background (e.g. nested tabs). - theme->set_type_variation("TabContainerOdd", "TabContainer"); - - Ref<StyleBoxFlat> style_tab_selected_odd = style_tab_selected->duplicate(); - style_tab_selected_odd->set_bg_color(disabled_bg_color); - theme->set_stylebox("tab_selected", "TabContainerOdd", style_tab_selected_odd); - - Ref<StyleBoxFlat> style_content_panel_odd = style_content_panel->duplicate(); - style_content_panel_odd->set_bg_color(disabled_bg_color); - theme->set_stylebox("panel", "TabContainerOdd", style_content_panel_odd); - - // This stylebox is used in 3d and 2d viewports (no borders). - Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate(); - style_content_panel_vp->set_content_margin_individual(border_width * 2, default_margin_size * EDSCALE, border_width * 2, border_width * 2); - theme->set_stylebox("Content", EditorStringName(EditorStyles), style_content_panel_vp); - - // This stylebox is used by preview tabs in the Theme Editor. - Ref<StyleBoxFlat> style_theme_preview_tab = style_tab_selected_odd->duplicate(); - style_theme_preview_tab->set_expand_margin(SIDE_BOTTOM, 5 * EDSCALE); - theme->set_stylebox("ThemeEditorPreviewFG", EditorStringName(EditorStyles), style_theme_preview_tab); - Ref<StyleBoxFlat> style_theme_preview_bg_tab = style_tab_unselected->duplicate(); - style_theme_preview_bg_tab->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE); - theme->set_stylebox("ThemeEditorPreviewBG", EditorStringName(EditorStyles), style_theme_preview_bg_tab); - - Ref<StyleBoxFlat> style_texture_region_bg = style_tree_bg->duplicate(); - style_texture_region_bg->set_content_margin_all(0); - theme->set_stylebox("TextureRegionPreviewBG", EditorStringName(EditorStyles), style_texture_region_bg); - theme->set_stylebox("TextureRegionPreviewFG", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); - - // Separators - theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width))); - theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width), 0, 0, true)); - - // Debugger - - Ref<StyleBoxFlat> style_panel_debugger = style_content_panel->duplicate(); - style_panel_debugger->set_border_width(SIDE_BOTTOM, 0); - theme->set_stylebox("DebuggerPanel", EditorStringName(EditorStyles), style_panel_debugger); - - Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate(); - int stylebox_offset = theme->get_font(SNAME("tab_selected"), SNAME("TabContainer"))->get_height(theme->get_font_size(SNAME("tab_selected"), SNAME("TabContainer"))) + theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->get_minimum_size().height + theme->get_stylebox(SNAME("panel"), SNAME("TabContainer"))->get_content_margin(SIDE_TOP); - style_panel_invisible_top->set_expand_margin(SIDE_TOP, -stylebox_offset); - style_panel_invisible_top->set_content_margin(SIDE_TOP, 0); - theme->set_stylebox("BottomPanelDebuggerOverride", EditorStringName(EditorStyles), style_panel_invisible_top); - - // LineEdit - - Ref<StyleBoxFlat> style_line_edit = style_widget->duplicate(); - // The original style_widget style has an extra 1 pixel offset that makes LineEdits not align with Buttons, - // so this compensates for that. - style_line_edit->set_content_margin(SIDE_TOP, style_line_edit->get_content_margin(SIDE_TOP) - 1 * EDSCALE); - - // Don't round the bottom corners to make the line look sharper. - style_line_edit->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - style_line_edit->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - - if (draw_extra_borders) { - style_line_edit->set_border_width_all(Math::round(EDSCALE)); - style_line_edit->set_border_color(extra_border_color_1); - } else { - // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors - // such as the Project Settings. - style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); - style_line_edit->set_border_color(dark_color_2); - } - - Ref<StyleBoxFlat> style_line_edit_disabled = style_line_edit->duplicate(); - style_line_edit_disabled->set_border_color(disabled_color); - style_line_edit_disabled->set_bg_color(disabled_bg_color); - - theme->set_stylebox("normal", "LineEdit", style_line_edit); - theme->set_stylebox("focus", "LineEdit", style_widget_focus); - theme->set_stylebox("read_only", "LineEdit", style_line_edit_disabled); - theme->set_icon("clear", "LineEdit", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); - theme->set_color("font_color", "LineEdit", font_color); - theme->set_color("font_selected_color", "LineEdit", mono_color); - theme->set_color("font_uneditable_color", "LineEdit", font_readonly_color); - theme->set_color("font_placeholder_color", "LineEdit", font_placeholder_color); - theme->set_color("font_outline_color", "LineEdit", font_outline_color); - theme->set_color("caret_color", "LineEdit", font_color); - theme->set_color("selection_color", "LineEdit", selection_color); - theme->set_color("clear_button_color", "LineEdit", font_color); - theme->set_color("clear_button_color_pressed", "LineEdit", accent_color); - - theme->set_constant("minimum_character_width", "LineEdit", 4); - theme->set_constant("outline_size", "LineEdit", 0); - theme->set_constant("caret_width", "LineEdit", 1); - - // TextEdit - theme->set_stylebox("normal", "TextEdit", style_line_edit); - theme->set_stylebox("focus", "TextEdit", style_widget_focus); - theme->set_stylebox("read_only", "TextEdit", style_line_edit_disabled); - theme->set_icon("tab", "TextEdit", theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons))); - theme->set_icon("space", "TextEdit", theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons))); - theme->set_color("font_color", "TextEdit", font_color); - theme->set_color("font_readonly_color", "TextEdit", font_readonly_color); - theme->set_color("font_placeholder_color", "TextEdit", font_placeholder_color); - theme->set_color("font_outline_color", "TextEdit", font_outline_color); - theme->set_color("caret_color", "TextEdit", font_color); - theme->set_color("selection_color", "TextEdit", selection_color); - theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); - - theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE); - theme->set_constant("outline_size", "TextEdit", 0); - theme->set_constant("caret_width", "TextEdit", 1); - - theme->set_icon("h_grabber", "SplitContainer", theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons))); - theme->set_icon("v_grabber", "SplitContainer", theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons))); - theme->set_icon("grabber", "VSplitContainer", theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons))); - theme->set_icon("grabber", "HSplitContainer", theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons))); - - theme->set_constant("separation", "SplitContainer", default_margin_size * 2 * EDSCALE); - theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE); - theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE); - - theme->set_constant("minimum_grab_thickness", "SplitContainer", 6 * EDSCALE); - theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * EDSCALE); - theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * EDSCALE); - - // Containers - theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE); - theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE); - theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE); - theme->set_constant("margin_left", "MarginContainer", 0); - theme->set_constant("margin_top", "MarginContainer", 0); - theme->set_constant("margin_right", "MarginContainer", 0); - theme->set_constant("margin_bottom", "MarginContainer", 0); - theme->set_constant("h_separation", "GridContainer", default_margin_size * EDSCALE); - theme->set_constant("v_separation", "GridContainer", default_margin_size * EDSCALE); - theme->set_constant("h_separation", "FlowContainer", default_margin_size * EDSCALE); - theme->set_constant("v_separation", "FlowContainer", default_margin_size * EDSCALE); - theme->set_constant("h_separation", "HFlowContainer", default_margin_size * EDSCALE); - theme->set_constant("v_separation", "HFlowContainer", default_margin_size * EDSCALE); - theme->set_constant("h_separation", "VFlowContainer", default_margin_size * EDSCALE); - theme->set_constant("v_separation", "VFlowContainer", default_margin_size * EDSCALE); - - // Custom theme type for MarginContainer with 4px margins. - theme->set_type_variation("MarginContainer4px", "MarginContainer"); - theme->set_constant("margin_left", "MarginContainer4px", 4 * EDSCALE); - theme->set_constant("margin_top", "MarginContainer4px", 4 * EDSCALE); - theme->set_constant("margin_right", "MarginContainer4px", 4 * EDSCALE); - theme->set_constant("margin_bottom", "MarginContainer4px", 4 * EDSCALE); - - // Window - - // Prevent corner artifacts between window title and body. - Ref<StyleBoxFlat> style_window_title = style_default->duplicate(); - style_window_title->set_corner_radius(CORNER_TOP_LEFT, 0); - style_window_title->set_corner_radius(CORNER_TOP_RIGHT, 0); - // Prevent visible line between window title and body. - style_window_title->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE); - - Ref<StyleBoxFlat> style_window = style_popup->duplicate(); - style_window->set_border_color(base_color); - style_window->set_border_width(SIDE_TOP, 24 * EDSCALE); - style_window->set_expand_margin(SIDE_TOP, 24 * EDSCALE); - theme->set_stylebox("embedded_border", "Window", style_window); - theme->set_stylebox("embedded_unfocused_border", "Window", style_window); - - theme->set_color("title_color", "Window", font_color); - theme->set_icon("close", "Window", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); - theme->set_icon("close_pressed", "Window", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); - theme->set_constant("close_h_offset", "Window", 22 * EDSCALE); - theme->set_constant("close_v_offset", "Window", 20 * EDSCALE); - theme->set_constant("title_height", "Window", 24 * EDSCALE); - theme->set_constant("resize_margin", "Window", 4 * EDSCALE); - theme->set_font("title_font", "Window", theme->get_font(SNAME("title"), EditorStringName(EditorFonts))); - theme->set_font_size("title_font_size", "Window", theme->get_font_size(SNAME("title_size"), EditorStringName(EditorFonts))); - - // Complex window (currently only Editor Settings and Project Settings) - Ref<StyleBoxFlat> style_complex_window = style_window->duplicate(); - style_complex_window->set_bg_color(dark_color_2); - style_complex_window->set_border_color(dark_color_2); - theme->set_stylebox("panel", "EditorSettingsDialog", style_complex_window); - theme->set_stylebox("panel", "ProjectSettingsEditor", style_complex_window); - theme->set_stylebox("panel", "EditorAbout", style_complex_window); - - // AcceptDialog - theme->set_stylebox("panel", "AcceptDialog", style_window_title); - theme->set_constant("buttons_separation", "AcceptDialog", 8 * EDSCALE); - - // HScrollBar - Ref<Texture2D> empty_icon = memnew(ImageTexture); - - if (increase_scrollbar_touch_area) { - theme->set_stylebox("scroll", "HScrollBar", make_line_stylebox(separator_color, 50)); - } else { - theme->set_stylebox("scroll", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, -5, 1, -5, 1)); - } - theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); - theme->set_stylebox("grabber", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); - theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); - theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); - - theme->set_icon("increment", "HScrollBar", empty_icon); - theme->set_icon("increment_highlight", "HScrollBar", empty_icon); - theme->set_icon("increment_pressed", "HScrollBar", empty_icon); - theme->set_icon("decrement", "HScrollBar", empty_icon); - theme->set_icon("decrement_highlight", "HScrollBar", empty_icon); - theme->set_icon("decrement_pressed", "HScrollBar", empty_icon); - - // VScrollBar - if (increase_scrollbar_touch_area) { - theme->set_stylebox("scroll", "VScrollBar", make_line_stylebox(separator_color, 50, 1, 1, true)); - } else { - theme->set_stylebox("scroll", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, -5, 1, -5)); - } - theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); - theme->set_stylebox("grabber", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); - theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); - theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); - - theme->set_icon("increment", "VScrollBar", empty_icon); - theme->set_icon("increment_highlight", "VScrollBar", empty_icon); - theme->set_icon("increment_pressed", "VScrollBar", empty_icon); - theme->set_icon("decrement", "VScrollBar", empty_icon); - theme->set_icon("decrement_highlight", "VScrollBar", empty_icon); - theme->set_icon("decrement_pressed", "VScrollBar", empty_icon); - - // HSlider - theme->set_icon("grabber_highlight", "HSlider", theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons))); - theme->set_icon("grabber", "HSlider", theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons))); - theme->set_stylebox("slider", "HSlider", make_flat_stylebox(dark_color_3, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width)); - theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width)); - theme->set_stylebox("grabber_area_highlight", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2)); - theme->set_constant("center_grabber", "HSlider", 0); - theme->set_constant("grabber_offset", "HSlider", 0); - - // VSlider - theme->set_icon("grabber", "VSlider", theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons))); - theme->set_icon("grabber_highlight", "VSlider", theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons))); - theme->set_stylebox("slider", "VSlider", make_flat_stylebox(dark_color_3, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width)); - theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width)); - theme->set_stylebox("grabber_area_highlight", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0)); - theme->set_constant("center_grabber", "VSlider", 0); - theme->set_constant("grabber_offset", "VSlider", 0); - - // RichTextLabel - theme->set_color("default_color", "RichTextLabel", font_color); - theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0)); - theme->set_color("font_outline_color", "RichTextLabel", font_outline_color); - theme->set_color("selection_color", "RichTextLabel", selection_color); - theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE); - theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE); - theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE); - theme->set_constant("outline_size", "RichTextLabel", 0); - theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox()); - theme->set_stylebox("normal", "RichTextLabel", style_tree_bg); - - // Editor help. - Ref<StyleBoxFlat> style_editor_help = style_default->duplicate(); - style_editor_help->set_bg_color(dark_color_2); - style_editor_help->set_border_color(dark_color_3); - theme->set_stylebox("background", "EditorHelp", style_editor_help); - - theme->set_color("title_color", "EditorHelp", accent_color); - theme->set_color("headline_color", "EditorHelp", mono_color); - theme->set_color("text_color", "EditorHelp", font_color); - theme->set_color("comment_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); - theme->set_color("symbol_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); - theme->set_color("value_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); - theme->set_color("qualifier_color", "EditorHelp", font_color * Color(1, 1, 1, 0.8)); - theme->set_color("type_color", "EditorHelp", accent_color.lerp(font_color, 0.5)); - theme->set_color("selection_color", "EditorHelp", selection_color); - theme->set_color("link_color", "EditorHelp", accent_color.lerp(mono_color, 0.8)); - theme->set_color("code_color", "EditorHelp", accent_color.lerp(mono_color, 0.6)); - theme->set_color("kbd_color", "EditorHelp", accent_color.lerp(property_color, 0.6)); - theme->set_color("code_bg_color", "EditorHelp", dark_color_3); - theme->set_color("kbd_bg_color", "EditorHelp", dark_color_1); - theme->set_color("param_bg_color", "EditorHelp", dark_color_1); - theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE)); - theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE); - theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE); - theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE); - theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE); - - // Panel - theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width)); - theme->set_stylebox("PanelForeground", EditorStringName(EditorStyles), style_default); - - // Label - theme->set_stylebox("normal", "Label", style_empty); - theme->set_color("font_color", "Label", font_color); - theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0)); - theme->set_color("font_outline_color", "Label", font_outline_color); - theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE); - theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE); - theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE); - theme->set_constant("line_spacing", "Label", 3 * EDSCALE); - theme->set_constant("outline_size", "Label", 0); - - // LinkButton - theme->set_stylebox("focus", "LinkButton", style_empty); - theme->set_color("font_color", "LinkButton", font_color); - theme->set_color("font_hover_color", "LinkButton", font_hover_color); - theme->set_color("font_hover_pressed_color", "LinkButton", font_hover_pressed_color); - theme->set_color("font_focus_color", "LinkButton", font_focus_color); - theme->set_color("font_pressed_color", "LinkButton", accent_color); - theme->set_color("font_disabled_color", "LinkButton", font_disabled_color); - theme->set_color("font_outline_color", "LinkButton", font_outline_color); - - theme->set_constant("outline_size", "LinkButton", 0); - - theme->set_type_variation("HeaderSmallLink", "LinkButton"); - theme->set_font("font", "HeaderSmallLink", theme->get_font(SNAME("font"), SNAME("HeaderSmall"))); - theme->set_font_size("font_size", "HeaderSmallLink", theme->get_font_size(SNAME("font_size"), SNAME("HeaderSmall"))); - - // TooltipPanel + TooltipLabel - // TooltipPanel is also used for custom tooltips, while TooltipLabel - // is only relevant for default tooltips. - Ref<StyleBoxFlat> style_tooltip = style_popup->duplicate(); - style_tooltip->set_shadow_size(0); - style_tooltip->set_content_margin_all(default_margin_size * EDSCALE * 0.5); - style_tooltip->set_bg_color(dark_color_3 * Color(0.8, 0.8, 0.8, 0.9)); - style_tooltip->set_border_width_all(0); - theme->set_color("font_color", "TooltipLabel", font_hover_color); - theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0)); - theme->set_stylebox("panel", "TooltipPanel", style_tooltip); - - // PopupPanel - theme->set_stylebox("panel", "PopupPanel", style_popup); - - Ref<StyleBoxFlat> control_editor_popup_style = style_popup->duplicate(); - control_editor_popup_style->set_shadow_size(0); - control_editor_popup_style->set_content_margin(SIDE_LEFT, default_margin_size * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_TOP, default_margin_size * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_RIGHT, default_margin_size * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_BOTTOM, default_margin_size * EDSCALE); - control_editor_popup_style->set_border_width_all(0); - - theme->set_stylebox("panel", "ControlEditorPopupPanel", control_editor_popup_style); - theme->set_type_variation("ControlEditorPopupPanel", "PopupPanel"); - - // SpinBox - theme->set_icon("updown", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdown"), EditorStringName(EditorIcons))); - theme->set_icon("updown_disabled", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdownDisabled"), EditorStringName(EditorIcons))); - - // ProgressBar - theme->set_stylebox("background", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressBar"), EditorStringName(EditorIcons)), 4, 4, 4, 4, 0, 0, 0, 0)); - theme->set_stylebox("fill", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressFill"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 2, 1, 2, 1)); - theme->set_color("font_color", "ProgressBar", font_color); - theme->set_color("font_outline_color", "ProgressBar", font_outline_color); - theme->set_constant("outline_size", "ProgressBar", 0); - - // GraphEdit - theme->set_stylebox("panel", "GraphEdit", style_tree_bg); - Ref<StyleBoxFlat> graph_toolbar_style = make_flat_stylebox(dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3); - theme->set_stylebox("menu_panel", "GraphEdit", graph_toolbar_style); - - if (dark_theme) { - theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1)); - theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05)); - } else { - theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15)); - theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07)); - } - theme->set_color("selection_fill", "GraphEdit", theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor))); - theme->set_color("selection_stroke", "GraphEdit", theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor))); - theme->set_color("activity", "GraphEdit", accent_color); - - theme->set_icon("zoom_out", "GraphEdit", theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons))); - theme->set_icon("zoom_in", "GraphEdit", theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons))); - theme->set_icon("zoom_reset", "GraphEdit", theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons))); - theme->set_icon("grid_toggle", "GraphEdit", theme->get_icon(SNAME("GridToggle"), EditorStringName(EditorIcons))); - theme->set_icon("minimap_toggle", "GraphEdit", theme->get_icon(SNAME("GridMinimap"), EditorStringName(EditorIcons))); - theme->set_icon("snapping_toggle", "GraphEdit", theme->get_icon(SNAME("SnapGrid"), EditorStringName(EditorIcons))); - theme->set_icon("layout", "GraphEdit", theme->get_icon(SNAME("GridLayout"), EditorStringName(EditorIcons))); - - // GraphEditMinimap - Ref<StyleBoxFlat> style_minimap_bg = make_flat_stylebox(dark_color_1, 0, 0, 0, 0); - style_minimap_bg->set_border_color(dark_color_3); - style_minimap_bg->set_border_width_all(1); - theme->set_stylebox("panel", "GraphEditMinimap", style_minimap_bg); - - Ref<StyleBoxFlat> style_minimap_camera; - Ref<StyleBoxFlat> style_minimap_node; - if (dark_theme) { - style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0); - style_minimap_camera->set_border_color(Color(0.65, 0.65, 0.65, 0.45)); - style_minimap_node = make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0); - } else { - style_minimap_camera = make_flat_stylebox(Color(0.38, 0.38, 0.38, 0.2), 0, 0, 0, 0); - style_minimap_camera->set_border_color(Color(0.38, 0.38, 0.38, 0.45)); - style_minimap_node = make_flat_stylebox(Color(0, 0, 0), 0, 0, 0, 0); - } - style_minimap_camera->set_border_width_all(1); - style_minimap_node->set_anti_aliased(false); - theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera); - theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node); - - Color minimap_resizer_color; - if (dark_theme) { - minimap_resizer_color = Color(1, 1, 1, 0.65); - } else { - minimap_resizer_color = Color(0, 0, 0, 0.65); - } - theme->set_icon("resizer", "GraphEditMinimap", theme->get_icon(SNAME("GuiResizerTopLeft"), EditorStringName(EditorIcons))); - theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color); - - // GraphNode - - const int gn_margin_top = 2; - const int gn_margin_side = 2; - const int gn_margin_bottom = 2; - - Color graphnode_bg = dark_color_3; - if (!dark_theme) { - graphnode_bg = prop_section_color; - } - const Color graph_node_selected_border_color = graphnode_bg.lerp(accent_color, 0.275); - - const Color graphnode_frame_bg = graphnode_bg.lerp(style_tree_bg->get_bg_color(), 0.3); - - Ref<StyleBoxFlat> graphn_sb_panel = make_flat_stylebox(graphnode_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, corner_width); - graphn_sb_panel->set_border_width_all(border_width); - graphn_sb_panel->set_border_color(graphnode_bg); - graphn_sb_panel->set_corner_radius_individual(0, 0, corner_radius * EDSCALE, corner_radius * EDSCALE); - graphn_sb_panel->set_expand_margin(SIDE_TOP, 17 * EDSCALE); - - Ref<StyleBoxFlat> graphn_sb_panel_selected = make_flat_stylebox(graphnode_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, corner_width); - graphn_sb_panel_selected->set_border_width_all(2 * EDSCALE + border_width); - graphn_sb_panel_selected->set_border_color(graph_node_selected_border_color); - graphn_sb_panel_selected->set_corner_radius_individual(0, 0, corner_radius * EDSCALE, corner_radius * EDSCALE); - graphn_sb_panel_selected->set_expand_margin(SIDE_TOP, 17 * EDSCALE); - - const int gn_titlebar_margin_left = 12; - const int gn_titlebar_margin_right = 4; // The rest is for the close button. - Ref<StyleBoxFlat> graphn_sb_titlebar = make_flat_stylebox(graphnode_bg, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, corner_width); - graphn_sb_titlebar->set_expand_margin(SIDE_TOP, 2 * EDSCALE); - graphn_sb_titlebar->set_corner_radius_individual(corner_radius * EDSCALE, corner_radius * EDSCALE, 0, 0); - - Ref<StyleBoxFlat> graphn_sb_titlebar_selected = make_flat_stylebox(graph_node_selected_border_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, corner_width); - graphn_sb_titlebar_selected->set_corner_radius_individual(corner_radius * EDSCALE, corner_radius * EDSCALE, 0, 0); - graphn_sb_titlebar_selected->set_expand_margin(SIDE_TOP, 2 * EDSCALE); - Ref<StyleBoxEmpty> graphn_sb_slot = make_empty_stylebox(12, 0, 12, 0); - - theme->set_stylebox("panel", "GraphElement", graphn_sb_panel); - theme->set_stylebox("panel_selected", "GraphElement", graphn_sb_panel_selected); - theme->set_stylebox("titlebar", "GraphElement", graphn_sb_titlebar); - theme->set_stylebox("titlebar_selected", "GraphElement", graphn_sb_titlebar_selected); - - // GraphNode's title Label. - theme->set_type_variation("GraphNodeTitleLabel", "Label"); - - theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0)); - theme->set_color("font_color", "GraphNodeTitleLabel", font_color); - theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE); - - Color graphnode_decoration_color = dark_color_1.inverted(); - - theme->set_color("resizer_color", "GraphElement", graphnode_decoration_color); - theme->set_icon("resizer", "GraphElement", theme->get_icon(SNAME("GuiResizer"), EditorStringName(EditorIcons))); - - // GraphNode. - theme->set_stylebox("panel", "GraphNode", graphn_sb_panel); - theme->set_stylebox("panel_selected", "GraphNode", graphn_sb_panel_selected); - theme->set_stylebox("titlebar", "GraphNode", graphn_sb_titlebar); - theme->set_stylebox("titlebar_selected", "GraphNode", graphn_sb_titlebar_selected); - theme->set_stylebox("slot", "GraphNode", graphn_sb_slot); - - theme->set_color("resizer_color", "GraphNode", graphnode_decoration_color); - - theme->set_constant("port_h_offset", "GraphNode", 0); - theme->set_constant("separation", "GraphNode", 1 * EDSCALE); - - Ref<ImageTexture> port_icon = theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons)); - // The true size is 24x24 This is necessary for sharp port icons at high zoom levels in GraphEdit (up to ~200%). - port_icon->set_size_override(Size2(12, 12)); - theme->set_icon("port", "GraphNode", port_icon); - - // StateMachine graph - theme->set_stylebox("panel", "GraphStateMachine", style_tree_bg); - theme->set_stylebox("error_panel", "GraphStateMachine", style_tree_bg); - theme->set_color("error_color", "GraphStateMachine", error_color); - - const int sm_margin_side = 10 * EDSCALE; - - Ref<StyleBoxFlat> sm_node_style = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), sm_margin_side, 24 * EDSCALE, sm_margin_side, gn_margin_bottom, corner_width); - sm_node_style->set_border_width_all(border_width); - sm_node_style->set_border_color(graphnode_bg); - - Ref<StyleBoxFlat> sm_node_selected_style = make_flat_stylebox(graphnode_bg * Color(1, 1, 1, 0.9), sm_margin_side, 24 * EDSCALE, sm_margin_side, gn_margin_bottom, corner_width); - sm_node_selected_style->set_border_width_all(2 * EDSCALE + border_width); - sm_node_selected_style->set_border_color(accent_color * Color(1, 1, 1, 0.9)); - sm_node_selected_style->set_shadow_size(8 * EDSCALE); - sm_node_selected_style->set_shadow_color(shadow_color); - - Ref<StyleBoxFlat> sm_node_playing_style = sm_node_selected_style->duplicate(); - sm_node_playing_style->set_border_color(warning_color); - sm_node_playing_style->set_shadow_color(warning_color * Color(1, 1, 1, 0.2)); - - theme->set_stylebox("node_frame", "GraphStateMachine", sm_node_style); - theme->set_stylebox("node_frame_selected", "GraphStateMachine", sm_node_selected_style); - theme->set_stylebox("node_frame_playing", "GraphStateMachine", sm_node_playing_style); - - Ref<StyleBoxFlat> sm_node_start_style = sm_node_style->duplicate(); - sm_node_start_style->set_border_width_all(1 * EDSCALE); - sm_node_start_style->set_border_color(success_color.lightened(0.24)); - theme->set_stylebox("node_frame_start", "GraphStateMachine", sm_node_start_style); - - Ref<StyleBoxFlat> sm_node_end_style = sm_node_style->duplicate(); - sm_node_end_style->set_border_width_all(1 * EDSCALE); - sm_node_end_style->set_border_color(error_color); - theme->set_stylebox("node_frame_end", "GraphStateMachine", sm_node_end_style); - - theme->set_font("node_title_font", "GraphStateMachine", theme->get_font(SNAME("font"), SNAME("Label"))); - theme->set_font_size("node_title_font_size", "GraphStateMachine", theme->get_font_size(SNAME("font_size"), SNAME("Label"))); - theme->set_color("node_title_font_color", "GraphStateMachine", font_color); - - theme->set_color("transition_color", "GraphStateMachine", font_color); - theme->set_color("transition_disabled_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.2)); - theme->set_color("transition_icon_color", "GraphStateMachine", Color(1, 1, 1)); - theme->set_color("transition_icon_disabled_color", "GraphStateMachine", Color(1, 1, 1, 0.2)); - theme->set_color("highlight_color", "GraphStateMachine", accent_color); - theme->set_color("highlight_disabled_color", "GraphStateMachine", accent_color * Color(1, 1, 1, 0.6)); - theme->set_color("guideline_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.3)); - - theme->set_color("playback_color", "GraphStateMachine", font_color); - theme->set_color("playback_background_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.3)); - - // GridContainer - theme->set_constant("v_separation", "GridContainer", Math::round(widget_default_margin.y - 2 * EDSCALE)); - - // FileDialog - theme->set_icon("folder", "FileDialog", theme->get_icon(SNAME("Folder"), EditorStringName(EditorIcons))); - theme->set_icon("parent_folder", "FileDialog", theme->get_icon(SNAME("ArrowUp"), EditorStringName(EditorIcons))); - theme->set_icon("back_folder", "FileDialog", theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons))); - theme->set_icon("forward_folder", "FileDialog", theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons))); - theme->set_icon("reload", "FileDialog", theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); - theme->set_icon("toggle_hidden", "FileDialog", theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons))); - // Use a different color for folder icons to make them easier to distinguish from files. - // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color. - theme->set_color("folder_icon_color", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(accent_color, 0.7)); - theme->set_color("files_disabled", "FileDialog", font_disabled_color); - - // ColorPicker - theme->set_constant("margin", "ColorPicker", default_margin_size); - theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE); - theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE); - theme->set_constant("h_width", "ColorPicker", 30 * EDSCALE); - theme->set_constant("label_width", "ColorPicker", 10 * EDSCALE); - theme->set_constant("center_slider_grabbers", "ColorPicker", 1); - theme->set_icon("screen_picker", "ColorPicker", theme->get_icon(SNAME("ColorPick"), EditorStringName(EditorIcons))); - theme->set_icon("shape_circle", "ColorPicker", theme->get_icon(SNAME("PickerShapeCircle"), EditorStringName(EditorIcons))); - theme->set_icon("shape_rect", "ColorPicker", theme->get_icon(SNAME("PickerShapeRectangle"), EditorStringName(EditorIcons))); - theme->set_icon("shape_rect_wheel", "ColorPicker", theme->get_icon(SNAME("PickerShapeRectangleWheel"), EditorStringName(EditorIcons))); - theme->set_icon("add_preset", "ColorPicker", theme->get_icon(SNAME("Add"), EditorStringName(EditorIcons))); - theme->set_icon("sample_bg", "ColorPicker", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); - theme->set_icon("overbright_indicator", "ColorPicker", theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons))); - theme->set_icon("bar_arrow", "ColorPicker", theme->get_icon(SNAME("ColorPickerBarArrow"), EditorStringName(EditorIcons))); - theme->set_icon("picker_cursor", "ColorPicker", theme->get_icon(SNAME("PickerCursor"), EditorStringName(EditorIcons))); - - // ColorPickerButton - theme->set_icon("bg", "ColorPickerButton", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); - - // ColorPresetButton - Ref<StyleBoxFlat> preset_sb = make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2, 2); - theme->set_stylebox("preset_fg", "ColorPresetButton", preset_sb); - theme->set_icon("preset_bg", "ColorPresetButton", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); - theme->set_icon("overbright_indicator", "ColorPresetButton", theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons))); - - // Information on 3D viewport - Ref<StyleBoxFlat> style_info_3d_viewport = style_default->duplicate(); - style_info_3d_viewport->set_bg_color(style_info_3d_viewport->get_bg_color() * Color(1, 1, 1, 0.5)); - style_info_3d_viewport->set_border_width_all(0); - theme->set_stylebox("Information3dViewport", EditorStringName(EditorStyles), style_info_3d_viewport); - - // Asset Library. - theme->set_stylebox("bg", "AssetLib", style_empty); - theme->set_stylebox("panel", "AssetLib", style_content_panel); - theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5)); - theme->set_icon("dismiss", "AssetLib", theme->get_icon(SNAME("Close"), EditorStringName(EditorIcons))); - - // Theme editor. - theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25)); - Color theme_preview_picker_bg_color = accent_color; - theme_preview_picker_bg_color.a = 0.2; - Ref<StyleBoxFlat> theme_preview_picker_sb = make_flat_stylebox(theme_preview_picker_bg_color, 0, 0, 0, 0); - theme_preview_picker_sb->set_border_color(accent_color); - theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE); - theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb); - Color theme_preview_picker_label_bg_color = accent_color; - theme_preview_picker_label_bg_color.set_v(0.5); - Ref<StyleBoxFlat> theme_preview_picker_label_sb = make_flat_stylebox(theme_preview_picker_label_bg_color, 4.0, 1.0, 4.0, 3.0); - theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb); - - // Dictionary editor add item. - // Expand to the left and right by 4px to compensate for the dictionary editor margins. - Ref<StyleBoxFlat> style_dictionary_add_item = make_flat_stylebox(prop_subsection_color, 0, 4, 0, 4, corner_radius); - style_dictionary_add_item->set_expand_margin(SIDE_LEFT, 4 * EDSCALE); - style_dictionary_add_item->set_expand_margin(SIDE_RIGHT, 4 * EDSCALE); - theme->set_stylebox("DictionaryAddItem", EditorStringName(EditorStyles), style_dictionary_add_item); - - Ref<StyleBoxEmpty> vshader_label_style = make_empty_stylebox(2, 1, 2, 1); - theme->set_stylebox("label_style", "VShaderEditor", vshader_label_style); - - // Project manager. - theme->set_stylebox("search_panel", "ProjectManager", style_tree_bg); - theme->set_constant("sidebar_button_icon_separation", "ProjectManager", int(6 * EDSCALE)); - - // adaptive script theme constants - // for comments and elements with lower relevance - const Color dim_color = Color(font_color, 0.5); - - const float mono_value = mono_color.r; - const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07); - const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14); - const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27); - - const Color symbol_color = dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61); - const Color keyword_color = dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51); - const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8); - const Color base_type_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2); - const Color engine_type_color = dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4); - const Color user_type_color = dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4); - const Color comment_color = dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5); - const Color doc_comment_color = dark_theme ? Color(0.6, 0.7, 0.8, 0.8) : Color(0.15, 0.15, 0.4, 0.7); - const Color string_color = dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0); - - // Use the brightest background color on a light theme (which generally uses a negative contrast rate). - const Color te_background_color = dark_theme ? background_color : dark_color_3; - const Color completion_background_color = dark_theme ? base_color : background_color; - const Color completion_selected_color = alpha1; - const Color completion_existing_color = alpha2; - // Same opacity as the scroll grabber editor icon. - const Color completion_scroll_color = Color(mono_value, mono_value, mono_value, 0.29); - const Color completion_scroll_hovered_color = Color(mono_value, mono_value, mono_value, 0.4); - const Color completion_font_color = font_color; - const Color text_color = font_color; - const Color line_number_color = dim_color; - const Color safe_line_number_color = dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75); - const Color caret_color = mono_color; - const Color caret_background_color = mono_color.inverted(); - const Color text_selected_color = Color(0, 0, 0, 0); - const Color brace_mismatch_color = dark_theme ? error_color : Color(1, 0.08, 0, 1); - const Color current_line_color = alpha1; - const Color line_length_guideline_color = dark_theme ? base_color : background_color; - const Color word_highlighted_color = alpha1; - const Color number_color = dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1); - const Color function_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1); - const Color member_variable_color = dark_theme ? Color(0.34, 0.7, 1.0).lerp(mono_color, 0.6) : Color(0, 0.4, 0.68, 1); - const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3); - const Color bookmark_color = Color(0.08, 0.49, 0.98); - const Color breakpoint_color = dark_theme ? error_color : Color(1, 0.27, 0.2, 1); - const Color executing_line_color = Color(0.98, 0.89, 0.27); - const Color code_folding_color = alpha3; - const Color folded_code_region_color = Color(0.68, 0.46, 0.77, 0.2); - const Color search_result_color = alpha1; - const Color search_result_border_color = dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38); - - EditorSettings *setting = EditorSettings::get_singleton(); - String text_editor_color_theme = setting->get("text_editor/theme/color_theme"); - if (text_editor_color_theme == "Default") { - setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true); - setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true); - setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true); - setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true); - setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true); - setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true); - setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true); - setting->set_initial_value("text_editor/theme/highlighting/doc_comment_color", doc_comment_color, true); - setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true); - setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_hovered_color", completion_scroll_hovered_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true); - setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true); - setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true); - setting->set_initial_value("text_editor/theme/highlighting/safe_line_number_color", safe_line_number_color, true); - setting->set_initial_value("text_editor/theme/highlighting/caret_color", caret_color, true); - setting->set_initial_value("text_editor/theme/highlighting/caret_background_color", caret_background_color, true); - setting->set_initial_value("text_editor/theme/highlighting/text_selected_color", text_selected_color, true); - setting->set_initial_value("text_editor/theme/highlighting/selection_color", selection_color, true); - setting->set_initial_value("text_editor/theme/highlighting/brace_mismatch_color", brace_mismatch_color, true); - setting->set_initial_value("text_editor/theme/highlighting/current_line_color", current_line_color, true); - setting->set_initial_value("text_editor/theme/highlighting/line_length_guideline_color", line_length_guideline_color, true); - setting->set_initial_value("text_editor/theme/highlighting/word_highlighted_color", word_highlighted_color, true); - setting->set_initial_value("text_editor/theme/highlighting/number_color", number_color, true); - setting->set_initial_value("text_editor/theme/highlighting/function_color", function_color, true); - setting->set_initial_value("text_editor/theme/highlighting/member_variable_color", member_variable_color, true); - setting->set_initial_value("text_editor/theme/highlighting/mark_color", mark_color, true); - setting->set_initial_value("text_editor/theme/highlighting/bookmark_color", bookmark_color, true); - setting->set_initial_value("text_editor/theme/highlighting/breakpoint_color", breakpoint_color, true); - setting->set_initial_value("text_editor/theme/highlighting/executing_line_color", executing_line_color, true); - setting->set_initial_value("text_editor/theme/highlighting/code_folding_color", code_folding_color, true); - setting->set_initial_value("text_editor/theme/highlighting/folded_code_region_color", folded_code_region_color, true); - setting->set_initial_value("text_editor/theme/highlighting/search_result_color", search_result_color, true); - setting->set_initial_value("text_editor/theme/highlighting/search_result_border_color", search_result_border_color, true); - } else if (text_editor_color_theme == "Godot 2") { - setting->load_text_editor_theme(); - } - - // Now theme is loaded, apply it to CodeEdit. - theme->set_font("font", "CodeEdit", theme->get_font(SNAME("source"), EditorStringName(EditorFonts))); - theme->set_font_size("font_size", "CodeEdit", theme->get_font_size(SNAME("source_size"), EditorStringName(EditorFonts))); - - Ref<StyleBoxFlat> code_edit_stylebox = make_flat_stylebox(EDITOR_GET("text_editor/theme/highlighting/background_color"), widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y, corner_radius); - theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox); - theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox); - theme->set_stylebox("focus", "CodeEdit", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); - - theme->set_icon("tab", "CodeEdit", theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons))); - theme->set_icon("space", "CodeEdit", theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons))); - theme->set_icon("folded", "CodeEdit", theme->get_icon(SNAME("CodeFoldedRightArrow"), EditorStringName(EditorIcons))); - theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("CodeFoldDownArrow"), EditorStringName(EditorIcons))); - theme->set_icon("folded_code_region", "CodeEdit", theme->get_icon(SNAME("CodeRegionFoldedRightArrow"), EditorStringName(EditorIcons))); - theme->set_icon("can_fold_code_region", "CodeEdit", theme->get_icon(SNAME("CodeRegionFoldDownArrow"), EditorStringName(EditorIcons))); - theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("TextEditorPlay"), EditorStringName(EditorIcons))); - theme->set_icon("breakpoint", "CodeEdit", theme->get_icon(SNAME("Breakpoint"), EditorStringName(EditorIcons))); - - theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing")); - - theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); - theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color")); - theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color")); - theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color")); - theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color")); - theme->set_color("completion_scroll_hovered_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_hovered_color")); - theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color")); - theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color")); - theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/caret_color")); - theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_selected_color")); - theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/selection_color")); - theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/brace_mismatch_color")); - theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/current_line_color")); - theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_length_guideline_color")); - theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/word_highlighted_color")); - theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/bookmark_color")); - theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/breakpoint_color")); - theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/executing_line_color")); - theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/code_folding_color")); - theme->set_color("folded_code_region_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/folded_code_region_color")); - theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_color")); - theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_border_color")); - - OS::get_singleton()->benchmark_end_measure("EditorTheme", "Create Editor Theme"); - - return theme; -} - -Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) { - Ref<Theme> theme = create_editor_theme(p_theme); - - OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Custom Theme"); - - const String custom_theme_path = EDITOR_GET("interface/theme/custom_theme"); - if (!custom_theme_path.is_empty()) { - Ref<Theme> custom_theme = ResourceLoader::load(custom_theme_path); - if (custom_theme.is_valid()) { - theme->merge_with(custom_theme); - } - } - - OS::get_singleton()->benchmark_end_measure("EditorTheme", "Create Custom Theme"); - return theme; -} - -/** - * Returns the SVG code for the default project icon. - */ -String get_default_project_icon() { - for (int i = 0; i < editor_icons_count; i++) { - if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) { - return String(editor_icons_sources[i]); - } - } - return String(); -} diff --git a/editor/event_listener_line_edit.cpp b/editor/event_listener_line_edit.cpp index e51808c78c..2c46e1c20a 100644 --- a/editor/event_listener_line_edit.cpp +++ b/editor/event_listener_line_edit.cpp @@ -175,12 +175,12 @@ void EventListenerLineEdit::_on_text_changed(const String &p_text) { } void EventListenerLineEdit::_on_focus() { - set_placeholder(TTR("Listening for input...")); + set_placeholder(TTR("Listening for Input")); } void EventListenerLineEdit::_on_unfocus() { ignore_next_event = true; - set_placeholder(TTR("Filter by event...")); + set_placeholder(TTR("Filter by Event")); } Ref<InputEvent> EventListenerLineEdit::get_event() const { @@ -227,5 +227,5 @@ void EventListenerLineEdit::_bind_methods() { EventListenerLineEdit::EventListenerLineEdit() { set_caret_blink_enabled(false); - set_placeholder(TTR("Filter by event...")); + set_placeholder(TTR("Filter by Event")); } diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index ab2ada9ae4..ee25893a30 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -40,11 +40,11 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/export/editor_export.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "editor_export_plugin.h" #include "scene/resources/image_texture.h" #include "scene/resources/packed_scene.h" @@ -456,7 +456,7 @@ void EditorExportPlatform::_edit_files_with_filter(Ref<DirAccess> &da, const Vec da->list_dir_end(); for (int i = 0; i < dirs.size(); ++i) { - String dir = dirs[i]; + const String &dir = dirs[i]; if (dir.begins_with(".")) { continue; } @@ -547,8 +547,10 @@ EditorExportPlatform::ExportNotifier::~ExportNotifier() { for (int i = 0; i < export_plugins.size(); i++) { if (GDVIRTUAL_IS_OVERRIDDEN_PTR(export_plugins[i], _export_end)) { export_plugins.write[i]->_export_end_script(); + } else { + export_plugins.write[i]->_export_end(); } - export_plugins.write[i]->_export_end(); + export_plugins.write[i]->_export_end_clear(); export_plugins.write[i]->set_export_preset(Ref<EditorExportPlugin>()); } } @@ -899,7 +901,7 @@ Vector<String> EditorExportPlatform::get_forced_export_files() { if (FileAccess::exists(abs_path)) { files.push_back(ts_data); // Remove the file later. - MessageQueue::get_singleton()->push_callable(callable_mp_static(DirAccess::remove_absolute), abs_path); + callable_mp_static(DirAccess::remove_absolute).call_deferred(abs_path); } } } @@ -1096,7 +1098,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<String> fields = l.split("::"); if (fields.size() == 4) { FileExportCache fec; - String path = fields[0]; + const String &path = fields[0]; fec.source_md5 = fields[1].strip_edges(); fec.source_modified_time = fields[2].strip_edges().to_int(); fec.saved_path = fields[3]; @@ -1364,8 +1366,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & if (path_remaps.size()) { if (true) { //new remap mode, use always as it's friendlier with multiple .pck exports for (int i = 0; i < path_remaps.size(); i += 2) { - String from = path_remaps[i]; - String to = path_remaps[i + 1]; + const String &from = path_remaps[i]; + const String &to = path_remaps[i + 1]; String remap_file = "[remap]\n\npath=\"" + to.c_escape() + "\"\n"; CharString utf8 = remap_file.utf8(); Vector<uint8_t> new_file; diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp index 6576960b9a..ec8c8c7b69 100644 --- a/editor/export/editor_export_plugin.cpp +++ b/editor/export/editor_export_plugin.cpp @@ -291,6 +291,8 @@ void EditorExportPlugin::_export_file(const String &p_path, const String &p_type void EditorExportPlugin::_export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags) { } +void EditorExportPlugin::_export_end() {} + void EditorExportPlugin::skip() { skipped = true; } diff --git a/editor/export/editor_export_plugin.h b/editor/export/editor_export_plugin.h index 7d866ce37e..fe97d2e04f 100644 --- a/editor/export/editor_export_plugin.h +++ b/editor/export/editor_export_plugin.h @@ -71,7 +71,7 @@ class EditorExportPlugin : public RefCounted { skipped = false; } - _FORCE_INLINE_ void _export_end() { + _FORCE_INLINE_ void _export_end_clear() { ios_frameworks.clear(); ios_embedded_frameworks.clear(); ios_bundle_files.clear(); @@ -108,6 +108,7 @@ protected: virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features); virtual void _export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags); + virtual void _export_end(); static void _bind_methods(); diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp index 26ed7c46fb..69ad076f8a 100644 --- a/editor/export/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -36,10 +36,10 @@ #include "core/version.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/progress_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/file_dialog.h" #include "scene/gui/menu_button.h" #include "scene/gui/separator.h" @@ -758,7 +758,7 @@ void ExportTemplateManager::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { current_value->add_theme_font_override("font", get_theme_font(SNAME("main"), EditorStringName(EditorFonts))); current_missing_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), EditorStringName(Editor))); - current_installed_label->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + current_installed_label->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); mirror_options_button->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); } break; diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index f2c5eeb2ed..63bd87e6cc 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -35,12 +35,12 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_properties.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/export/editor_export.h" #include "editor/gui/editor_file_dialog.h" #include "editor/import/resource_importer_texture_settings.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_box.h" #include "scene/gui/check_button.h" #include "scene/gui/item_list.h" @@ -824,7 +824,7 @@ void ProjectExportDialog::_setup_item_for_file_mode(TreeItem *p_item, EditorExpo p_item->set_cell_mode(1, TreeItem::CELL_MODE_STRING); p_item->set_editable(1, false); p_item->set_selectable(1, false); - p_item->set_custom_color(1, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + p_item->set_custom_color(1, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } else { p_item->set_checked(0, true); p_item->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM); @@ -1191,6 +1191,7 @@ ProjectExportDialog::ProjectExportDialog() { preset_vb->add_child(mc); mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); presets = memnew(ItemList); + presets->set_auto_translate(false); SET_DRAG_FORWARDING_GCD(presets, ProjectExportDialog); mc->add_child(presets); presets->connect("item_selected", callable_mp(this, &ProjectExportDialog::_edit_preset)); @@ -1276,6 +1277,7 @@ ProjectExportDialog::ProjectExportDialog() { server_strip_message = memnew(Label); server_strip_message->set_visible(false); server_strip_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); + server_strip_message->set_custom_minimum_size(Size2(300 * EDSCALE, 1)); resources_vb->add_child(server_strip_message); { @@ -1283,7 +1285,7 @@ ProjectExportDialog::ProjectExportDialog() { ClassDB::get_inheriters_from_class("Resource", &resource_names); PackedStringArray strippable; - for (StringName resource_name : resource_names) { + for (const StringName &resource_name : resource_names) { if (ClassDB::has_method(resource_name, "create_placeholder", true)) { strippable.push_back(resource_name); } @@ -1394,12 +1396,14 @@ ProjectExportDialog::ProjectExportDialog() { set_cancel_button_text(TTR("Close")); set_ok_button_text(TTR("Export PCK/ZIP...")); + get_ok_button()->set_tooltip_text(TTR("Export the project resources as a PCK or ZIP package. This is not a playable build, only the project data without a Godot executable.")); get_ok_button()->set_disabled(true); #ifdef ANDROID_ENABLED export_button = memnew(Button); export_button->hide(); #else export_button = add_button(TTR("Export Project..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export"); + export_button->set_tooltip_text(TTR("Export the project as a playable build (Godot executable and project data) for the selected preset.")); #endif export_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_project)); // Disable initially before we select a valid preset diff --git a/editor/fbx_importer_manager.cpp b/editor/fbx_importer_manager.cpp index 5922cbf312..7199ef3842 100644 --- a/editor/fbx_importer_manager.cpp +++ b/editor/fbx_importer_manager.cpp @@ -32,9 +32,9 @@ #include "core/config/project_settings.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/link_button.h" void FBXImporterManager::_notification(int p_what) { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 1b966fced1..0aa9a3bfee 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -42,17 +42,17 @@ #include "editor/editor_feature_profile.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_dir_dialog.h" #include "editor/gui/editor_scene_tabs.h" -#include "editor/import/scene_import_settings.h" +#include "editor/import/3d/scene_import_settings.h" #include "editor/import_dock.h" #include "editor/plugins/editor_resource_tooltip_plugins.h" #include "editor/scene_create_dialog.h" #include "editor/scene_tree_dock.h" #include "editor/shader_create_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/item_list.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" @@ -388,7 +388,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo const Color default_folder_color = get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog")); for (int i = 0; i < favorite_paths.size(); i++) { - String favorite = favorite_paths[i]; + const String &favorite = favorite_paths[i]; if (!favorite.begins_with("res://")) { continue; } @@ -470,8 +470,6 @@ void FileSystemDock::_update_display_mode(bool p_force) { case DISPLAY_MODE_HSPLIT: case DISPLAY_MODE_VSPLIT: const bool is_vertical = display_mode == DISPLAY_MODE_VSPLIT; - const int split_offset = split_box->get_split_offset(); - is_vertical ? split_box_offset_h = split_offset : split_box_offset_v = split_offset; split_box->set_vertical(is_vertical); const int actual_offset = is_vertical ? split_box_offset_v : split_box_offset_h; @@ -653,7 +651,7 @@ void FileSystemDock::_notification(int p_what) { void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_selected) { // Update the import dock. import_dock_needs_update = true; - call_deferred(SNAME("_update_import_dock")); + callable_mp(this, &FileSystemDock::_update_import_dock).call_deferred(); // Return if we don't select something new. if (!p_selected) { @@ -767,7 +765,7 @@ void FileSystemDock::navigate_to_path(const String &p_path) { } void FileSystemDock::_file_list_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, const Variant &p_udata) { - if ((file_list_vb->is_visible_in_tree() || current_path == p_path.get_base_dir()) && p_preview.is_valid()) { + if ((file_list_vb->is_visible_in_tree() || current_path.trim_suffix("/") == p_path.get_base_dir()) && p_preview.is_valid()) { Array uarr = p_udata; int idx = uarr[0]; String file = uarr[1]; @@ -867,18 +865,7 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> * struct FileSystemDock::FileInfoTypeComparator { bool operator()(const FileInfo &p_a, const FileInfo &p_b) const { - // Uses the extension, then the icon name to distinguish file types. - String icon_path_a = ""; - String icon_path_b = ""; - Ref<Texture2D> icon_a = EditorNode::get_singleton()->get_class_icon(p_a.type); - if (icon_a.is_valid()) { - icon_path_a = icon_a->get_name(); - } - Ref<Texture2D> icon_b = EditorNode::get_singleton()->get_class_icon(p_b.type); - if (icon_b.is_valid()) { - icon_path_b = icon_b->get_name(); - } - return NaturalNoCaseComparator()(p_a.name.get_extension() + icon_path_a + p_a.name.get_basename(), p_b.name.get_extension() + icon_path_b + p_b.name.get_basename()); + return NaturalNoCaseComparator()(p_a.name.get_extension() + p_a.type + p_a.name.get_basename(), p_b.name.get_extension() + p_b.type + p_b.name.get_basename()); } }; @@ -1883,10 +1870,6 @@ Vector<String> FileSystemDock::_check_existing() { return conflicting_items; } -void FileSystemDock::_move_dialog_confirm(const String &p_path) { - _move_operation_confirm(p_path, move_dialog->is_copy_pressed()); -} - void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_copy, Overwrite p_overwrite) { if (p_overwrite == OVERWRITE_UNDECIDED) { to_move_path = p_to_path; @@ -2135,6 +2118,135 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected } } break; + case FILE_OPEN_IN_TERMINAL: { + String fpath = current_path; + if (current_path == "Favorites") { + fpath = p_selected[0]; + } + + Vector<String> terminal_emulators; + const String terminal_emulator_setting = EDITOR_GET("filesystem/external_programs/terminal_emulator"); + if (terminal_emulator_setting.is_empty()) { + // Figure out a default terminal emulator to use. +#if defined(WINDOWS_ENABLED) + // Default to PowerShell as done by Windows 10 and later. + terminal_emulators.push_back("powershell"); +#elif defined(MACOS_ENABLED) + terminal_emulators.push_back("/System/Applications/Utilities/Terminal.app"); +#elif defined(LINUXBSD_ENABLED) + // Try terminal emulators that ship with common Linux distributions first. + terminal_emulators.push_back("gnome-terminal"); + terminal_emulators.push_back("konsole"); + terminal_emulators.push_back("xfce4-terminal"); + terminal_emulators.push_back("lxterminal"); + terminal_emulators.push_back("kitty"); + terminal_emulators.push_back("alacritty"); + terminal_emulators.push_back("urxvt"); + terminal_emulators.push_back("xterm"); +#endif + } else { + // Use the user-specified terminal. + terminal_emulators.push_back(terminal_emulator_setting); + } + + String arguments = EDITOR_GET("filesystem/external_programs/terminal_emulator_flags"); + if (arguments.is_empty()) { + // NOTE: This default value is ignored further below if the terminal executable is `powershell` or `cmd`, + // due to these terminals requiring nonstandard syntax to start in a specified folder. + arguments = "{directory}"; + } + +#ifdef LINUXBSD_ENABLED + String chosen_terminal_emulator; + for (const String &terminal_emulator : terminal_emulators) { + List<String> test_args; // Required for `execute()`, as it doesn't accept `Vector<String>`. + test_args.push_back("-v"); + test_args.push_back(terminal_emulator); + // Silence command name being printed when found. (stderr is already silenced by `OS::execute()` by default.) + // FIXME: This doesn't appear to silence stdout. + test_args.push_back(">"); + test_args.push_back("/dev/null"); + int exit_code = 0; + const Error err = OS::get_singleton()->execute("command", test_args, nullptr, &exit_code); + if (err == OK && exit_code == EXIT_SUCCESS) { + chosen_terminal_emulator = terminal_emulator; + break; + } else if (err == ERR_CANT_FORK) { + ERR_PRINT_ED(vformat(TTR("Couldn't run external program to check for terminal emulator presence: command -v %s"), terminal_emulator)); + } + } +#else + // On Windows and macOS, the first (and only) terminal emulator in the list is always available. + String chosen_terminal_emulator = terminal_emulators[0]; +#endif + + List<String> terminal_emulator_args; // Required for `execute()`, as it doesn't accept `Vector<String>`. +#ifdef LINUXBSD_ENABLED + // Prepend default arguments based on the terminal emulator name. + // Use `String.ends_with()` so that installations in non-default paths + // or `/usr/local/bin` are detected correctly. + if (chosen_terminal_emulator.ends_with("konsole")) { + terminal_emulator_args.push_back("--workdir"); + } +#endif + + bool append_default_args = true; + +#ifdef WINDOWS_ENABLED + // Prepend default arguments based on the terminal emulator name. + // Use `String.get_basename().to_lower()` to handle Windows' case-insensitive paths + // with optional file extensions for executables in `PATH`. + if (chosen_terminal_emulator.get_basename().to_lower() == "powershell") { + terminal_emulator_args.push_back("-noexit"); + terminal_emulator_args.push_back("-command"); + terminal_emulator_args.push_back("cd '{directory}'"); + append_default_args = false; + } else if (chosen_terminal_emulator.get_basename().to_lower() == "cmd") { + terminal_emulator_args.push_back("/K"); + terminal_emulator_args.push_back("cd /d {directory}"); + append_default_args = false; + } +#endif + + Vector<String> arguments_array = arguments.split(" "); + for (const String &argument : arguments_array) { + if (!append_default_args && argument == "{directory}") { + // Prevent appending a `{directory}` placeholder twice when using powershell or cmd. + // This allows users to enter the path to cmd or PowerShell in the custom terminal emulator path, + // and make it work without having to enter custom arguments. + continue; + } + terminal_emulator_args.push_back(argument); + } + + const bool is_directory = fpath.ends_with("/"); + for (int i = 0; i < terminal_emulator_args.size(); i++) { + if (is_directory) { + terminal_emulator_args[i] = terminal_emulator_args[i].replace("{directory}", ProjectSettings::get_singleton()->globalize_path(fpath)); + } else { + terminal_emulator_args[i] = terminal_emulator_args[i].replace("{directory}", ProjectSettings::get_singleton()->globalize_path(fpath).get_base_dir()); + } + } + + if (OS::get_singleton()->is_stdout_verbose()) { + // Print full command line to help with troubleshooting. + String command_string = chosen_terminal_emulator; + for (const String &arg : terminal_emulator_args) { + command_string += " " + arg; + } + print_line("Opening terminal emulator:", command_string); + } + + const Error err = OS::get_singleton()->create_process(chosen_terminal_emulator, terminal_emulator_args, nullptr, true); + if (err != OK) { + String args_string; + for (int i = 0; i < terminal_emulator_args.size(); i++) { + args_string += terminal_emulator_args[i]; + } + ERR_PRINT_ED(vformat(TTR("Couldn't run external terminal program (error code %d): %s %s\nCheck `filesystem/external_programs/terminal_emulator` and `filesystem/external_programs/terminal_emulator_flags` in the Editor Settings."), err, chosen_terminal_emulator, args_string)); + } + } break; + case FILE_OPEN: { // Open folders. TreeItem *selected = tree->get_root(); @@ -2172,7 +2284,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected // Instantiate all selected scenes. Vector<String> paths; for (int i = 0; i < p_selected.size(); i++) { - String fpath = p_selected[i]; + const String &fpath = p_selected[i]; if (EditorFileSystem::get_singleton()->get_file_type(fpath) == "PackedScene") { paths.push_back(fpath); } @@ -2210,7 +2322,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected case FILE_DEPENDENCIES: { // Checkout the file dependencies. if (!p_selected.is_empty()) { - String fpath = p_selected[0]; + const String &fpath = p_selected[0]; deps_editor->edit(fpath); } } break; @@ -2218,7 +2330,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected case FILE_OWNERS: { // Checkout the file owners. if (!p_selected.is_empty()) { - String fpath = p_selected[0]; + const String &fpath = p_selected[0]; owners_editor->show(fpath); } } break; @@ -2228,12 +2340,13 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected to_move.clear(); Vector<String> collapsed_paths = _remove_self_included_paths(p_selected); for (int i = collapsed_paths.size() - 1; i >= 0; i--) { - String fpath = collapsed_paths[i]; + const String &fpath = collapsed_paths[i]; if (fpath != "res://") { to_move.push_back(FileOrFolder(fpath, !fpath.ends_with("/"))); } } if (to_move.size() > 0) { + move_dialog->config(p_selected); move_dialog->popup_centered_ratio(0.4); } } break; @@ -2275,7 +2388,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected Vector<String> collapsed_paths = _remove_self_included_paths(p_selected); for (int i = 0; i < collapsed_paths.size(); i++) { - String fpath = collapsed_paths[i]; + const String &fpath = collapsed_paths[i]; if (fpath != "res://") { if (fpath.ends_with("/")) { remove_folders.push_back(fpath); @@ -2347,7 +2460,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected case FILE_COPY_PATH: { if (!p_selected.is_empty()) { - String fpath = p_selected[0]; + const String &fpath = p_selected[0]; DisplayServer::get_singleton()->clipboard_set(fpath); } } break; @@ -2459,6 +2572,14 @@ void FileSystemDock::_change_split_mode() { emit_signal(SNAME("display_mode_changed")); } +void FileSystemDock::_split_dragged(int p_offset) { + if (split_box->is_vertical()) { + split_box_offset_v = p_offset; + } else { + split_box_offset_h = p_offset; + } +} + void FileSystemDock::fix_dependencies(const String &p_for_file) { deps_editor->edit(p_for_file); } @@ -2859,7 +2980,7 @@ void FileSystemDock::_folder_color_index_pressed(int p_index, PopupMenu *p_menu) // Update project settings with new folder colors. for (int i = 0; i < selected.size(); i++) { - String fpath = selected[i]; + const String &fpath = selected[i]; if (chosen_color_name) { assigned_folder_colors[fpath] = chosen_color_name; @@ -2890,7 +3011,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str bool all_not_favorites = true; for (int i = 0; i < p_paths.size(); i++) { - String fpath = p_paths[i]; + const String &fpath = p_paths[i]; if (fpath.ends_with("/")) { foldernames.push_back(fpath); all_files = false; @@ -3048,19 +3169,23 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str } if (p_paths.size() == 1) { - const String fpath = p_paths[0]; + const String &fpath = p_paths[0]; #if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) p_popup->add_separator(); // Opening the system file manager is not supported on the Android and web editors. const bool is_directory = fpath.ends_with("/"); - const String item_text = is_directory ? TTR("Open in File Manager") : TTR("Show in File Manager"); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Filesystem")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); - p_popup->set_item_text(p_popup->get_item_index(FILE_SHOW_IN_EXPLORER), item_text); + p_popup->set_item_text(p_popup->get_item_index(FILE_SHOW_IN_EXPLORER), is_directory ? TTR("Open in File Manager") : TTR("Show in File Manager")); + if (!is_directory) { p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("ExternalLink")), ED_GET_SHORTCUT("filesystem_dock/open_in_external_program"), FILE_OPEN_EXTERNAL); } + + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_OPEN_IN_TERMINAL); + p_popup->set_item_text(p_popup->get_item_index(FILE_OPEN_IN_TERMINAL), is_directory ? TTR("Open in Terminal") : TTR("Open Containing Folder in Terminal")); #endif current_path = fpath; @@ -3105,6 +3230,7 @@ void FileSystemDock::_tree_empty_click(const Vector2 &p_pos, MouseButton p_butto // Opening the system file manager is not supported on the Android and web editors. tree_popup->add_separator(); tree_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Filesystem")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); + tree_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_OPEN_IN_TERMINAL); #endif tree_popup->set_position(tree->get_screen_position() + p_pos); @@ -3192,7 +3318,7 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) { // Update the import dock. import_dock_needs_update = true; - call_deferred(SNAME("_update_import_dock")); + callable_mp(this, &FileSystemDock::_update_import_dock).call_deferred(); } void FileSystemDock::_tree_mouse_exited() { @@ -3283,6 +3409,8 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { _tree_rmb_option(FILE_SHOW_IN_EXPLORER); } else if (ED_IS_SHORTCUT("filesystem_dock/open_in_external_program", p_event)) { _tree_rmb_option(FILE_OPEN_EXTERNAL); + } else if (ED_IS_SHORTCUT("filesystem_dock/open_in_terminal", p_event)) { + _tree_rmb_option(FILE_OPEN_IN_TERMINAL); } else if (ED_IS_SHORTCUT("editor/open_search", p_event)) { focus_on_filter(); } else { @@ -3343,6 +3471,8 @@ void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) { _file_list_rmb_option(FILE_RENAME); } else if (ED_IS_SHORTCUT("filesystem_dock/show_in_explorer", p_event)) { _file_list_rmb_option(FILE_SHOW_IN_EXPLORER); + } else if (ED_IS_SHORTCUT("filesystem_dock/open_in_terminal", p_event)) { + _file_list_rmb_option(FILE_OPEN_IN_TERMINAL); } else if (ED_IS_SHORTCUT("editor/open_search", p_event)) { focus_on_filter(); } else { @@ -3424,7 +3554,7 @@ void FileSystemDock::_update_import_dock() { Vector<String> imports; String import_type; for (int i = 0; i < efiles.size(); i++) { - String fpath = efiles[i]; + const String &fpath = efiles[i]; Ref<ConfigFile> cf; cf.instantiate(); Error err = cf->load(fpath + ".import"); @@ -3504,16 +3634,11 @@ MenuButton *FileSystemDock::_create_file_menu_button() { } void FileSystemDock::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_tree"), &FileSystemDock::_update_tree); - ClassDB::bind_method(D_METHOD("_file_list_thumbnail_done"), &FileSystemDock::_file_list_thumbnail_done); ClassDB::bind_method(D_METHOD("_tree_thumbnail_done"), &FileSystemDock::_tree_thumbnail_done); - ClassDB::bind_method(D_METHOD("_select_file"), &FileSystemDock::_select_file); ClassDB::bind_method(D_METHOD("navigate_to_path", "path"), &FileSystemDock::navigate_to_path); - ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock); - ClassDB::bind_method(D_METHOD("add_resource_tooltip_plugin", "plugin"), &FileSystemDock::add_resource_tooltip_plugin); ClassDB::bind_method(D_METHOD("remove_resource_tooltip_plugin", "plugin"), &FileSystemDock::remove_resource_tooltip_plugin); @@ -3529,6 +3654,70 @@ void FileSystemDock::_bind_methods() { ADD_SIGNAL(MethodInfo("display_mode_changed")); } +void FileSystemDock::save_layout_to_config(Ref<ConfigFile> p_layout, const String &p_section) const { + p_layout->set_value(p_section, "dock_filesystem_h_split_offset", get_h_split_offset()); + p_layout->set_value(p_section, "dock_filesystem_v_split_offset", get_v_split_offset()); + p_layout->set_value(p_section, "dock_filesystem_display_mode", get_display_mode()); + p_layout->set_value(p_section, "dock_filesystem_file_sort", get_file_sort()); + p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", get_file_list_display_mode()); + PackedStringArray selected_files = get_selected_paths(); + p_layout->set_value(p_section, "dock_filesystem_selected_paths", selected_files); + Vector<String> uncollapsed_paths = get_uncollapsed_paths(); + p_layout->set_value(p_section, "dock_filesystem_uncollapsed_paths", uncollapsed_paths); +} + +void FileSystemDock::load_layout_from_config(Ref<ConfigFile> p_layout, const String &p_section) { + if (p_layout->has_section_key(p_section, "dock_filesystem_h_split_offset")) { + int fs_h_split_ofs = p_layout->get_value(p_section, "dock_filesystem_h_split_offset"); + set_h_split_offset(fs_h_split_ofs); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_v_split_offset")) { + int fs_v_split_ofs = p_layout->get_value(p_section, "dock_filesystem_v_split_offset"); + set_v_split_offset(fs_v_split_ofs); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) { + DisplayMode dock_filesystem_display_mode = DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode"))); + set_display_mode(dock_filesystem_display_mode); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) { + FileSortOption dock_filesystem_file_sort = FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort"))); + set_file_sort(dock_filesystem_file_sort); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) { + FileListDisplayMode dock_filesystem_file_list_display_mode = FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode"))); + set_file_list_display_mode(dock_filesystem_file_list_display_mode); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_selected_paths")) { + PackedStringArray dock_filesystem_selected_paths = p_layout->get_value(p_section, "dock_filesystem_selected_paths"); + for (int i = 0; i < dock_filesystem_selected_paths.size(); i++) { + select_file(dock_filesystem_selected_paths[i]); + } + } + + // Restore collapsed state. + PackedStringArray uncollapsed_tis; + if (p_layout->has_section_key(p_section, "dock_filesystem_uncollapsed_paths")) { + uncollapsed_tis = p_layout->get_value(p_section, "dock_filesystem_uncollapsed_paths"); + } else { + uncollapsed_tis = { "res://" }; + } + + if (!uncollapsed_tis.is_empty()) { + for (int i = 0; i < uncollapsed_tis.size(); i++) { + TreeItem *uncollapsed_ti = get_tree_control()->get_item_with_metadata(uncollapsed_tis[i], 0); + if (uncollapsed_ti) { + uncollapsed_ti->set_collapsed(false); + } + } + get_tree_control()->queue_redraw(); + } +} + FileSystemDock::FileSystemDock() { singleton = this; set_name("FileSystem"); @@ -3547,6 +3736,7 @@ FileSystemDock::FileSystemDock() { // Opening the system file manager or opening in an external program is not supported on the Android and web editors. ED_SHORTCUT("filesystem_dock/show_in_explorer", TTR("Open in File Manager")); ED_SHORTCUT("filesystem_dock/open_in_external_program", TTR("Open in External Program")); + ED_SHORTCUT("filesystem_dock/open_in_terminal", TTR("Open in Terminal")); #endif // Properly translating color names would require a separate HashMap, so for simplicity they are provided as comments. @@ -3628,6 +3818,8 @@ FileSystemDock::FileSystemDock() { split_box = memnew(SplitContainer); split_box->set_v_size_flags(SIZE_EXPAND_FILL); + split_box->connect("dragged", callable_mp(this, &FileSystemDock::_split_dragged)); + split_box_offset_h = 240 * EDSCALE; add_child(split_box); tree = memnew(FileSystemTree); @@ -3708,7 +3900,8 @@ FileSystemDock::FileSystemDock() { move_dialog = memnew(EditorDirDialog); add_child(move_dialog); - move_dialog->connect("dir_selected", callable_mp(this, &FileSystemDock::_move_dialog_confirm)); + move_dialog->connect("move_pressed", callable_mp(this, &FileSystemDock::_move_operation_confirm).bind(false, OVERWRITE_UNDECIDED)); + move_dialog->connect("copy_pressed", callable_mp(this, &FileSystemDock::_move_operation_confirm).bind(true, OVERWRITE_UNDECIDED)); overwrite_dialog = memnew(ConfirmationDialog); add_child(overwrite_dialog); @@ -3745,7 +3938,7 @@ FileSystemDock::FileSystemDock() { make_dir_dialog = memnew(DirectoryCreateDialog); add_child(make_dir_dialog); - make_dir_dialog->connect("dir_created", callable_mp(this, &FileSystemDock::_rescan)); + make_dir_dialog->connect("dir_created", callable_mp(this, &FileSystemDock::_rescan).unbind(1)); make_scene_dialog = memnew(SceneCreateDialog); add_child(make_scene_dialog); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index f70afaa65e..6c69acb953 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -102,6 +102,12 @@ public: FILE_SORT_MAX, }; + enum Overwrite { + OVERWRITE_UNDECIDED, + OVERWRITE_REPLACE, + OVERWRITE_RENAME, + }; + private: enum FileMenu { FILE_OPEN, @@ -121,6 +127,7 @@ private: FILE_NEW, FILE_SHOW_IN_EXPLORER, FILE_OPEN_EXTERNAL, + FILE_OPEN_IN_TERMINAL, FILE_COPY_PATH, FILE_COPY_UID, FOLDER_EXPAND_ALL, @@ -132,12 +139,6 @@ private: FILE_NEW_SCENE, }; - enum Overwrite { - OVERWRITE_UNDECIDED, - OVERWRITE_REPLACE, - OVERWRITE_RENAME, - }; - HashMap<String, Color> folder_colors; Dictionary assigned_folder_colors; @@ -289,7 +290,6 @@ private: void _duplicate_operation_confirm(); void _overwrite_dialog_action(bool p_overwrite); Vector<String> _check_existing(); - void _move_dialog_confirm(const String &p_path); void _move_operation_confirm(const String &p_to_path, bool p_copy = false, Overwrite p_overwrite = OVERWRITE_UNDECIDED); void _tree_rmb_option(int p_option); @@ -305,6 +305,7 @@ private: void _rescan(); void _change_split_mode(); + void _split_dragged(int p_offset); void _search_changed(const String &p_text, const Control *p_from); @@ -386,18 +387,20 @@ public: void fix_dependencies(const String &p_for_file); - int get_split_offset() { return split_box->get_split_offset(); } - void set_split_offset(int p_offset) { split_box->set_split_offset(p_offset); } + int get_h_split_offset() const { return split_box_offset_h; } + void set_h_split_offset(int p_offset) { split_box_offset_h = p_offset; } + int get_v_split_offset() const { return split_box_offset_v; } + void set_v_split_offset(int p_offset) { split_box_offset_v = p_offset; } void select_file(const String &p_file); void set_display_mode(DisplayMode p_display_mode); - DisplayMode get_display_mode() { return display_mode; } + DisplayMode get_display_mode() const { return display_mode; } void set_file_sort(FileSortOption p_file_sort); - FileSortOption get_file_sort() { return file_sort; } + FileSortOption get_file_sort() const { return file_sort; } void set_file_list_display_mode(FileListDisplayMode p_mode); - FileListDisplayMode get_file_list_display_mode() { return file_list_display_mode; }; + FileListDisplayMode get_file_list_display_mode() const { return file_list_display_mode; }; Tree *get_tree_control() { return tree; } @@ -405,8 +408,13 @@ public: void remove_resource_tooltip_plugin(const Ref<EditorResourceTooltipPlugin> &p_plugin); Control *create_tooltip_for_path(const String &p_path) const; + void save_layout_to_config(Ref<ConfigFile> p_layout, const String &p_section) const; + void load_layout_from_config(Ref<ConfigFile> p_layout, const String &p_section); + FileSystemDock(); ~FileSystemDock(); }; +VARIANT_ENUM_CAST(FileSystemDock::Overwrite); + #endif // FILESYSTEM_DOCK_H diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index a14df01858..c708e77719 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -34,8 +34,8 @@ #include "core/io/dir_access.h" #include "core/os/os.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/check_box.h" @@ -172,9 +172,11 @@ void FindInFiles::_iterate() { _current_dir = _current_dir.path_join(folder_name); PackedStringArray sub_dirs; - _scan_dir("res://" + _current_dir, sub_dirs); + PackedStringArray files_to_scan; + _scan_dir("res://" + _current_dir, sub_dirs, files_to_scan); _folders_stack.push_back(sub_dirs); + _files_to_scan.append_array(files_to_scan); } else { // Go back one level. @@ -211,7 +213,7 @@ float FindInFiles::get_progress() const { return 0; } -void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders) { +void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders, PackedStringArray &out_files_to_scan) { Ref<DirAccess> dir = DirAccess::open(path); if (dir.is_null()) { print_verbose("Cannot open directory! " + path); @@ -227,8 +229,11 @@ void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders) { break; } - // If there is a .gdignore file in the directory, skip searching the directory. + // If there is a .gdignore file in the directory, clear all the files/folders + // to be searched on this path and skip searching the directory. if (file == ".gdignore") { + out_folders.clear(); + out_files_to_scan.clear(); break; } @@ -247,7 +252,7 @@ void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders) { } else { String file_ext = file.get_extension(); if (_extension_filter.has(file_ext)) { - _files_to_scan.push_back(path.path_join(file)); + out_files_to_scan.push_back(path.path_join(file)); } } } @@ -460,7 +465,7 @@ void FindInFilesDialog::_notification(int p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { if (is_visible()) { // Doesn't work more than once if not deferred... - _search_text_line_edit->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)_search_text_line_edit, &Control::grab_focus).call_deferred(); _search_text_line_edit->select_all(); // Extensions might have changed in the meantime, we clean them and instance them again. for (int i = 0; i < _filters_container->get_child_count(); i++) { diff --git a/editor/find_in_files.h b/editor/find_in_files.h index 25ce2b0415..fcf5dd6281 100644 --- a/editor/find_in_files.h +++ b/editor/find_in_files.h @@ -67,7 +67,7 @@ protected: private: void _process(); void _iterate(); - void _scan_dir(String path, PackedStringArray &out_folders); + void _scan_dir(String path, PackedStringArray &out_folders, PackedStringArray &out_files_to_scan); void _scan_file(String fpath); // Config diff --git a/editor/group_settings_editor.cpp b/editor/group_settings_editor.cpp index a91154ae36..634192ab50 100644 --- a/editor/group_settings_editor.cpp +++ b/editor/group_settings_editor.cpp @@ -31,13 +31,13 @@ #include "group_settings_editor.h" #include "core/config/project_settings.h" -#include "editor/editor_scale.h" +#include "editor/editor_file_system.h" +#include "editor/editor_node.h" #include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" #include "editor/gui/editor_validation_panel.h" #include "editor/scene_tree_dock.h" -#include "editor_file_system.h" -#include "editor_node.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/packed_scene.h" void GroupSettingsEditor::_notification(int p_what) { @@ -45,6 +45,9 @@ void GroupSettingsEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { update_groups(); } break; + case NOTIFICATION_THEME_CHANGED: { + add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + } break; } } diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 9fa9fe5a9d..723a7c8901 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -31,12 +31,12 @@ #include "groups_editor.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_validation_panel.h" #include "editor/project_settings_editor.h" #include "editor/scene_tree_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/check_button.h" #include "scene/gui/grid_container.h" @@ -274,20 +274,22 @@ void GroupsEditor::_update_groups_and_tree() { _update_tree(); } -void GroupsEditor::_update_scene_groups(Node *p_node) { - if (scene_groups_cache.has(p_node)) { - scene_groups = scene_groups_cache[p_node]; - scene_groups_cache.erase(p_node); +void GroupsEditor::_update_scene_groups(const ObjectID &p_id) { + HashMap<ObjectID, HashMap<StringName, bool>>::Iterator I = scene_groups_cache.find(p_id); + if (I) { + scene_groups = I->value; + scene_groups_cache.remove(I); } else { scene_groups = HashMap<StringName, bool>(); } } -void GroupsEditor::_cache_scene_groups(Node *p_node) { +void GroupsEditor::_cache_scene_groups(const ObjectID &p_id) { const int edited_scene_count = EditorNode::get_editor_data().get_edited_scene_count(); for (int i = 0; i < edited_scene_count; i++) { - if (p_node == EditorNode::get_editor_data().get_edited_scene_root(i)) { - scene_groups_cache[p_node] = scene_groups_for_caching; + Node *edited_scene_root = EditorNode::get_editor_data().get_edited_scene_root(i); + if (edited_scene_root && p_id == edited_scene_root->get_instance_id()) { + scene_groups_cache[p_id] = scene_groups_for_caching; break; } } @@ -305,7 +307,7 @@ void GroupsEditor::set_current(Node *p_node) { if (scene_tree->get_edited_scene_root() != scene_root_node) { scene_root_node = scene_tree->get_edited_scene_root(); - _update_scene_groups(scene_root_node); + _update_scene_groups(scene_root_node->get_instance_id()); _update_groups(); } @@ -803,7 +805,7 @@ void GroupsEditor::_bind_methods() { void GroupsEditor::_node_removed(Node *p_node) { if (scene_root_node == p_node) { scene_groups_for_caching = scene_groups; - callable_mp(this, &GroupsEditor::_cache_scene_groups).call_deferred(p_node); + callable_mp(this, &GroupsEditor::_cache_scene_groups).call_deferred(p_node->get_instance_id()); scene_root_node = nullptr; } diff --git a/editor/groups_editor.h b/editor/groups_editor.h index cf74470b1b..8a0ca067de 100644 --- a/editor/groups_editor.h +++ b/editor/groups_editor.h @@ -78,14 +78,14 @@ class GroupsEditor : public VBoxContainer { Button *add = nullptr; Tree *tree = nullptr; - HashMap<Node *, HashMap<StringName, bool>> scene_groups_cache; + HashMap<ObjectID, HashMap<StringName, bool>> scene_groups_cache; HashMap<StringName, bool> scene_groups_for_caching; HashMap<StringName, bool> scene_groups; HashMap<StringName, String> global_groups; - void _update_scene_groups(Node *p_node); - void _cache_scene_groups(Node *p_node); + void _update_scene_groups(const ObjectID &p_id); + void _cache_scene_groups(const ObjectID &p_id); void _show_add_group_dialog(); void _show_rename_group_dialog(); diff --git a/editor/gui/editor_dir_dialog.cpp b/editor/gui/editor_dir_dialog.cpp index fada434a03..8821a0eeae 100644 --- a/editor/gui/editor_dir_dialog.cpp +++ b/editor/gui/editor_dir_dialog.cpp @@ -30,22 +30,18 @@ #include "editor_dir_dialog.h" -#include "core/io/dir_access.h" -#include "core/os/keyboard.h" -#include "core/os/os.h" +#include "editor/directory_create_dialog.h" #include "editor/editor_file_system.h" -#include "editor/editor_scale.h" -#include "editor/editor_settings.h" -#include "scene/gui/check_box.h" +#include "scene/gui/box_container.h" #include "scene/gui/tree.h" #include "servers/display_server.h" void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p_dir, const String &p_select_path) { updating = true; - String path = p_dir->get_path(); + const String path = p_dir->get_path(); - p_item->set_metadata(0, p_dir->get_path()); + p_item->set_metadata(0, path); p_item->set_icon(0, tree->get_editor_theme_icon(SNAME("Folder"))); p_item->set_icon_modulate(0, tree->get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog"))); @@ -59,6 +55,10 @@ void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p p_item->set_text(0, p_dir->get_name()); } + if (path == new_dir_path || !p_item->get_parent()) { + p_item->select(0); + } + updating = false; for (int i = 0; i < p_dir->get_subdir_count(); i++) { TreeItem *ti = tree->create_item(p_item); @@ -66,6 +66,22 @@ void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p } } +void EditorDirDialog::config(const Vector<String> &p_paths) { + ERR_FAIL_COND(p_paths.is_empty()); + + if (p_paths.size() == 1) { + String path = p_paths[0]; + if (path.ends_with("/")) { + path = path.substr(0, path.length() - 1); + } + // TRANSLATORS: %s is the file name that will be moved or duplicated. + set_title(vformat(TTR("Move/Duplicate: %s"), path.get_file())); + } else { + // TRANSLATORS: %d is the number of files that will be moved or duplicated. + set_title(vformat(TTRN("Move/Duplicate %d Item", "Move/Duplicate %d Items", p_paths.size()), p_paths.size())); + } +} + void EditorDirDialog::reload(const String &p_path) { if (!is_visible()) { must_reload = true; @@ -76,13 +92,10 @@ void EditorDirDialog::reload(const String &p_path) { TreeItem *root = tree->create_item(); _update_dir(root, EditorFileSystem::get_singleton()->get_filesystem(), p_path); _item_collapsed(root); + new_dir_path.clear(); must_reload = false; } -bool EditorDirDialog::is_copy_pressed() const { - return copy->is_pressed(); -} - void EditorDirDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -112,14 +125,6 @@ void EditorDirDialog::_notification(int p_what) { } } -void EditorDirDialog::_copy_toggled(bool p_pressed) { - if (p_pressed) { - set_ok_button_text(TTR("Copy")); - } else { - set_ok_button_text(TTR("Move")); - } -} - void EditorDirDialog::_item_collapsed(Object *p_item) { TreeItem *item = Object::cast_to<TreeItem>(p_item); @@ -135,100 +140,83 @@ void EditorDirDialog::_item_collapsed(Object *p_item) { } void EditorDirDialog::_item_activated() { - _ok_pressed(); // From AcceptDialog. + TreeItem *ti = tree->get_selected(); + ERR_FAIL_NULL(ti); + if (ti->get_child_count() > 0) { + ti->set_collapsed(!ti->is_collapsed()); + } } -void EditorDirDialog::ok_pressed() { +void EditorDirDialog::_copy_pressed() { TreeItem *ti = tree->get_selected(); - if (!ti) { - return; - } + ERR_FAIL_NULL(ti); - String dir = ti->get_metadata(0); - emit_signal(SNAME("dir_selected"), dir); hide(); + emit_signal(SNAME("copy_pressed"), ti->get_metadata(0)); } -void EditorDirDialog::_make_dir() { +void EditorDirDialog::ok_pressed() { TreeItem *ti = tree->get_selected(); - if (!ti) { - mkdirerr->set_text(TTR("Please select a base directory first.")); - mkdirerr->popup_centered(); - return; - } + ERR_FAIL_NULL(ti); - makedialog->popup_centered(Size2(250, 80)); - makedirname->grab_focus(); + hide(); + emit_signal(SNAME("move_pressed"), ti->get_metadata(0)); } -void EditorDirDialog::_make_dir_confirm() { +void EditorDirDialog::_make_dir() { TreeItem *ti = tree->get_selected(); - if (!ti) { - return; - } - - String dir = ti->get_metadata(0); - - Ref<DirAccess> d = DirAccess::open(dir); - ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + dir + "'."); - - const String stripped_dirname = makedirname->get_text().strip_edges(); + ERR_FAIL_NULL(ti); + makedialog->config(ti->get_metadata(0)); + makedialog->popup_centered(); +} - if (d->dir_exists(stripped_dirname)) { - mkdirerr->set_text(TTR("Could not create folder. File with that name already exists.")); - mkdirerr->popup_centered(); - return; +void EditorDirDialog::_make_dir_confirm(const String &p_path) { + // Multiple level of directories can be created at once. + String base_dir = p_path.get_base_dir(); + while (true) { + opened_paths.insert(base_dir + "/"); + if (base_dir == "res://") { + break; + } + base_dir = base_dir.get_base_dir(); } - Error err = d->make_dir(stripped_dirname); - if (err != OK) { - mkdirerr->popup_centered(Size2(250, 80) * EDSCALE); - } else { - opened_paths.insert(dir); - EditorFileSystem::get_singleton()->scan_changes(); // We created a dir, so rescan changes. - } - makedirname->set_text(""); // reset label + new_dir_path = p_path + "/"; + EditorFileSystem::get_singleton()->scan_changes(); // We created a dir, so rescan changes. } void EditorDirDialog::_bind_methods() { - ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir"))); + ADD_SIGNAL(MethodInfo("copy_pressed", PropertyInfo(Variant::STRING, "dir"))); + ADD_SIGNAL(MethodInfo("move_pressed", PropertyInfo(Variant::STRING, "dir"))); } EditorDirDialog::EditorDirDialog() { - set_title(TTR("Choose a Directory")); set_hide_on_ok(false); VBoxContainer *vb = memnew(VBoxContainer); add_child(vb); + HBoxContainer *hb = memnew(HBoxContainer); + vb->add_child(hb); + + hb->add_child(memnew(Label(TTR("Choose target directory:")))); + hb->add_spacer(); + + makedir = memnew(Button(TTR("Create Folder"))); + hb->add_child(makedir); + makedir->connect("pressed", callable_mp(this, &EditorDirDialog::_make_dir)); + tree = memnew(Tree); vb->add_child(tree); tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->connect("item_activated", callable_mp(this, &EditorDirDialog::_item_activated)); - copy = memnew(CheckBox); - vb->add_child(copy); - copy->set_text(TTR("Copy File(s)")); - copy->connect("toggled", callable_mp(this, &EditorDirDialog::_copy_toggled)); + set_ok_button_text(TTR("Move")); - makedir = add_button(TTR("Create Folder"), DisplayServer::get_singleton()->get_swap_cancel_ok(), "makedir"); - makedir->connect("pressed", callable_mp(this, &EditorDirDialog::_make_dir)); + copy = add_button(TTR("Copy"), !DisplayServer::get_singleton()->get_swap_cancel_ok()); + copy->connect("pressed", callable_mp(this, &EditorDirDialog::_copy_pressed)); - makedialog = memnew(ConfirmationDialog); - makedialog->set_title(TTR("Create Folder")); + makedialog = memnew(DirectoryCreateDialog); add_child(makedialog); - - VBoxContainer *makevb = memnew(VBoxContainer); - makedialog->add_child(makevb); - - makedirname = memnew(LineEdit); - makevb->add_margin_child(TTR("Name:"), makedirname); - makedialog->register_text_enter(makedirname); - makedialog->connect("confirmed", callable_mp(this, &EditorDirDialog::_make_dir_confirm)); - - mkdirerr = memnew(AcceptDialog); - mkdirerr->set_text(TTR("Could not create folder.")); - add_child(mkdirerr); - - set_ok_button_text(TTR("Move")); + makedialog->connect("dir_created", callable_mp(this, &EditorDirDialog::_make_dir_confirm)); } diff --git a/editor/gui/editor_dir_dialog.h b/editor/gui/editor_dir_dialog.h index 9f2b48c164..40badec212 100644 --- a/editor/gui/editor_dir_dialog.h +++ b/editor/gui/editor_dir_dialog.h @@ -33,7 +33,7 @@ #include "scene/gui/dialogs.h" -class CheckBox; +class DirectoryCreateDialog; class EditorFileSystemDirectory; class Tree; class TreeItem; @@ -41,25 +41,24 @@ class TreeItem; class EditorDirDialog : public ConfirmationDialog { GDCLASS(EditorDirDialog, ConfirmationDialog); - ConfirmationDialog *makedialog = nullptr; - LineEdit *makedirname = nullptr; - AcceptDialog *mkdirerr = nullptr; + DirectoryCreateDialog *makedialog = nullptr; Button *makedir = nullptr; + Button *copy = nullptr; HashSet<String> opened_paths; + String new_dir_path; Tree *tree = nullptr; bool updating = false; - CheckBox *copy = nullptr; - void _copy_toggled(bool p_pressed); void _item_collapsed(Object *p_item); void _item_activated(); void _update_dir(TreeItem *p_item, EditorFileSystemDirectory *p_dir, const String &p_select_path = String()); void _make_dir(); - void _make_dir_confirm(); + void _make_dir_confirm(const String &p_path); + void _copy_pressed(); void ok_pressed() override; bool must_reload = false; @@ -69,8 +68,8 @@ protected: static void _bind_methods(); public: + void config(const Vector<String> &p_paths); void reload(const String &p_path = ""); - bool is_copy_pressed() const; EditorDirDialog(); }; diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp index fad7e29be7..4d1fd1f7b7 100644 --- a/editor/gui/editor_file_dialog.cpp +++ b/editor/gui/editor_file_dialog.cpp @@ -38,9 +38,9 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/filesystem_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/center_container.h" #include "scene/gui/label.h" #include "scene/gui/margin_container.h" @@ -1909,6 +1909,7 @@ EditorFileDialog::EditorFileDialog() { fav_down->connect("pressed", callable_mp(this, &EditorFileDialog::_favorite_move_down)); favorites = memnew(ItemList); + favorites->set_auto_translate(false); fav_vb->add_child(favorites); favorites->set_v_size_flags(Control::SIZE_EXPAND_FILL); favorites->connect("item_selected", callable_mp(this, &EditorFileDialog::_favorite_selected)); @@ -1918,6 +1919,7 @@ EditorFileDialog::EditorFileDialog() { rec_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE); rec_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL); recent = memnew(ItemList); + recent->set_auto_translate(false); recent->set_allow_reselect(true); rec_vb->add_margin_child(TTR("Recent:"), recent, true); recent->connect("item_selected", callable_mp(this, &EditorFileDialog::_recent_selected)); @@ -1941,6 +1943,7 @@ EditorFileDialog::EditorFileDialog() { // Item (files and folders) list with context menu. item_list = memnew(ItemList); + item_list->set_auto_translate(false); item_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); item_list->connect("item_clicked", callable_mp(this, &EditorFileDialog::_item_list_item_rmb_clicked)); item_list->connect("empty_clicked", callable_mp(this, &EditorFileDialog::_item_list_empty_clicked)); diff --git a/editor/gui/editor_object_selector.cpp b/editor/gui/editor_object_selector.cpp index 9acd38bcf4..c97d68fb35 100644 --- a/editor/gui/editor_object_selector.cpp +++ b/editor/gui/editor_object_selector.cpp @@ -32,9 +32,9 @@ #include "editor/editor_data.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/multi_node_edit.h" +#include "editor/themes/editor_scale.h" Size2 EditorObjectSelector::get_minimum_size() const { Ref<Font> font = get_theme_font(SNAME("font")); diff --git a/editor/gui/editor_scene_tabs.cpp b/editor/gui/editor_scene_tabs.cpp index 7f8f2fd8a3..915b161372 100644 --- a/editor/gui/editor_scene_tabs.cpp +++ b/editor/gui/editor_scene_tabs.cpp @@ -32,11 +32,11 @@ #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/inspector_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/panel.h" diff --git a/editor/gui/editor_spin_slider.cpp b/editor/gui/editor_spin_slider.cpp index 750837cce9..8401f08391 100644 --- a/editor/gui/editor_spin_slider.cpp +++ b/editor/gui/editor_spin_slider.cpp @@ -33,8 +33,8 @@ #include "core/input/input.h" #include "core/math/expression.h" #include "core/os/keyboard.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/themes/editor_scale.h" String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const { if (grabber->is_visible()) { @@ -92,7 +92,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) { } } else if (mb->get_button_index() == MouseButton::WHEEL_UP || mb->get_button_index() == MouseButton::WHEEL_DOWN) { if (grabber->is_visible()) { - call_deferred(SNAME("queue_redraw")); + callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw).call_deferred(); } } } @@ -637,11 +637,11 @@ void EditorSpinSlider::_focus_entered() { _ensure_input_popup(); value_input->set_text(get_text_value()); value_input_popup->set_size(get_size()); - value_input_popup->call_deferred(SNAME("show")); - value_input->call_deferred(SNAME("grab_focus")); - value_input->call_deferred(SNAME("select_all")); value_input->set_focus_next(find_next_valid_focus()->get_path()); value_input->set_focus_previous(find_prev_valid_focus()->get_path()); + callable_mp((CanvasItem *)value_input_popup, &CanvasItem::show).call_deferred(); + callable_mp((Control *)value_input, &Control::grab_focus).call_deferred(); + callable_mp(value_input, &LineEdit ::select_all).call_deferred(); emit_signal("value_focus_entered"); } diff --git a/editor/gui/editor_toaster.cpp b/editor/gui/editor_toaster.cpp index 1abb591508..48e1c56e83 100644 --- a/editor/gui/editor_toaster.cpp +++ b/editor/gui/editor_toaster.cpp @@ -30,9 +30,9 @@ #include "editor_toaster.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/gui/label.h" #include "scene/gui/panel_container.h" @@ -406,7 +406,7 @@ void EditorToaster::popup_str(String p_message, Severity p_severity, String p_to // Since "_popup_str" adds nodes to the tree, and since the "add_child" method is not // thread-safe, it's better to defer the call to the next cycle to be thread-safe. is_processing_error = true; - call_deferred(SNAME("_popup_str"), p_message, p_severity, p_tooltip); + callable_mp(this, &EditorToaster::_popup_str).call_deferred(p_message, p_severity, p_tooltip); is_processing_error = false; } @@ -499,11 +499,6 @@ EditorToaster *EditorToaster::get_singleton() { return singleton; } -void EditorToaster::_bind_methods() { - // Binding method to make it defer-able. - ClassDB::bind_method(D_METHOD("_popup_str", "message", "severity", "tooltip"), &EditorToaster::_popup_str); -} - EditorToaster::EditorToaster() { set_notify_transform(true); set_process_internal(true); diff --git a/editor/gui/editor_toaster.h b/editor/gui/editor_toaster.h index 3e39d9d519..5034cb66fc 100644 --- a/editor/gui/editor_toaster.h +++ b/editor/gui/editor_toaster.h @@ -105,7 +105,6 @@ private: protected: static EditorToaster *singleton; - static void _bind_methods(); void _notification(int p_what); diff --git a/editor/gui/editor_validation_panel.cpp b/editor/gui/editor_validation_panel.cpp index 14fe05e906..c08af1915f 100644 --- a/editor/gui/editor_validation_panel.cpp +++ b/editor/gui/editor_validation_panel.cpp @@ -30,8 +30,8 @@ #include "editor_validation_panel.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/label.h" diff --git a/editor/gui/editor_zoom_widget.cpp b/editor/gui/editor_zoom_widget.cpp index 7d522761f3..6db4c5047e 100644 --- a/editor/gui/editor_zoom_widget.cpp +++ b/editor/gui/editor_zoom_widget.cpp @@ -31,8 +31,8 @@ #include "editor_zoom_widget.h" #include "core/os/keyboard.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/themes/editor_scale.h" void EditorZoomWidget::_update_zoom_label() { String zoom_text; diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp index 327b73f993..7a9df26fa7 100644 --- a/editor/gui/scene_tree_editor.cpp +++ b/editor/gui/scene_tree_editor.cpp @@ -31,11 +31,9 @@ #include "scene_tree_editor.h" #include "core/config/project_settings.h" -#include "core/object/message_queue.h" #include "core/object/script_language.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" @@ -43,6 +41,7 @@ #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/flow_container.h" #include "scene/gui/label.h" #include "scene/gui/tab_container.h" @@ -121,7 +120,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i } } else if (p_id == BUTTON_GROUP) { - undo_redo->create_action(TTR("Button Group")); + undo_redo->create_action(TTR("Ungroup Children")); if (n->is_class("CanvasItem") || n->is_class("Node3D")) { undo_redo->add_do_method(n, "remove_meta", "_edit_group_"); @@ -236,7 +235,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { item->add_button(0, get_editor_theme_icon(SNAME("Script")), BUTTON_SCRIPT); } else { //has no script (or script is a custom type) - _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); item->set_selectable(0, false); if (!scr.is_null()) { // make sure to mark the script if a custom type @@ -268,7 +267,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { item->set_selectable(0, marked_selectable); _set_item_custom_color(item, get_theme_color(SNAME("accent_color"), EditorStringName(Editor))); } else if (!p_node->can_process()) { - _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } else if (!marked_selectable && !marked_children_selectable) { Node *node = p_node; while (node) { @@ -361,33 +360,12 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } { - // Display the node name in all tooltips so that long node names can be previewed - // without having to rename them. - String tooltip = String(p_node->get_name()); - - if (p_node == get_scene_node() && p_node->get_scene_inherited_state().is_valid()) { - item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); - tooltip += String("\n" + TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path()); - } else if (p_node != get_scene_node() && !p_node->get_scene_file_path().is_empty() && can_open_instance) { - item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); - tooltip += String("\n" + TTR("Instance:") + " " + p_node->get_scene_file_path()); + _update_node_tooltip(p_node, item); + Callable delay_update_tooltip = callable_mp(this, &SceneTreeEditor::_queue_update_node_tooltip); + if (p_node->is_connected("editor_description_changed", delay_update_tooltip)) { + p_node->disconnect("editor_description_changed", delay_update_tooltip); } - - StringName custom_type = EditorNode::get_singleton()->get_object_custom_type_name(p_node); - tooltip += String("\n" + TTR("Type:") + " " + (custom_type != StringName() ? String(custom_type) : p_node->get_class())); - - if (!p_node->get_editor_description().is_empty()) { - const PackedInt32Array boundaries = TS->string_get_word_breaks(p_node->get_editor_description(), "", 80); - tooltip += "\n"; - - for (int i = 0; i < boundaries.size(); i += 2) { - const int start = boundaries[i]; - const int end = boundaries[i + 1]; - tooltip += "\n" + p_node->get_editor_description().substr(start, end - start + 1).rstrip("\n"); - } - } - - item->set_tooltip_text(0, tooltip); + p_node->connect("editor_description_changed", delay_update_tooltip.bind(item)); } if (can_open_instance && is_scene_tree_dock) { // Show buttons only when necessary (SceneTreeDock) to avoid crashes. @@ -514,12 +492,52 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (!valid) { - _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); item->set_selectable(0, false); } } } +void SceneTreeEditor::_queue_update_node_tooltip(Node *p_node, TreeItem *p_item) { + Callable update_tooltip = callable_mp(this, &SceneTreeEditor::_update_node_tooltip); + if (update_node_tooltip_delay->is_connected("timeout", update_tooltip)) { + update_node_tooltip_delay->disconnect("timeout", update_tooltip); + } + + update_node_tooltip_delay->connect("timeout", update_tooltip.bind(p_node, p_item)); + update_node_tooltip_delay->start(); +} + +void SceneTreeEditor::_update_node_tooltip(Node *p_node, TreeItem *p_item) { + // Display the node name in all tooltips so that long node names can be previewed + // without having to rename them. + String tooltip = p_node->get_name(); + + if (p_node == get_scene_node() && p_node->get_scene_inherited_state().is_valid()) { + p_item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); + tooltip += String("\n" + TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path()); + } else if (p_node != get_scene_node() && !p_node->get_scene_file_path().is_empty() && can_open_instance) { + p_item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); + tooltip += String("\n" + TTR("Instance:") + " " + p_node->get_scene_file_path()); + } + + StringName custom_type = EditorNode::get_singleton()->get_object_custom_type_name(p_node); + tooltip += "\n" + TTR("Type:") + " " + (custom_type != StringName() ? String(custom_type) : p_node->get_class()); + + if (!p_node->get_editor_description().is_empty()) { + const PackedInt32Array boundaries = TS->string_get_word_breaks(p_node->get_editor_description(), "", 80); + tooltip += "\n"; + + for (int i = 0; i < boundaries.size(); i += 2) { + const int start = boundaries[i]; + const int end = boundaries[i + 1]; + tooltip += "\n" + p_node->get_editor_description().substr(start, end - start + 1).rstrip("\n"); + } + } + + p_item->set_tooltip_text(0, tooltip); +} + void SceneTreeEditor::_node_visibility_changed(Node *p_node) { if (!p_node || (p_node != get_scene_node() && !p_node->get_owner())) { return; @@ -574,7 +592,7 @@ void SceneTreeEditor::_node_script_changed(Node *p_node) { return; } - MessageQueue::get_singleton()->push_call(this, "_update_tree"); + callable_mp(this, &SceneTreeEditor::_update_tree).call_deferred(false); tree_dirty = true; } @@ -607,7 +625,7 @@ void SceneTreeEditor::_node_renamed(Node *p_node) { emit_signal(SNAME("node_renamed")); if (!tree_dirty) { - MessageQueue::get_singleton()->push_call(this, "_update_tree"); + callable_mp(this, &SceneTreeEditor::_update_tree).call_deferred(false); tree_dirty = true; } } @@ -700,7 +718,7 @@ bool SceneTreeEditor::_update_filter(TreeItem *p_parent, bool p_scroll_to_select } p_parent->set_selectable(0, true); } else if (keep_for_children) { - p_parent->set_custom_color(0, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + p_parent->set_custom_color(0, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); p_parent->set_selectable(0, false); p_parent->deselect(0); } @@ -728,7 +746,7 @@ bool SceneTreeEditor::_item_matches_all_terms(TreeItem *p_item, PackedStringArra } for (int i = 0; i < p_terms.size(); i++) { - String term = p_terms[i]; + const String &term = p_terms[i]; // Recognize special filter. if (term.contains(":") && !term.get_slicec(':', 0).is_empty()) { @@ -824,12 +842,12 @@ void SceneTreeEditor::_test_update_tree() { return; // did not change } - MessageQueue::get_singleton()->push_call(this, "_update_tree"); + callable_mp(this, &SceneTreeEditor::_update_tree).call_deferred(false); tree_dirty = true; } void SceneTreeEditor::_tree_process_mode_changed() { - MessageQueue::get_singleton()->push_call(this, "_update_tree"); + callable_mp(this, &SceneTreeEditor::_update_tree).call_deferred(false); tree_dirty = true; } @@ -844,7 +862,7 @@ void SceneTreeEditor::_tree_changed() { return; } - MessageQueue::get_singleton()->push_call(this, "_test_update_tree"); + callable_mp(this, &SceneTreeEditor::_test_update_tree).call_deferred(); pending_test_update = true; } @@ -1465,7 +1483,6 @@ void SceneTreeEditor::set_connecting_signal(bool p_enable) { void SceneTreeEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_tree"), &SceneTreeEditor::_update_tree, DEFVAL(false)); // Still used by UndoRedo. ClassDB::bind_method("_rename_node", &SceneTreeEditor::_rename_node); - ClassDB::bind_method("_test_update_tree", &SceneTreeEditor::_test_update_tree); ClassDB::bind_method(D_METHOD("update_tree"), &SceneTreeEditor::update_tree); @@ -1538,6 +1555,11 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope update_timer->set_wait_time(0.5); add_child(update_timer); + update_node_tooltip_delay = memnew(Timer); + update_node_tooltip_delay->set_wait_time(0.5); + update_node_tooltip_delay->set_one_shot(true); + add_child(update_node_tooltip_delay); + script_types = memnew(List<StringName>); ClassDB::get_inheriters_from_class("Script", script_types); } @@ -1618,7 +1640,7 @@ void SceneTreeDialog::_notification(int p_what) { tree->update_tree(); // Select the search bar by default. - filter->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)filter, &Control::grab_focus).call_deferred(); } } break; diff --git a/editor/gui/scene_tree_editor.h b/editor/gui/scene_tree_editor.h index 96d6d065f6..179050daeb 100644 --- a/editor/gui/scene_tree_editor.h +++ b/editor/gui/scene_tree_editor.h @@ -37,6 +37,7 @@ class EditorSelection; class TextureRect; +class Timer; class SceneTreeEditor : public Control { GDCLASS(SceneTreeEditor, Control); @@ -108,6 +109,8 @@ class SceneTreeEditor : public Control { bool display_foreign = false; bool tree_dirty = true; bool pending_test_update = false; + Timer *update_node_tooltip_delay = nullptr; + static void _bind_methods(); void _cell_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button); @@ -118,6 +121,8 @@ class SceneTreeEditor : public Control { void _node_visibility_changed(Node *p_node); void _update_visibility_color(Node *p_node, TreeItem *p_item); void _set_item_custom_color(TreeItem *p_item, Color p_color); + void _update_node_tooltip(Node *p_node, TreeItem *p_item); + void _queue_update_node_tooltip(Node *p_node, TreeItem *p_item); void _selection_changed(); Node *get_scene_node() const; diff --git a/editor/history_dock.cpp b/editor/history_dock.cpp index 0ec840b8f1..6ec240fdf0 100644 --- a/editor/history_dock.cpp +++ b/editor/history_dock.cpp @@ -248,6 +248,7 @@ HistoryDock::HistoryDock() { global_history_checkbox->connect("toggled", callable_mp(this, &HistoryDock::refresh_history).unbind(1)); action_list = memnew(ItemList); + action_list->set_auto_translate(false); add_child(action_list); action_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); action_list->connect("item_selected", callable_mp(this, &HistoryDock::seek_history)); diff --git a/editor/icons/GuiHsplitter.svg b/editor/icons/GuiHsplitter.svg index 6d1f7e785c..cf42f057c6 100644 --- a/editor/icons/GuiHsplitter.svg +++ b/editor/icons/GuiHsplitter.svg @@ -1 +1 @@ -<svg height="64" viewBox="0 0 8 64" width="8" xmlns="http://www.w3.org/2000/svg"><path d="M4 2v60" fill="none" stroke="#fff" stroke-linecap="round" stroke-opacity=".4" stroke-width="2"/></svg> +<svg height="64" viewBox="0 0 2 64" width="2" xmlns="http://www.w3.org/2000/svg"><path d="M1 2v60" fill="none" stroke="#fff" stroke-linecap="round" stroke-opacity=".4" stroke-width="2"/></svg> diff --git a/editor/icons/GuiVsplitter.svg b/editor/icons/GuiVsplitter.svg index cadd231579..b7850e76f0 100644 --- a/editor/icons/GuiVsplitter.svg +++ b/editor/icons/GuiVsplitter.svg @@ -1 +1 @@ -<svg height="8" viewBox="0 0 64 8" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M2 4h60" fill="none" stroke="#fff" stroke-linecap="round" stroke-opacity=".4" stroke-width="2"/></svg> +<svg height="2" viewBox="0 0 64 2" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M2 1h60" fill="none" stroke="#fff" stroke-linecap="round" stroke-opacity=".4" stroke-width="2"/></svg> diff --git a/editor/icons/PhysicsMaterial.svg b/editor/icons/PhysicsMaterial.svg new file mode 100644 index 0000000000..bdb41a1d27 --- /dev/null +++ b/editor/icons/PhysicsMaterial.svg @@ -0,0 +1 @@ +<svg height="16" width="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#e0e0e0"><path d="M14 8.5v4L8 15l-6-2.5v-4M8 11v4" stroke-opacity=".6" stroke-linejoin="round" stroke-width="2"/><path d="m8 6 6 2.5L8 11 2 8.5z" stroke-linejoin="round" stroke-width="2"/><path d="M3.5 2l1 1.8M8 1v2m4.5-1-1 1.8" stroke-linecap="round" stroke-width="1.75"/></g></svg> diff --git a/editor/icons/SCsub b/editor/icons/SCsub index dd4243d750..cbbfe1d7ea 100644 --- a/editor/icons/SCsub +++ b/editor/icons/SCsub @@ -3,7 +3,6 @@ Import("env") import os - import editor_icons_builders @@ -23,4 +22,4 @@ for path in env.module_icons_paths: else: icon_sources += Glob(path + "/*.svg") # Custom. -env.Alias("editor_icons", [env.MakeEditorIconsBuilder("#editor/editor_icons.gen.h", icon_sources)]) +env.Alias("editor_icons", [env.MakeEditorIconsBuilder("#editor/themes/editor_icons.gen.h", icon_sources)]) diff --git a/editor/icons/Terminal.svg b/editor/icons/Terminal.svg new file mode 100644 index 0000000000..5d92bdf8be --- /dev/null +++ b/editor/icons/Terminal.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m2 13 5.0000552-5-5.0000552-5"/><path d="m9 13h5"/></g></svg> diff --git a/editor/icons/TileMapLayer.svg b/editor/icons/TileMapLayer.svg new file mode 100644 index 0000000000..1903a87e3b --- /dev/null +++ b/editor/icons/TileMapLayer.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 7v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#8da5f3"/></svg>
\ No newline at end of file diff --git a/editor/icons/editor_icons_builders.py b/editor/icons/editor_icons_builders.py index 359245b6d7..378eb323db 100644 --- a/editor/icons/editor_icons_builders.py +++ b/editor/icons/editor_icons_builders.py @@ -1,4 +1,5 @@ -"""Functions used to generate source files during build time +""" +Functions used to generate source files during build time All such functions are invoked in a subprocess on Windows to prevent build flakiness. diff --git a/editor/import/collada.cpp b/editor/import/3d/collada.cpp index be63973ea7..ae8041d6fe 100644 --- a/editor/import/collada.cpp +++ b/editor/import/3d/collada.cpp @@ -1718,7 +1718,7 @@ void Collada::_parse_animation(XMLParser &p_parser) { for (int i = 0; i < channel_sources.size(); i++) { String source = _uri_to_id(channel_sources[i]); - String target = channel_targets[i]; + const String &target = channel_targets[i]; ERR_CONTINUE(!samplers.has(source)); HashMap<String, String> &sampler = samplers[source]; diff --git a/editor/import/collada.h b/editor/import/3d/collada.h index 7877b1e86d..7877b1e86d 100644 --- a/editor/import/collada.h +++ b/editor/import/3d/collada.h diff --git a/editor/import/editor_import_collada.cpp b/editor/import/3d/editor_import_collada.cpp index 3f7ed8ab8b..49fec679bf 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/3d/editor_import_collada.cpp @@ -32,7 +32,7 @@ #include "core/os/os.h" #include "editor/editor_node.h" -#include "editor/import/collada.h" +#include "editor/import/3d/collada.h" #include "scene/3d/camera_3d.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/light_3d.h" @@ -1151,7 +1151,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres ERR_FAIL_COND_V(skeletons.is_empty(), ERR_INVALID_DATA); - String skname = skeletons[0]; + const String &skname = skeletons[0]; ERR_FAIL_COND_V(!node_map.has(skname), ERR_INVALID_DATA); NodeMap nmsk = node_map[skname]; Skeleton3D *sk = Object::cast_to<Skeleton3D>(nmsk.node); @@ -1205,7 +1205,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres valid = true; Vector<String> names = morph->sources[target].sarray; for (int i = 0; i < names.size(); i++) { - String meshid2 = names[i]; + const String &meshid2 = names[i]; if (collada.state.mesh_data_map.has(meshid2)) { Ref<ImporterMesh> mesh = Ref<ImporterMesh>(memnew(ImporterMesh)); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid2]; diff --git a/editor/import/editor_import_collada.h b/editor/import/3d/editor_import_collada.h index 2950f499cb..e0214c2fd0 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/3d/editor_import_collada.h @@ -31,7 +31,7 @@ #ifndef EDITOR_IMPORT_COLLADA_H #define EDITOR_IMPORT_COLLADA_H -#include "editor/import/resource_importer_scene.h" +#include "editor/import/3d/resource_importer_scene.h" class EditorSceneFormatImporterCollada : public EditorSceneFormatImporter { GDCLASS(EditorSceneFormatImporterCollada, EditorSceneFormatImporter); diff --git a/editor/import/post_import_plugin_skeleton_renamer.cpp b/editor/import/3d/post_import_plugin_skeleton_renamer.cpp index adeea51dae..ffe75f189c 100644 --- a/editor/import/post_import_plugin_skeleton_renamer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_renamer.cpp @@ -30,7 +30,7 @@ #include "post_import_plugin_skeleton_renamer.h" -#include "editor/import/scene_import_settings.h" +#include "editor/import/3d/scene_import_settings.h" #include "scene/3d/bone_attachment_3d.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/skeleton_3d.h" @@ -45,7 +45,7 @@ void PostImportPluginSkeletonRenamer::get_internal_import_options(InternalImport } } -void PostImportPluginSkeletonRenamer::_internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options, HashMap<String, String> p_rename_map) { +void PostImportPluginSkeletonRenamer::_internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options, const HashMap<String, String> &p_rename_map) { // Prepare objects. Object *map = p_options["retarget/bone_map"].get_validated_object(); if (!map || !bool(p_options["retarget/bone_renamer/rename_bones"])) { @@ -121,7 +121,7 @@ void PostImportPluginSkeletonRenamer::_internal_process(InternalImportCategory p // Rename bones in all Nodes by calling method. { Dictionary rename_map_dict; - for (HashMap<String, String>::Iterator E = p_rename_map.begin(); E; ++E) { + for (HashMap<String, String>::ConstIterator E = p_rename_map.begin(); E; ++E) { rename_map_dict[E->key] = E->value; } diff --git a/editor/import/post_import_plugin_skeleton_renamer.h b/editor/import/3d/post_import_plugin_skeleton_renamer.h index 98f778f6c2..a977117374 100644 --- a/editor/import/post_import_plugin_skeleton_renamer.h +++ b/editor/import/3d/post_import_plugin_skeleton_renamer.h @@ -40,7 +40,7 @@ public: virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) override; virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) override; - void _internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options, HashMap<String, String> p_rename_map); + void _internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options, const HashMap<String, String> &p_rename_map); PostImportPluginSkeletonRenamer(); }; diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp index 3390bf4ed4..53bf24fb7e 100644 --- a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp @@ -30,7 +30,7 @@ #include "post_import_plugin_skeleton_rest_fixer.h" -#include "editor/import/scene_import_settings.h" +#include "editor/import/3d/scene_import_settings.h" #include "scene/3d/bone_attachment_3d.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/skeleton_3d.h" diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.h b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.h index c765169fd0..c765169fd0 100644 --- a/editor/import/post_import_plugin_skeleton_rest_fixer.h +++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.h diff --git a/editor/import/post_import_plugin_skeleton_track_organizer.cpp b/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp index e5a8e879fc..53bcc59fcb 100644 --- a/editor/import/post_import_plugin_skeleton_track_organizer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp @@ -30,7 +30,7 @@ #include "post_import_plugin_skeleton_track_organizer.h" -#include "editor/import/scene_import_settings.h" +#include "editor/import/3d/scene_import_settings.h" #include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/bone_map.h" diff --git a/editor/import/post_import_plugin_skeleton_track_organizer.h b/editor/import/3d/post_import_plugin_skeleton_track_organizer.h index 24a4f70aa9..24a4f70aa9 100644 --- a/editor/import/post_import_plugin_skeleton_track_organizer.h +++ b/editor/import/3d/post_import_plugin_skeleton_track_organizer.h diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/3d/resource_importer_obj.cpp index 082e78fdbe..a5e51636af 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/3d/resource_importer_obj.cpp @@ -202,7 +202,7 @@ static Error _parse_material_library(const String &p_path, HashMap<String, Ref<S return OK; } -static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_optimize, Vector3 p_scale_mesh, Vector3 p_offset_mesh, bool p_disable_compression, List<String> *r_missing_deps) { +static Error _parse_obj(const String &p_path, List<Ref<ImporterMesh>> &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_optimize, Vector3 p_scale_mesh, Vector3 p_offset_mesh, bool p_disable_compression, List<String> *r_missing_deps) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path)); @@ -220,7 +220,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ ERR_FAIL_COND_V_MSG(coff_header_machines.find(first_bytes) != -1, ERR_FILE_CORRUPT, vformat("Couldn't read OBJ file '%s', it seems to be binary, corrupted, or empty.", p_path)); f->seek(0); - Ref<ArrayMesh> mesh; + Ref<ImporterMesh> mesh; mesh.instantiate(); bool generate_tangents = p_generate_tangents; @@ -400,24 +400,24 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ print_verbose("OBJ: Current material library " + current_material_library + " has " + itos(material_map.has(current_material_library))); print_verbose("OBJ: Current material " + current_material + " has " + itos(material_map.has(current_material_library) && material_map[current_material_library].has(current_material))); - + Ref<StandardMaterial3D> material; if (material_map.has(current_material_library) && material_map[current_material_library].has(current_material)) { - Ref<StandardMaterial3D> &material = material_map[current_material_library][current_material]; + material = material_map[current_material_library][current_material]; if (!colors.is_empty()) { material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); } surf_tool->set_material(material); } - mesh = surf_tool->commit(mesh, mesh_flags); - if (!current_material.is_empty()) { - mesh->surface_set_name(mesh->get_surface_count() - 1, current_material.get_basename()); + mesh->set_surface_name(mesh->get_surface_count() - 1, current_material.get_basename()); } else if (!current_group.is_empty()) { - mesh->surface_set_name(mesh->get_surface_count() - 1, current_group); + mesh->set_surface_name(mesh->get_surface_count() - 1, current_group); } + Array array = surf_tool->commit_to_arrays(); + mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, array, TypedArray<Array>(), Dictionary(), material, name, mesh_flags); + print_verbose("OBJ: Added surface :" + mesh->get_surface_name(mesh->get_surface_count() - 1)); - print_verbose("OBJ: Added surface :" + mesh->surface_get_name(mesh->get_surface_count() - 1)); surf_tool->clear(); surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES); } @@ -476,7 +476,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ } Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) { - List<Ref<Mesh>> meshes; + List<Ref<ImporterMesh>> meshes; Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, false, Vector3(1, 1, 1), Vector3(0, 0, 0), p_flags & IMPORT_FORCE_DISABLE_MESH_COMPRESSION, r_missing_deps); @@ -489,16 +489,9 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, co Node3D *scene = memnew(Node3D); - for (const Ref<Mesh> &m : meshes) { - Ref<ImporterMesh> mesh; - mesh.instantiate(); - mesh->set_name(m->get_name()); - 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), String(), m->surface_get_format(i)); - } - + for (Ref<ImporterMesh> m : meshes) { ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D); - mi->set_mesh(mesh); + mi->set_mesh(m); mi->set_name(m->get_name()); scene->add_child(mi, true); mi->set_owner(scene); @@ -565,7 +558,7 @@ bool ResourceImporterOBJ::get_option_visibility(const String &p_path, const Stri } Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { - List<Ref<Mesh>> meshes; + List<Ref<ImporterMesh>> meshes; Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["optimize_mesh"], p_options["scale_mesh"], p_options["offset_mesh"], p_options["force_disable_mesh_compression"], nullptr); @@ -574,7 +567,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s String save_path = p_save_path + ".mesh"; - err = ResourceSaver::save(meshes.front()->get(), save_path); + err = ResourceSaver::save(meshes.front()->get()->get_mesh(), save_path); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Mesh to file '" + save_path + "'."); diff --git a/editor/import/resource_importer_obj.h b/editor/import/3d/resource_importer_obj.h index faf0f336c0..faf0f336c0 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/3d/resource_importer_obj.h diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp index 80dc3f194c..dfb14c6741 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/3d/resource_importer_scene.cpp @@ -35,7 +35,7 @@ #include "core/object/script_language.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" -#include "editor/import/scene_import_settings.h" +#include "editor/import/3d/scene_import_settings.h" #include "scene/3d/area_3d.h" #include "scene/3d/collision_shape_3d.h" #include "scene/3d/importer_mesh_instance_3d.h" @@ -2377,9 +2377,8 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashM ERR_FAIL_COND_V(!importer.is_valid(), nullptr); Error err = OK; - HashMap<StringName, Variant> options_dupe = p_options; - Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS | EditorSceneFormatImporter::IMPORT_FORCE_DISABLE_MESH_COMPRESSION, options_dupe, nullptr, &err); + Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS | EditorSceneFormatImporter::IMPORT_FORCE_DISABLE_MESH_COMPRESSION, p_options, nullptr, &err); if (!scene || err != OK) { return nullptr; } diff --git a/editor/import/resource_importer_scene.h b/editor/import/3d/resource_importer_scene.h index 6ea4d1af7d..6ea4d1af7d 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/3d/resource_importer_scene.h diff --git a/editor/import/scene_import_settings.cpp b/editor/import/3d/scene_import_settings.cpp index 4ecc6dedbd..736f941aa4 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/3d/scene_import_settings.cpp @@ -34,10 +34,10 @@ #include "editor/editor_file_system.h" #include "editor/editor_inspector.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/importer_mesh.h" diff --git a/editor/import/scene_import_settings.h b/editor/import/3d/scene_import_settings.h index 3e71d5da17..c6c416daba 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/3d/scene_import_settings.h @@ -31,7 +31,7 @@ #ifndef SCENE_IMPORT_SETTINGS_H #define SCENE_IMPORT_SETTINGS_H -#include "editor/import/resource_importer_scene.h" +#include "editor/import/3d/resource_importer_scene.h" #include "scene/3d/camera_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/mesh_instance_3d.h" diff --git a/editor/import/SCsub b/editor/import/SCsub index 359d04e5df..a8c06cc406 100644 --- a/editor/import/SCsub +++ b/editor/import/SCsub @@ -3,3 +3,4 @@ Import("env") env.add_source_files(env.editor_sources, "*.cpp") +env.add_source_files(env.editor_sources, "3d/*.cpp") diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp index 5414c6e74b..a62ac97244 100644 --- a/editor/import/audio_stream_import_settings.cpp +++ b/editor/import/audio_stream_import_settings.cpp @@ -31,8 +31,8 @@ #include "audio_stream_import_settings.h" #include "editor/audio_stream_preview.h" #include "editor/editor_file_system.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_box.h" AudioStreamImportSettingsDialog *AudioStreamImportSettingsDialog::singleton = nullptr; @@ -277,6 +277,8 @@ void AudioStreamImportSettingsDialog::_draw_indicator() { rect.size.height -= y_ofs; } + _current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /"); + float ofs_x = (_current - zoom_bar->get_value()) * rect.size.width / zoom_bar->get_page(); if (ofs_x < 0 || ofs_x >= rect.size.width) { return; @@ -310,8 +312,6 @@ void AudioStreamImportSettingsDialog::_draw_indicator() { } } } - - _current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /"); } void AudioStreamImportSettingsDialog::_on_indicator_mouse_exited() { diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 5564726594..5e6ed02de9 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -36,10 +36,10 @@ #include "editor/editor_locale_dialog.h" #include "editor/editor_node.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" /*************************************************************************/ /* Settings data */ @@ -1345,6 +1345,7 @@ DynamicFontImportSettingsDialog::DynamicFontImportSettingsDialog() { page2_description->set_text(TTR("Add font size, and variation coordinates, and select glyphs to pre-render:")); page2_description->set_h_size_flags(Control::SIZE_EXPAND_FILL); page2_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); + page2_description->set_custom_minimum_size(Size2(300 * EDSCALE, 1)); page2_vb->add_child(page2_description); HSplitContainer *page2_hb = memnew(HSplitContainer); @@ -1418,6 +1419,7 @@ DynamicFontImportSettingsDialog::DynamicFontImportSettingsDialog() { page2_0_description->set_text(TTR("Select translations to add all required glyphs to pre-render list:")); page2_0_description->set_h_size_flags(Control::SIZE_EXPAND_FILL); page2_0_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); + page2_0_description->set_custom_minimum_size(Size2(300 * EDSCALE, 1)); page2_0_vb->add_child(page2_0_description); locale_tree = memnew(Tree); @@ -1449,6 +1451,7 @@ DynamicFontImportSettingsDialog::DynamicFontImportSettingsDialog() { page2_1_description->set_text(TTR("Enter a text and select OpenType features to shape and add all required glyphs to pre-render list:")); page2_1_description->set_h_size_flags(Control::SIZE_EXPAND_FILL); page2_1_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); + page2_1_description->set_custom_minimum_size(Size2(300 * EDSCALE, 1)); page2_1_vb->add_child(page2_1_description); HSplitContainer *page2_1_hb = memnew(HSplitContainer); @@ -1486,6 +1489,7 @@ DynamicFontImportSettingsDialog::DynamicFontImportSettingsDialog() { page2_2_description->set_text(TTR("Add or remove glyphs from the character map to pre-render list:\nNote: Some stylistic alternatives and glyph variants do not have one-to-one correspondence to character, and not shown in this map, use \"Glyphs from the text\" tab to add these.")); page2_2_description->set_h_size_flags(Control::SIZE_EXPAND_FILL); page2_2_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); + page2_2_description->set_custom_minimum_size(Size2(300 * EDSCALE, 1)); page2_2_vb->add_child(page2_2_description); HSplitContainer *glyphs_split = memnew(HSplitContainer); diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp index 7afce116b8..3243dcf256 100644 --- a/editor/import/editor_import_plugin.cpp +++ b/editor/import/editor_import_plugin.cpp @@ -186,6 +186,15 @@ Error EditorImportPlugin::import(const String &p_source_file, const String &p_sa ERR_FAIL_V_MSG(ERR_METHOD_NOT_FOUND, "Unimplemented _import in add-on."); } +bool EditorImportPlugin::can_import_threaded() const { + bool ret = false; + if (GDVIRTUAL_CALL(_can_import_threaded, ret)) { + return ret; + } else { + return ResourceImporter::can_import_threaded(); + } +} + Error EditorImportPlugin::_append_import_external_resource(const String &p_file, const Dictionary &p_custom_options, const String &p_custom_importer, Variant p_generator_parameters) { HashMap<StringName, Variant> options; List<Variant> keys; @@ -213,5 +222,6 @@ void EditorImportPlugin::_bind_methods() { GDVIRTUAL_BIND(_get_import_order) GDVIRTUAL_BIND(_get_option_visibility, "path", "option_name", "options") GDVIRTUAL_BIND(_import, "source_file", "save_path", "options", "platform_variants", "gen_files"); + GDVIRTUAL_BIND(_can_import_threaded); ClassDB::bind_method(D_METHOD("append_import_external_resource", "path", "custom_options", "custom_importer", "generator_parameters"), &EditorImportPlugin::_append_import_external_resource, DEFVAL(Dictionary()), DEFVAL(String()), DEFVAL(Variant())); } diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index fb164c7f15..ea5cfc2682 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -52,6 +52,7 @@ protected: GDVIRTUAL0RC(int, _get_import_order) GDVIRTUAL3RC(bool, _get_option_visibility, String, StringName, Dictionary) GDVIRTUAL5RC(Error, _import, String, String, Dictionary, TypedArray<String>, TypedArray<String>) + GDVIRTUAL0RC(bool, _can_import_threaded) Error _append_import_external_resource(const String &p_file, const Dictionary &p_custom_options = Dictionary(), const String &p_custom_importer = String(), Variant p_generator_parameters = Variant()); @@ -69,6 +70,7 @@ public: 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 HashMap<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata = nullptr) override; + virtual bool can_import_threaded() const override; Error append_import_external_resource(const String &p_file, const HashMap<StringName, Variant> &p_custom_options = HashMap<StringName, Variant>(), const String &p_custom_importer = String(), Variant p_generator_parameters = Variant()); }; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 7f27be99f7..cdfc85cf6f 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -36,10 +36,10 @@ #include "core/version.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/gui/editor_toaster.h" #include "editor/import/resource_importer_texture_settings.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/compressed_texture.h" void ResourceImporterTexture::_texture_reimport_roughness(const Ref<CompressedTexture2D> &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 5996b459a5..0ceece263c 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -33,10 +33,10 @@ #include "core/config/project_settings.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" class ImportDockParameters : public Object { GDCLASS(ImportDockParameters, Object); diff --git a/editor/input_event_configuration_dialog.cpp b/editor/input_event_configuration_dialog.cpp index db7922233e..0f483fcaef 100644 --- a/editor/input_event_configuration_dialog.cpp +++ b/editor/input_event_configuration_dialog.cpp @@ -30,9 +30,9 @@ #include "editor/input_event_configuration_dialog.h" #include "core/input/input_map.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/event_listener_line_edit.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_box.h" #include "scene/gui/line_edit.h" #include "scene/gui/option_button.h" diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 717aaf396f..e1640af47b 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -31,7 +31,6 @@ #include "inspector_dock.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" @@ -39,6 +38,7 @@ #include "editor/gui/editor_file_dialog.h" #include "editor/gui/editor_object_selector.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" InspectorDock *InspectorDock::singleton = nullptr; @@ -139,8 +139,8 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { } } + unique_resources_list_tree->clear(); if (resource_propnames.size()) { - unique_resources_list_tree->clear(); TreeItem *root = unique_resources_list_tree->create_item(); for (int i = 0; i < resource_propnames.size(); i++) { @@ -461,15 +461,6 @@ void InspectorDock::_notification(int p_what) { } void InspectorDock::_bind_methods() { - ClassDB::bind_method("_unref_resource", &InspectorDock::_unref_resource); - ClassDB::bind_method("_paste_resource", &InspectorDock::_paste_resource); - ClassDB::bind_method("_copy_resource", &InspectorDock::_copy_resource); - - ClassDB::bind_method("_menu_collapseall", &InspectorDock::_menu_collapseall); - ClassDB::bind_method("_menu_expandall", &InspectorDock::_menu_expandall); - - ClassDB::bind_method("edit_resource", &InspectorDock::edit_resource); - ClassDB::bind_method("store_script_properties", &InspectorDock::store_script_properties); ClassDB::bind_method("apply_script_properties", &InspectorDock::apply_script_properties); diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index fb34740318..8bdd5a3102 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -32,12 +32,12 @@ #include "core/config/project_settings.h" #include "core/string/translation.h" -#include "editor/editor_scale.h" #include "editor/editor_translation_parser.h" #include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" #include "editor/gui/editor_file_dialog.h" #include "editor/pot_generator.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/control.h" void LocalizationEditor::_notification(int p_what) { @@ -189,7 +189,7 @@ void LocalizationEditor::_translation_res_select() { if (updating_translations) { return; } - call_deferred(SNAME("update_translations")); + callable_mp(this, &LocalizationEditor::update_translations).call_deferred(); } void LocalizationEditor::_translation_res_option_popup(bool p_arrow_clicked) { @@ -545,7 +545,7 @@ void LocalizationEditor::update_translations() { PackedStringArray selected = remaps[keys[i]]; for (int j = 0; j < selected.size(); j++) { - String s2 = selected[j]; + const String &s2 = selected[j]; int qp = s2.rfind(":"); String path = s2.substr(0, qp); String locale = s2.substr(qp + 1, s2.length()); diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index db4f5a67e5..1e564f96c0 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -30,9 +30,9 @@ #include "node_dock.h" -#include "connections_dialog.h" +#include "editor/connections_dialog.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" void NodeDock::show_groups() { groups_button->set_pressed(true); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 041a121a3a..5c2c059c98 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -35,9 +35,9 @@ #include "core/object/script_language.h" #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "editor/editor_scale.h" #include "editor/gui/editor_validation_panel.h" #include "editor/project_settings_editor.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/grid_container.h" void PluginConfigDialog::_clear_fields() { diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index a15875fd93..2c86314ae2 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -34,10 +34,10 @@ #include "core/math/geometry_2d.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/gui/dialogs.h" #include "scene/gui/separator.h" diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index ed1df4b07f..5875b46c19 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -32,11 +32,11 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/animation/animation_blend_tree.h" #include "scene/gui/button.h" #include "scene/gui/check_box.h" diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 057170098d..9d922f4608 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -36,11 +36,11 @@ #include "core/math/geometry_2d.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/button.h" diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 4a17fd89ff..8786c4cb20 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -36,11 +36,12 @@ #include "core/os/keyboard.h" #include "editor/editor_inspector.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" +#include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/gui/check_box.h" #include "scene/gui/menu_button.h" @@ -623,6 +624,111 @@ void AnimationNodeBlendTreeEditor::_filter_edited() { updating = false; } +void AnimationNodeBlendTreeEditor::_filter_fill_selection() { + TreeItem *ti = filters->get_root(); + if (!ti) { + return; + } + + updating = true; + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Fill Selected Filter Children")); + + _filter_fill_selection_recursive(undo_redo, ti, false); + + undo_redo->add_do_method(this, "_update_filters", _filter_edit); + undo_redo->add_undo_method(this, "_update_filters", _filter_edit); + undo_redo->commit_action(); + updating = false; + + _update_filters(_filter_edit); +} + +void AnimationNodeBlendTreeEditor::_filter_invert_selection() { + TreeItem *ti = filters->get_root(); + if (!ti) { + return; + } + + updating = true; + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Invert Filter Selection")); + + _filter_invert_selection_recursive(undo_redo, ti); + + undo_redo->add_do_method(this, "_update_filters", _filter_edit); + undo_redo->add_undo_method(this, "_update_filters", _filter_edit); + undo_redo->commit_action(); + updating = false; + + _update_filters(_filter_edit); +} + +void AnimationNodeBlendTreeEditor::_filter_clear_selection() { + TreeItem *ti = filters->get_root(); + if (!ti) { + return; + } + + updating = true; + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Clear Filter Selection")); + + _filter_clear_selection_recursive(undo_redo, ti); + + undo_redo->add_do_method(this, "_update_filters", _filter_edit); + undo_redo->add_undo_method(this, "_update_filters", _filter_edit); + undo_redo->commit_action(); + updating = false; + + _update_filters(_filter_edit); +} + +void AnimationNodeBlendTreeEditor::_filter_fill_selection_recursive(EditorUndoRedoManager *p_undo_redo, TreeItem *p_item, bool p_parent_filtered) { + TreeItem *ti = p_item->get_first_child(); + bool parent_filtered = p_parent_filtered; + while (ti) { + NodePath item_path = ti->get_metadata(0); + bool filtered = _filter_edit->is_path_filtered(item_path); + parent_filtered |= filtered; + + p_undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_path", item_path, parent_filtered); + p_undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_path", item_path, filtered); + + _filter_fill_selection_recursive(p_undo_redo, ti, parent_filtered); + ti = ti->get_next(); + parent_filtered = p_parent_filtered; + } +} + +void AnimationNodeBlendTreeEditor::_filter_invert_selection_recursive(EditorUndoRedoManager *p_undo_redo, TreeItem *p_item) { + TreeItem *ti = p_item->get_first_child(); + while (ti) { + NodePath item_path = ti->get_metadata(0); + bool filtered = _filter_edit->is_path_filtered(item_path); + + p_undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_path", item_path, !filtered); + p_undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_path", item_path, filtered); + + _filter_invert_selection_recursive(p_undo_redo, ti); + ti = ti->get_next(); + } +} + +void AnimationNodeBlendTreeEditor::_filter_clear_selection_recursive(EditorUndoRedoManager *p_undo_redo, TreeItem *p_item) { + TreeItem *ti = p_item->get_first_child(); + while (ti) { + NodePath item_path = ti->get_metadata(0); + bool filtered = _filter_edit->is_path_filtered(item_path); + + p_undo_redo->add_do_method(_filter_edit.ptr(), "set_filter_path", item_path, false); + p_undo_redo->add_undo_method(_filter_edit.ptr(), "set_filter_path", item_path, filtered); + + _filter_clear_selection_recursive(p_undo_redo, ti); + ti = ti->get_next(); + } +} + bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &anode) { if (updating || _filter_edit != anode) { return false; @@ -1121,10 +1227,28 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { VBoxContainer *filter_vbox = memnew(VBoxContainer); filter_dialog->add_child(filter_vbox); + HBoxContainer *filter_hbox = memnew(HBoxContainer); + filter_vbox->add_child(filter_hbox); + filter_enabled = memnew(CheckBox); filter_enabled->set_text(TTR("Enable Filtering")); filter_enabled->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_filter_toggled)); - filter_vbox->add_child(filter_enabled); + filter_hbox->add_child(filter_enabled); + + filter_fill_selection = memnew(Button); + filter_fill_selection->set_text(TTR("Fill Selected Children")); + filter_fill_selection->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_filter_fill_selection)); + filter_hbox->add_child(filter_fill_selection); + + filter_invert_selection = memnew(Button); + filter_invert_selection->set_text(TTR("Invert")); + filter_invert_selection->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_filter_invert_selection)); + filter_hbox->add_child(filter_invert_selection); + + filter_clear_selection = memnew(Button); + filter_clear_selection->set_text(TTR("Clear")); + filter_clear_selection->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_filter_clear_selection)); + filter_hbox->add_child(filter_clear_selection); filters = memnew(Tree); filter_vbox->add_child(filters); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index 1f7a33e02a..690b127938 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -66,6 +66,9 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { AcceptDialog *filter_dialog = nullptr; Tree *filters = nullptr; CheckBox *filter_enabled = nullptr; + Button *filter_fill_selection = nullptr; + Button *filter_invert_selection = nullptr; + Button *filter_clear_selection = nullptr; HashMap<StringName, ProgressBar *> animations; Vector<EditorProperty *> visible_properties; @@ -116,6 +119,12 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _inspect_filters(const String &p_which); void _filter_edited(); void _filter_toggled(); + void _filter_fill_selection(); + void _filter_invert_selection(); + void _filter_clear_selection(); + void _filter_fill_selection_recursive(EditorUndoRedoManager *p_undo_redo, TreeItem *p_item, bool p_parent_filtered); + void _filter_invert_selection_recursive(EditorUndoRedoManager *p_undo_redo, TreeItem *p_item); + void _filter_clear_selection_recursive(EditorUndoRedoManager *p_undo_redo, TreeItem *p_item); Ref<AnimationNode> _filter_edit; void _popup(bool p_has_input_ports, const Vector2 &p_node_position); diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp index e3b2154e37..58b1dbde8a 100644 --- a/editor/plugins/animation_library_editor.cpp +++ b/editor/plugins/animation_library_editor.cpp @@ -30,11 +30,11 @@ #include "animation_library_editor.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/animation/animation_mixer.h" void AnimationLibraryEditor::set_animation_mixer(Object *p_mixer) { @@ -137,7 +137,7 @@ void AnimationLibraryEditor::_load_library() { file_dialog->add_filter("*." + K); } - file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); file_dialog->set_current_file(""); file_dialog->popup_centered_ratio(); @@ -299,85 +299,9 @@ void AnimationLibraryEditor::_file_popup_selected(int p_id) { } break; } } + void AnimationLibraryEditor::_load_file(String p_path) { switch (file_dialog_action) { - case FILE_DIALOG_ACTION_OPEN_LIBRARY: { - Ref<AnimationLibrary> al = ResourceLoader::load(p_path); - if (al.is_null()) { - error_dialog->set_text(TTR("Invalid AnimationLibrary file.")); - error_dialog->popup_centered(); - return; - } - - List<StringName> libs; - mixer->get_animation_library_list(&libs); - for (const StringName &K : libs) { - Ref<AnimationLibrary> al2 = mixer->get_animation_library(K); - if (al2 == al) { - error_dialog->set_text(TTR("This library is already added to the mixer.")); - error_dialog->popup_centered(); - - return; - } - } - - String name = AnimationLibrary::validate_library_name(p_path.get_file().get_basename()); - - int attempt = 1; - - while (bool(mixer->has_animation_library(name))) { - attempt++; - name = p_path.get_file().get_basename() + " " + itos(attempt); - } - - EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - - undo_redo->create_action(vformat(TTR("Add Animation Library: %s"), name)); - undo_redo->add_do_method(mixer, "add_animation_library", name, al); - undo_redo->add_undo_method(mixer, "remove_animation_library", name); - undo_redo->add_do_method(this, "_update_editor", mixer); - undo_redo->add_undo_method(this, "_update_editor", mixer); - undo_redo->commit_action(); - } break; - case FILE_DIALOG_ACTION_OPEN_ANIMATION: { - Ref<Animation> anim = ResourceLoader::load(p_path); - if (anim.is_null()) { - error_dialog->set_text(TTR("Invalid Animation file.")); - error_dialog->popup_centered(); - return; - } - - Ref<AnimationLibrary> al = mixer->get_animation_library(adding_animation_to_library); - List<StringName> anims; - al->get_animation_list(&anims); - for (const StringName &K : anims) { - Ref<Animation> a2 = al->get_animation(K); - if (a2 == anim) { - error_dialog->set_text(TTR("This animation is already added to the library.")); - error_dialog->popup_centered(); - return; - } - } - - String name = p_path.get_file().get_basename(); - - int attempt = 1; - - while (al->has_animation(name)) { - attempt++; - name = p_path.get_file().get_basename() + " " + itos(attempt); - } - - EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - - undo_redo->create_action(vformat(TTR("Load Animation into Library: %s"), name)); - undo_redo->add_do_method(al.ptr(), "add_animation", name, anim); - undo_redo->add_undo_method(al.ptr(), "remove_animation", name); - undo_redo->add_do_method(this, "_update_editor", mixer); - undo_redo->add_undo_method(this, "_update_editor", mixer); - undo_redo->commit_action(); - } break; - case FILE_DIALOG_ACTION_SAVE_LIBRARY: { Ref<AnimationLibrary> al = mixer->get_animation_library(file_dialog_library); String prev_path = al->get_path(); @@ -415,6 +339,121 @@ void AnimationLibraryEditor::_load_file(String p_path) { undo_redo->commit_action(); } } break; + default: { + } + } +} + +void AnimationLibraryEditor::_load_files(const PackedStringArray &p_paths) { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + bool has_created_action = false; + bool show_error_diag = false; + List<String> name_list; + + switch (file_dialog_action) { + case FILE_DIALOG_ACTION_OPEN_LIBRARY: { + for (const String &path : p_paths) { + Ref<AnimationLibrary> al = ResourceLoader::load(path); + if (al.is_null()) { + show_error_diag = true; + error_dialog->set_text(TTR("Some AnimationLibrary files were invalid.")); + continue; + } + + List<StringName> libs; + mixer->get_animation_library_list(&libs); + bool is_already_added = false; + for (const StringName &K : libs) { + if (mixer->get_animation_library(K) == al) { + // Prioritize the "invalid" error message. + if (!show_error_diag) { + show_error_diag = true; + error_dialog->set_text(TTR("Some of the selected libraries were already added to the mixer.")); + } + + is_already_added = true; + break; + } + } + + if (is_already_added) { + continue; + } + + String name = AnimationLibrary::validate_library_name(path.get_file().get_basename()); + int attempt = 1; + while (bool(mixer->has_animation_library(name)) || name_list.find(name)) { + attempt++; + name = path.get_file().get_basename() + " " + itos(attempt); + } + name_list.push_back(name); + + if (!has_created_action) { + has_created_action = true; + undo_redo->create_action(p_paths.size() > 1 ? TTR("Add Animation Libraries") : vformat(TTR("Add Animation Library: %s"), name)); + } + undo_redo->add_do_method(mixer, "add_animation_library", name, al); + undo_redo->add_undo_method(mixer, "remove_animation_library", name); + } + } break; + case FILE_DIALOG_ACTION_OPEN_ANIMATION: { + Ref<AnimationLibrary> al = mixer->get_animation_library(adding_animation_to_library); + for (const String &path : p_paths) { + Ref<Animation> anim = ResourceLoader::load(path); + if (anim.is_null()) { + show_error_diag = true; + error_dialog->set_text(TTR("Some Animation files were invalid.")); + continue; + } + + List<StringName> anims; + al->get_animation_list(&anims); + bool is_already_added = false; + for (const StringName &K : anims) { + if (al->get_animation(K) == anim) { + // Prioritize the "invalid" error message. + if (!show_error_diag) { + show_error_diag = true; + error_dialog->set_text(TTR("Some of the selected animations were already added to the library.")); + } + + is_already_added = true; + break; + } + } + + if (is_already_added) { + continue; + } + + String name = path.get_file().get_basename(); + int attempt = 1; + while (al->has_animation(name) || name_list.find(name)) { + attempt++; + name = path.get_file().get_basename() + " " + itos(attempt); + } + name_list.push_back(name); + + if (!has_created_action) { + has_created_action = true; + undo_redo->create_action(p_paths.size() > 1 ? TTR("Load Animations into Library") : vformat(TTR("Load Animation into Library: %s"), name)); + } + undo_redo->add_do_method(al.ptr(), "add_animation", name, anim); + undo_redo->add_undo_method(al.ptr(), "remove_animation", name); + } + } break; + default: { + } + } + + if (has_created_action) { + undo_redo->add_do_method(this, "_update_editor", mixer); + undo_redo->add_undo_method(this, "_update_editor", mixer); + undo_redo->commit_action(); + } + + if (show_error_diag) { + error_dialog->popup_centered(); } } @@ -506,7 +545,7 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int } file_dialog->set_title(TTR("Load Animation")); - file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); file_dialog->set_current_file(""); file_dialog->popup_centered_ratio(); @@ -673,12 +712,12 @@ void AnimationLibraryEditor::update_tree() { libitem->set_metadata(0, K); libitem->set_icon(0, get_editor_theme_icon("AnimationLibrary")); - libitem->add_button(0, get_editor_theme_icon("Add"), LIB_BUTTON_ADD, animation_library_is_foreign, TTR("Add Animation to Library")); - libitem->add_button(0, get_editor_theme_icon("Load"), LIB_BUTTON_LOAD, animation_library_is_foreign, TTR("Load animation from file and add to library")); - libitem->add_button(0, get_editor_theme_icon("ActionPaste"), LIB_BUTTON_PASTE, animation_library_is_foreign, TTR("Paste Animation to Library from clipboard")); + libitem->add_button(0, get_editor_theme_icon("Add"), LIB_BUTTON_ADD, animation_library_is_foreign, TTR("Add animation to library.")); + libitem->add_button(0, get_editor_theme_icon("Load"), LIB_BUTTON_LOAD, animation_library_is_foreign, TTR("Load animation from file and add to library.")); + libitem->add_button(0, get_editor_theme_icon("ActionPaste"), LIB_BUTTON_PASTE, animation_library_is_foreign, TTR("Paste animation to library from clipboard.")); - libitem->add_button(1, get_editor_theme_icon("Save"), LIB_BUTTON_FILE, false, TTR("Save animation library to resource on disk")); - libitem->add_button(1, get_editor_theme_icon("Remove"), LIB_BUTTON_DELETE, false, TTR("Remove animation library")); + libitem->add_button(1, get_editor_theme_icon("Save"), LIB_BUTTON_FILE, false, TTR("Save animation library to resource on disk.")); + libitem->add_button(1, get_editor_theme_icon("Remove"), LIB_BUTTON_DELETE, false, TTR("Remove animation library.")); libitem->set_custom_bg_color(0, ss_color); @@ -690,7 +729,7 @@ void AnimationLibraryEditor::update_tree() { anitem->set_editable(0, !animation_library_is_foreign); anitem->set_metadata(0, L); anitem->set_icon(0, get_editor_theme_icon("Animation")); - anitem->add_button(0, get_editor_theme_icon("ActionCopy"), ANIM_BUTTON_COPY, animation_library_is_foreign, TTR("Copy animation to clipboard")); + anitem->add_button(0, get_editor_theme_icon("ActionCopy"), ANIM_BUTTON_COPY, animation_library_is_foreign, TTR("Copy animation to clipboard.")); Ref<Animation> anim = al->get_animation(L); String anim_path = anim->get_path(); @@ -717,8 +756,8 @@ void AnimationLibraryEditor::update_tree() { anitem->set_text(1, anim_path.get_file()); } } - anitem->add_button(1, get_editor_theme_icon("Save"), ANIM_BUTTON_FILE, animation_library_is_foreign, TTR("Save animation to resource on disk")); - anitem->add_button(1, get_editor_theme_icon("Remove"), ANIM_BUTTON_DELETE, animation_library_is_foreign, TTR("Remove animation from Library")); + anitem->add_button(1, get_editor_theme_icon("Save"), ANIM_BUTTON_FILE, animation_library_is_foreign, TTR("Save animation to resource on disk.")); + anitem->add_button(1, get_editor_theme_icon("Remove"), ANIM_BUTTON_DELETE, animation_library_is_foreign, TTR("Remove animation from Library.")); } } } @@ -728,6 +767,15 @@ void AnimationLibraryEditor::show_dialog() { popup_centered_ratio(0.5); } +void AnimationLibraryEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + new_library_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + load_library_button->set_icon(get_editor_theme_icon(SNAME("Load"))); + } + } +} + void AnimationLibraryEditor::_update_editor(Object *p_mixer) { emit_signal("update_editor", p_mixer); } @@ -743,6 +791,7 @@ AnimationLibraryEditor::AnimationLibraryEditor() { file_dialog = memnew(EditorFileDialog); add_child(file_dialog); file_dialog->connect("file_selected", callable_mp(this, &AnimationLibraryEditor::_load_file)); + file_dialog->connect("files_selected", callable_mp(this, &AnimationLibraryEditor::_load_files)); add_library_dialog = memnew(ConfirmationDialog); VBoxContainer *dialog_vb = memnew(VBoxContainer); @@ -760,12 +809,14 @@ AnimationLibraryEditor::AnimationLibraryEditor() { VBoxContainer *vb = memnew(VBoxContainer); HBoxContainer *hb = memnew(HBoxContainer); hb->add_spacer(true); - Button *b = memnew(Button(TTR("Add Library"))); - b->connect("pressed", callable_mp(this, &AnimationLibraryEditor::_add_library)); - hb->add_child(b); - b = memnew(Button(TTR("Load Library"))); - b->connect("pressed", callable_mp(this, &AnimationLibraryEditor::_load_library)); - hb->add_child(b); + new_library_button = memnew(Button(TTR("New Library"))); + new_library_button->set_tooltip_text(TTR("Create new empty animation library.")); + new_library_button->connect("pressed", callable_mp(this, &AnimationLibraryEditor::_add_library)); + hb->add_child(new_library_button); + load_library_button = memnew(Button(TTR("Load Library"))); + load_library_button->set_tooltip_text(TTR("Load animation library from disk.")); + load_library_button->connect("pressed", callable_mp(this, &AnimationLibraryEditor::_load_library)); + hb->add_child(load_library_button); vb->add_child(hb); tree = memnew(Tree); vb->add_child(tree); diff --git a/editor/plugins/animation_library_editor.h b/editor/plugins/animation_library_editor.h index b656642a7c..c003e9a10b 100644 --- a/editor/plugins/animation_library_editor.h +++ b/editor/plugins/animation_library_editor.h @@ -80,6 +80,9 @@ class AnimationLibraryEditor : public AcceptDialog { StringName file_dialog_animation; StringName file_dialog_library; + Button *new_library_button = nullptr; + Button *load_library_button = nullptr; + AcceptDialog *error_dialog = nullptr; bool adding_animation = false; StringName adding_animation_to_library; @@ -98,6 +101,7 @@ class AnimationLibraryEditor : public AcceptDialog { void _add_library_confirm(); void _load_library(); void _load_file(String p_path); + void _load_files(const PackedStringArray &p_paths); void _item_renamed(); void _button_pressed(TreeItem *p_item, int p_column, int p_id, MouseButton p_button); @@ -107,6 +111,7 @@ class AnimationLibraryEditor : public AcceptDialog { bool updating = false; protected: + void _notification(int p_what); void _update_editor(Object *p_mixer); static void _bind_methods(); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 84251e1476..b08d2e966d 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -36,7 +36,6 @@ #include "core/io/resource_saver.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" @@ -44,6 +43,7 @@ #include "editor/plugins/canvas_item_editor_plugin.h" // For onion skinning. #include "editor/plugins/node_3d_editor_plugin.h" // For onion skinning. #include "editor/scene_tree_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/animation/animation_tree.h" #include "scene/gui/separator.h" #include "scene/main/window.h" @@ -2139,7 +2139,7 @@ void AnimationPlayerEditorPlugin::_clear_dummy_player() { } Node *parent = dummy_player->get_parent(); if (parent) { - parent->call_deferred("remove_child", dummy_player); + callable_mp(parent, &Node::remove_child).call_deferred(dummy_player); } dummy_player->queue_free(); dummy_player = nullptr; diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index e9c8b0c610..bbfc1f2f99 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -36,10 +36,10 @@ #include "core/math/geometry_2d.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" @@ -203,7 +203,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } if (node_rects[i].edit.has_point(mb->get_position())) { //edit name - call_deferred(SNAME("_open_editor"), node_rects[i].node_name); + callable_mp(this, &AnimationNodeStateMachineEditor::_open_editor).call_deferred(node_rects[i].node_name); return; } @@ -1610,12 +1610,6 @@ void AnimationNodeStateMachineEditor::_update_mode() { void AnimationNodeStateMachineEditor::_bind_methods() { ClassDB::bind_method("_update_graph", &AnimationNodeStateMachineEditor::_update_graph); - ClassDB::bind_method("_open_editor", &AnimationNodeStateMachineEditor::_open_editor); - ClassDB::bind_method("_connect_to", &AnimationNodeStateMachineEditor::_connect_to); - ClassDB::bind_method("_stop_connecting", &AnimationNodeStateMachineEditor::_stop_connecting); - ClassDB::bind_method("_delete_selected", &AnimationNodeStateMachineEditor::_delete_selected); - ClassDB::bind_method("_delete_all", &AnimationNodeStateMachineEditor::_delete_all); - ClassDB::bind_method("_delete_tree_draw", &AnimationNodeStateMachineEditor::_delete_tree_draw); BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, AnimationNodeStateMachineEditor, panel_style, "panel", "GraphStateMachine"); BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, AnimationNodeStateMachineEditor, error_panel_style, "error_panel", "GraphStateMachine"); diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index efee22a9a9..7269395baf 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -40,8 +40,8 @@ #include "core/math/delaunay_2d.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/button.h" diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 36a0b46d92..2012955686 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -37,11 +37,11 @@ #include "core/version.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" #include "editor/project_settings_editor.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/menu_button.h" #include "scene/resources/image_texture.h" @@ -417,7 +417,6 @@ void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asse void EditorAssetLibraryItemDownload::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("AssetLib"))); status->add_theme_color_override("font_color", get_theme_color(SNAME("status_color"), SNAME("AssetLib"))); diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index 2be9528019..9b3f24c625 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -31,9 +31,9 @@ #include "audio_stream_editor_plugin.h" #include "editor/audio_stream_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/audio_stream_wav.h" // AudioStreamEditor diff --git a/editor/plugins/bit_map_editor_plugin.cpp b/editor/plugins/bit_map_editor_plugin.cpp index f2423cb803..f1d86de537 100644 --- a/editor/plugins/bit_map_editor_plugin.cpp +++ b/editor/plugins/bit_map_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "bit_map_editor_plugin.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/label.h" #include "scene/gui/texture_rect.h" #include "scene/resources/image_texture.h" diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp index db61c95474..38573fbaa7 100644 --- a/editor/plugins/bone_map_editor_plugin.cpp +++ b/editor/plugins/bone_map_editor_plugin.cpp @@ -30,12 +30,12 @@ #include "bone_map_editor_plugin.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" -#include "editor/import/post_import_plugin_skeleton_renamer.h" -#include "editor/import/post_import_plugin_skeleton_rest_fixer.h" -#include "editor/import/post_import_plugin_skeleton_track_organizer.h" -#include "editor/import/scene_import_settings.h" +#include "editor/import/3d/post_import_plugin_skeleton_renamer.h" +#include "editor/import/3d/post_import_plugin_skeleton_rest_fixer.h" +#include "editor/import/3d/post_import_plugin_skeleton_track_organizer.h" +#include "editor/import/3d/scene_import_settings.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/aspect_ratio_container.h" #include "scene/gui/separator.h" #include "scene/gui/texture_rect.h" @@ -95,7 +95,7 @@ void BoneMapperButton::_notification(int p_what) { } } -BoneMapperButton::BoneMapperButton(const StringName p_profile_bone_name, bool p_require, bool p_selected) { +BoneMapperButton::BoneMapperButton(const StringName &p_profile_bone_name, bool p_require, bool p_selected) { profile_bone_name = p_profile_bone_name; require = p_require; selected = p_selected; diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h index 9ff32707c7..9479ed3730 100644 --- a/editor/plugins/bone_map_editor_plugin.h +++ b/editor/plugins/bone_map_editor_plugin.h @@ -78,7 +78,7 @@ public: bool is_require() const; - BoneMapperButton(const StringName p_profile_bone_name, bool p_require, bool p_selected); + BoneMapperButton(const StringName &p_profile_bone_name, bool p_require, bool p_selected); ~BoneMapperButton(); }; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index bac2a4909f..6c776ad9b3 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -35,7 +35,6 @@ #include "core/os/keyboard.h" #include "editor/debugger/editor_debugger_node.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" @@ -45,6 +44,7 @@ #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/scene_tree_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/polygon_2d.h" #include "scene/2d/skeleton_2d.h" #include "scene/2d/sprite_2d.h" @@ -345,7 +345,7 @@ void CanvasItemEditor::_snap_other_nodes( } } -Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsigned int p_forced_modes, const CanvasItem *p_self_canvas_item, List<CanvasItem *> p_other_nodes_exceptions) { +Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsigned int p_forced_modes, const CanvasItem *p_self_canvas_item, const List<CanvasItem *> &p_other_nodes_exceptions) { snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; @@ -535,7 +535,7 @@ void CanvasItemEditor::_keying_changed() { } } -Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_list) { +Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(const List<CanvasItem *> &p_list) { ERR_FAIL_COND_V(p_list.is_empty(), Rect2()); // Handles the first element @@ -830,7 +830,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 return output; } -void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) { +void CanvasItemEditor::_save_canvas_item_state(const List<CanvasItem *> &p_canvas_items, bool save_bones) { original_transform = Transform2D(); bool transform_stored = false; @@ -853,14 +853,14 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items } } -void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) { +void CanvasItemEditor::_restore_canvas_item_state(const List<CanvasItem *> &p_canvas_items, bool restore_bones) { for (CanvasItem *ci : drag_selection) { CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(ci); ci->_edit_set_state(se->undo_state); } } -void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones) { +void CanvasItemEditor::_commit_canvas_item_state(const List<CanvasItem *> &p_canvas_items, String action_name, bool commit_bones) { List<CanvasItem *> modified_canvas_items; for (CanvasItem *ci : p_canvas_items) { Dictionary old_state = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(ci)->undo_state; @@ -976,7 +976,7 @@ void CanvasItemEditor::_node_created(Node *p_node) { c->_edit_set_position(xform.xform(node_create_position)); } - call_deferred(SNAME("_reset_create_position")); // Defer the call in case more than one node is added. + callable_mp(this, &CanvasItemEditor::_reset_create_position).call_deferred(); // Defer the call in case more than one node is added. } void CanvasItemEditor::_reset_create_position() { @@ -2014,14 +2014,14 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if ((b->is_alt_pressed() && !b->is_command_or_control_pressed()) || tool == TOOL_MOVE) { List<CanvasItem *> selection = _get_edited_canvas_items(); - drag_selection.clear(); - for (int i = 0; i < selection.size(); i++) { - if (_is_node_movable(selection[i], true)) { - drag_selection.push_back(selection[i]); + if (selection.size() > 0) { + drag_selection.clear(); + for (int i = 0; i < selection.size(); i++) { + if (_is_node_movable(selection[i], true)) { + drag_selection.push_back(selection[i]); + } } - } - if (selection.size() > 0) { drag_type = DRAG_MOVE; CanvasItem *ci = selection[0]; @@ -2043,8 +2043,9 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { drag_from = transform.affine_inverse().xform(b->get_position()); _save_canvas_item_state(drag_selection); + + return true; } - return true; } } } @@ -2344,7 +2345,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return true; } - if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && tool == TOOL_SELECT && !panner->is_panning()) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && !panner->is_panning() && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_SCALE || tool == TOOL_ROTATE)) { // Single item selection Point2 click = transform.affine_inverse().xform(b->get_position()); @@ -2379,7 +2380,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } else { bool still_selected = _select_click_on_item(ci, click, b->is_shift_pressed()); // Start dragging - if (still_selected) { + if (still_selected && (tool == TOOL_SELECT || tool == TOOL_MOVE)) { // Drag the node(s) if requested drag_start_origin = click; drag_type = DRAG_QUEUED; @@ -2463,7 +2464,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } } - if (k.is_valid() && k->is_action_pressed(SNAME("ui_cancel"), false, true) && drag_type == DRAG_NONE && tool == TOOL_SELECT) { + if (k.is_valid() && k->is_action_pressed(SNAME("ui_cancel"), false, true) && drag_type == DRAG_NONE) { // Unselect everything editor_selection->clear(); viewport->queue_redraw(); @@ -2609,7 +2610,7 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { // Grab focus if (!viewport->has_focus() && (!get_viewport()->gui_get_focus_owner() || !get_viewport()->gui_get_focus_owner()->is_text_field())) { - viewport->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)viewport, &Control::grab_focus).call_deferred(); } } @@ -3638,7 +3639,7 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans _draw_invisible_nodes_positions(p_node->get_child(i), parent_xform, canvas_xform); } - if (ci && !ci->_edit_use_rect() && (!editor_selection->is_selected(ci) || _is_node_locked(ci))) { + if (show_position_gizmos && ci && !ci->_edit_use_rect() && (!editor_selection->is_selected(ci) || _is_node_locked(ci))) { Transform2D xform = transform * canvas_xform * parent_xform; // Draw the node's position @@ -3775,13 +3776,13 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p real_t offset = 0; Ref<Texture2D> lock = get_editor_theme_icon(SNAME("LockViewport")); - if (p_node->has_meta("_edit_lock_") && show_edit_locks) { + if (show_lock_gizmos && p_node->has_meta("_edit_lock_")) { lock->draw(viewport_ci, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); offset += lock->get_size().x; } Ref<Texture2D> group = get_editor_theme_icon(SNAME("GroupViewport")); - if (ci->has_meta("_edit_group_") && show_edit_locks) { + if (show_group_gizmos && ci->has_meta("_edit_group_")) { group->draw(viewport_ci, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); //offset += group->get_size().x; } @@ -3910,6 +3911,11 @@ void CanvasItemEditor::_update_editor_settings() { void CanvasItemEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_READY: { + EditorRunBar::get_singleton()->connect("play_pressed", callable_mp(this, &CanvasItemEditor::_update_override_camera_button).bind(true)); + EditorRunBar::get_singleton()->connect("stop_pressed", callable_mp(this, &CanvasItemEditor::_update_override_camera_button).bind(false)); + } break; + case NOTIFICATION_PHYSICS_PROCESS: { EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels")); @@ -4289,16 +4295,28 @@ void CanvasItemEditor::_popup_callback(int p_op) { view_menu->get_popup()->set_item_checked(idx, show_viewport); viewport->queue_redraw(); } break; - case SHOW_EDIT_LOCKS: { - show_edit_locks = !show_edit_locks; - int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS); - view_menu->get_popup()->set_item_checked(idx, show_edit_locks); + case SHOW_POSITION_GIZMOS: { + show_position_gizmos = !show_position_gizmos; + int idx = gizmos_menu->get_item_index(SHOW_POSITION_GIZMOS); + gizmos_menu->set_item_checked(idx, show_position_gizmos); + viewport->queue_redraw(); + } break; + case SHOW_LOCK_GIZMOS: { + show_lock_gizmos = !show_lock_gizmos; + int idx = gizmos_menu->get_item_index(SHOW_LOCK_GIZMOS); + gizmos_menu->set_item_checked(idx, show_lock_gizmos); + viewport->queue_redraw(); + } break; + case SHOW_GROUP_GIZMOS: { + show_group_gizmos = !show_group_gizmos; + int idx = gizmos_menu->get_item_index(SHOW_GROUP_GIZMOS); + gizmos_menu->set_item_checked(idx, show_group_gizmos); viewport->queue_redraw(); } break; case SHOW_TRANSFORMATION_GIZMOS: { show_transformation_gizmos = !show_transformation_gizmos; - int idx = view_menu->get_popup()->get_item_index(SHOW_TRANSFORMATION_GIZMOS); - view_menu->get_popup()->set_item_checked(idx, show_transformation_gizmos); + int idx = gizmos_menu->get_item_index(SHOW_TRANSFORMATION_GIZMOS); + gizmos_menu->set_item_checked(idx, show_transformation_gizmos); viewport->queue_redraw(); } break; case SNAP_USE_NODE_PARENT: { @@ -4710,7 +4728,7 @@ void CanvasItemEditor::_focus_selection(int p_op) { zoom *= 0.90; zoom_widget->set_zoom(zoom); viewport->queue_redraw(); // Redraw to update the global canvas transform after zoom changes. - call_deferred(SNAME("center_at"), rect.get_center()); // Defer because the updated transform is needed. + callable_mp(this, &CanvasItemEditor::center_at).call_deferred(rect.get_center()); // Defer because the updated transform is needed. } else { center_at(rect.get_center()); } @@ -4759,7 +4777,9 @@ Dictionary CanvasItemEditor::get_state() const { state["show_guides"] = show_guides; state["show_helpers"] = show_helpers; state["show_zoom_control"] = zoom_widget->is_visible(); - state["show_edit_locks"] = show_edit_locks; + state["show_position_gizmos"] = show_position_gizmos; + state["show_lock_gizmos"] = show_lock_gizmos; + state["show_group_gizmos"] = show_group_gizmos; state["show_transformation_gizmos"] = show_transformation_gizmos; state["snap_rotation"] = snap_rotation; state["snap_scale"] = snap_scale; @@ -4896,16 +4916,28 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { view_menu->get_popup()->set_item_checked(idx, show_helpers); } - if (state.has("show_edit_locks")) { - show_edit_locks = state["show_edit_locks"]; - int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS); - view_menu->get_popup()->set_item_checked(idx, show_edit_locks); + if (state.has("show_position_gizmos")) { + show_position_gizmos = state["show_position_gizmos"]; + int idx = gizmos_menu->get_item_index(SHOW_POSITION_GIZMOS); + gizmos_menu->set_item_checked(idx, show_position_gizmos); + } + + if (state.has("show_lock_gizmos")) { + show_lock_gizmos = state["show_lock_gizmos"]; + int idx = gizmos_menu->get_item_index(SHOW_LOCK_GIZMOS); + gizmos_menu->set_item_checked(idx, show_lock_gizmos); + } + + if (state.has("show_group_gizmos")) { + show_group_gizmos = state["show_group_gizmos"]; + int idx = gizmos_menu->get_item_index(SHOW_GROUP_GIZMOS); + gizmos_menu->set_item_checked(idx, show_group_gizmos); } if (state.has("show_transformation_gizmos")) { show_transformation_gizmos = state["show_transformation_gizmos"]; - int idx = view_menu->get_popup()->get_item_index(SHOW_TRANSFORMATION_GIZMOS); - view_menu->get_popup()->set_item_checked(idx, show_transformation_gizmos); + int idx = gizmos_menu->get_item_index(SHOW_TRANSFORMATION_GIZMOS); + gizmos_menu->set_item_checked(idx, show_transformation_gizmos); } if (state.has("show_zoom_control")) { @@ -5053,9 +5085,6 @@ CanvasItemEditor::CanvasItemEditor() { SceneTreeDock::get_singleton()->connect("node_created", callable_mp(this, &CanvasItemEditor::_node_created)); SceneTreeDock::get_singleton()->connect("add_node_used", callable_mp(this, &CanvasItemEditor::_reset_create_position)); - EditorRunBar::get_singleton()->call_deferred(SNAME("connect"), "play_pressed", callable_mp(this, &CanvasItemEditor::_update_override_camera_button).bind(true)); - EditorRunBar::get_singleton()->call_deferred(SNAME("connect"), "stop_pressed", callable_mp(this, &CanvasItemEditor::_update_override_camera_button).bind(false)); - // Add some margin to the sides for better esthetics. // This prevents the first button's hover/pressed effect from "touching" the panel's border, // which looks ugly. @@ -5323,7 +5352,7 @@ CanvasItemEditor::CanvasItemEditor() { group_button->set_theme_type_variation("FlatButton"); main_menu_hbox->add_child(group_button); group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(GROUP_SELECTED)); - group_button->set_tooltip_text(TTR("Make selected node's children not selectable.")); + group_button->set_tooltip_text(TTR("Groups the selected node with its children. This causes the parent to be selected when any child node is clicked in 2D and 3D view.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | Key::G)); @@ -5331,7 +5360,7 @@ CanvasItemEditor::CanvasItemEditor() { ungroup_button->set_theme_type_variation("FlatButton"); main_menu_hbox->add_child(ungroup_button); ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNGROUP_SELECTED)); - ungroup_button->set_tooltip_text(TTR("Make selected node's children selectable.")); + ungroup_button->set_tooltip_text(TTR("Ungroups the selected node from its children. Child nodes will be individual items in 2D and 3D view.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::G)); @@ -5394,8 +5423,18 @@ CanvasItemEditor::CanvasItemEditor() { p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), Key::Y), SHOW_GUIDES); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_edit_locks", TTR("Show Group And Lock Icons")), SHOW_EDIT_LOCKS); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_transformation_gizmos", TTR("Show Transformation Gizmos")), SHOW_TRANSFORMATION_GIZMOS); + p->add_separator(); + + gizmos_menu = memnew(PopupMenu); + gizmos_menu->set_name("GizmosMenu"); + gizmos_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback)); + gizmos_menu->set_hide_on_checkable_item_selection(false); + gizmos_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_position_gizmos", TTR("Position")), SHOW_POSITION_GIZMOS); + gizmos_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_lock_gizmos", TTR("Lock")), SHOW_LOCK_GIZMOS); + gizmos_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_group_gizmos", TTR("Group")), SHOW_GROUP_GIZMOS); + gizmos_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_transformation_gizmos", TTR("Transformation")), SHOW_TRANSFORMATION_GIZMOS); + p->add_child(gizmos_menu); + p->add_submenu_item(TTR("Gizmos"), "GizmosMenu"); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), Key::F), VIEW_CENTER_TO_SELECTION); @@ -5806,7 +5845,7 @@ void CanvasItemEditorViewport::_perform_drop_data() { Vector<String> error_files; EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Create Node")); + undo_redo->create_action_for_history(TTR("Create Node"), EditorNode::get_editor_data().get_current_edited_scene_history_id()); for (int i = 0; i < selected_files.size(); i++) { String path = selected_files[i]; diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 9aac6e44df..7fe63e6282 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -126,7 +126,9 @@ private: SHOW_GUIDES, SHOW_ORIGIN, SHOW_VIEWPORT, - SHOW_EDIT_LOCKS, + SHOW_POSITION_GIZMOS, + SHOW_LOCK_GIZMOS, + SHOW_GROUP_GIZMOS, SHOW_TRANSFORMATION_GIZMOS, LOCK_SELECTED, UNLOCK_SELECTED, @@ -209,7 +211,9 @@ private: bool show_origin = true; bool show_viewport = true; bool show_helpers = false; - bool show_edit_locks = true; + bool show_position_gizmos = true; + bool show_lock_gizmos = true; + bool show_group_gizmos = true; bool show_transformation_gizmos = true; real_t zoom = 1.0; @@ -331,6 +335,7 @@ private: MenuButton *view_menu = nullptr; PopupMenu *grid_menu = nullptr; PopupMenu *theme_menu = nullptr; + PopupMenu *gizmos_menu = nullptr; HBoxContainer *animation_hb = nullptr; MenuButton *animation_menu = nullptr; @@ -388,9 +393,9 @@ private: CanvasItem *ref_item = nullptr; - void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false); - void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false); - void _commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones = false); + void _save_canvas_item_state(const List<CanvasItem *> &p_canvas_items, bool save_bones = false); + void _restore_canvas_item_state(const List<CanvasItem *> &p_canvas_items, bool restore_bones = false); + void _commit_canvas_item_state(const List<CanvasItem *> &p_canvas_items, String action_name, bool commit_bones = false); Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor); Vector2 _position_to_anchor(const Control *p_control, Vector2 position); @@ -424,7 +429,7 @@ private: void _switch_theme_preview(int p_mode); List<CanvasItem *> _get_edited_canvas_items(bool retrieve_locked = false, bool remove_canvas_item_if_parent_in_selection = true) const; - Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list); + Rect2 _get_encompassing_rect_from_list(const List<CanvasItem *> &p_list); void _expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D(), bool include_locked_nodes = true); Rect2 _get_encompassing_rect(const Node *p_node); @@ -540,7 +545,7 @@ public: SNAP_DEFAULT = SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL, }; - Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, unsigned int p_forced_modes = 0, const CanvasItem *p_self_canvas_item = nullptr, List<CanvasItem *> p_other_nodes_exceptions = List<CanvasItem *>()); + Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, unsigned int p_forced_modes = 0, const CanvasItem *p_self_canvas_item = nullptr, const List<CanvasItem *> &p_other_nodes_exceptions = List<CanvasItem *>()); real_t snap_angle(real_t p_target, real_t p_start = 0) const; Transform2D get_canvas_transform() const { return transform; } diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index a0539c401d..5b0831eeb8 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -31,11 +31,11 @@ #include "control_editor_plugin.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/grid_container.h" #include "scene/gui/separator.h" @@ -189,7 +189,7 @@ void EditorPropertyAnchorsPreset::setup(const Vector<String> &p_options) { Vector<String> text_split = p_options[i].split(":"); int64_t current_val = text_split[1].to_int(); - String option_name = text_split[0]; + const String &option_name = text_split[0]; if (option_name.begins_with("Preset")) { String preset_name = option_name.trim_prefix("Preset"); String humanized_name = preset_name.capitalize(); diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 72f6784836..ea32b659d7 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -36,11 +36,11 @@ #include "core/os/keyboard.h" #include "editor/editor_interface.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_spin_slider.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/flow_container.h" #include "scene/gui/menu_button.h" #include "scene/gui/popup_menu.h" diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp index 41eae444f7..b9bde65f94 100644 --- a/editor/plugins/debugger_editor_plugin.cpp +++ b/editor/plugins/debugger_editor_plugin.cpp @@ -35,9 +35,9 @@ #include "editor/debugger/editor_debugger_server.h" #include "editor/debugger/editor_file_server.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/menu_button.h" DebuggerEditorPlugin::DebuggerEditorPlugin(PopupMenu *p_debug_menu) { diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 015a4915a8..90bd117543 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -36,8 +36,8 @@ #include "core/object/script_language.h" #include "core/os/os.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/atlas_texture.h" #include "scene/resources/bit_map.h" #include "scene/resources/font.h" diff --git a/editor/plugins/editor_resource_tooltip_plugins.cpp b/editor/plugins/editor_resource_tooltip_plugins.cpp index 36852e79b5..fab8ee9f59 100644 --- a/editor/plugins/editor_resource_tooltip_plugins.cpp +++ b/editor/plugins/editor_resource_tooltip_plugins.cpp @@ -31,7 +31,7 @@ #include "editor_resource_tooltip_plugins.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/label.h" #include "scene/gui/texture_rect.h" diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp index a0500bdb48..d719850204 100644 --- a/editor/plugins/font_config_plugin.cpp +++ b/editor/plugins/font_config_plugin.cpp @@ -30,9 +30,9 @@ #include "font_config_plugin.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/import/dynamic_font_import_settings.h" +#include "editor/themes/editor_scale.h" /*************************************************************************/ /* EditorPropertyFontMetaObject */ diff --git a/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp index 1fce7f5efb..3a8a0cff96 100644 --- a/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp @@ -284,7 +284,7 @@ Joint3DGizmoPlugin::Joint3DGizmoPlugin() { update_timer->set_wait_time(1.0 / 120.0); update_timer->connect("timeout", callable_mp(this, &Joint3DGizmoPlugin::incremental_update_gizmos)); update_timer->set_autostart(true); - EditorNode::get_singleton()->call_deferred(SNAME("add_child"), update_timer); + callable_mp((Node *)EditorNode::get_singleton(), &Node::add_child).call_deferred(update_timer, false, Node::INTERNAL_MODE_DISABLED); } void Joint3DGizmoPlugin::incremental_update_gizmos() { diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp index e696b900d0..d8f9664e8d 100644 --- a/editor/plugins/gradient_editor_plugin.cpp +++ b/editor/plugins/gradient_editor_plugin.cpp @@ -30,15 +30,15 @@ #include "gradient_editor_plugin.h" -#include "canvas_item_editor_plugin.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_spin_slider.h" -#include "node_3d_editor_plugin.h" +#include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/plugins/node_3d_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/color_picker.h" #include "scene/gui/flow_container.h" #include "scene/gui/popup.h" diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp index 5952185cc0..bb6096ea34 100644 --- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp +++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp @@ -31,9 +31,9 @@ #include "gradient_texture_2d_editor_plugin.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_spin_slider.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/flow_container.h" diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp index 11f60a166c..335498dff9 100644 --- a/editor/plugins/lightmap_gi_editor_plugin.cpp +++ b/editor/plugins/lightmap_gi_editor_plugin.cpp @@ -105,7 +105,10 @@ void LightmapGIEditorPlugin::_bake_select_file(const String &p_file) { EditorNode::get_singleton()->show_warning(TTR("Lightmap data is not local to the scene.")); } break; case LightmapGI::BAKE_ERROR_TEXTURE_SIZE_TOO_SMALL: { - EditorNode::get_singleton()->show_warning(TTR("Maximum texture size is too small for the lightmap images.")); + EditorNode::get_singleton()->show_warning(TTR("Maximum texture size is too small for the lightmap images.\nWhile this can be fixed by increasing the maximum texture size, it is recommended you split the scene into more objects instead.")); + } break; + case LightmapGI::BAKE_ERROR_LIGHTMAP_TOO_SMALL: { + EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images. Make sure all meshes selected to bake have `lightmap_size_hint` value set high enough, and `texel_scale` value of LightmapGI is not too low.")); } break; default: { } break; diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 2a712caf92..b7c4479505 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -32,9 +32,9 @@ #include "core/config/project_settings.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" #include "scene/3d/camera_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/mesh_instance_3d.h" diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 729ca5d7f9..0324b1d4f7 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -31,7 +31,7 @@ #include "mesh_editor_plugin.h" #include "core/config/project_settings.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/main/viewport.h" diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 04be44ffc8..9669f992a8 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -31,10 +31,10 @@ #include "mesh_instance_3d_editor_plugin.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/node_3d_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/3d/collision_shape_3d.h" #include "scene/3d/navigation_region_3d.h" #include "scene/3d/physics_body_3d.h" diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 3bd786c04f..a427d0359d 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -825,6 +825,7 @@ void EditorNode3DGizmo::_bind_methods() { GDVIRTUAL_BIND(_is_handle_highlighted, "id", "secondary"); GDVIRTUAL_BIND(_get_handle_value, "id", "secondary"); + GDVIRTUAL_BIND(_begin_handle_action, "id", "secondary"); GDVIRTUAL_BIND(_set_handle, "id", "secondary", "camera", "point"); GDVIRTUAL_BIND(_commit_handle, "id", "secondary", "restore", "cancel"); @@ -1045,6 +1046,7 @@ void EditorNode3DGizmoPlugin::_bind_methods() { GDVIRTUAL_BIND(_is_handle_highlighted, "gizmo", "handle_id", "secondary"); GDVIRTUAL_BIND(_get_handle_value, "gizmo", "handle_id", "secondary"); + GDVIRTUAL_BIND(_begin_handle_action, "gizmo", "handle_id", "secondary"); GDVIRTUAL_BIND(_set_handle, "gizmo", "handle_id", "secondary", "camera", "screen_pos"); GDVIRTUAL_BIND(_commit_handle, "gizmo", "handle_id", "secondary", "restore", "cancel"); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 52f17c4a45..e4d24832bf 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1839,17 +1839,17 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { clicked = ObjectID(); - if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_or_control_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { + if (can_select_gizmos && ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_or_control_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)) { begin_transform(TRANSFORM_ROTATE, false); break; } - if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) { + if (can_select_gizmos && spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) { begin_transform(TRANSFORM_TRANSLATE, false); break; } - if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) { + if (can_select_gizmos && spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) { begin_transform(TRANSFORM_SCALE, false); break; } @@ -2734,11 +2734,11 @@ void Node3DEditorViewport::_notification(int p_what) { } else { set_freelook_active(false); } - call_deferred(SNAME("update_transform_gizmo_view")); + callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view).call_deferred(); } break; case NOTIFICATION_RESIZED: { - call_deferred(SNAME("update_transform_gizmo_view")); + callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view).call_deferred(); } break; case NOTIFICATION_PROCESS: { @@ -3355,7 +3355,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), false); orthogonal = false; auto_orthogonal = false; - call_deferred(SNAME("update_transform_gizmo_view")); + callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view).call_deferred(); _update_camera(0); _update_name(); @@ -3365,7 +3365,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), true); orthogonal = true; auto_orthogonal = false; - call_deferred(SNAME("update_transform_gizmo_view")); + callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view).call_deferred(); _update_camera(0); _update_name(); } break; @@ -3985,8 +3985,6 @@ Dictionary Node3DEditorViewport::get_state() const { } void Node3DEditorViewport::_bind_methods() { - ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"), &Node3DEditorViewport::update_transform_gizmo_view); // Used by call_deferred. - ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport"))); ADD_SIGNAL(MethodInfo("clicked", PropertyInfo(Variant::OBJECT, "viewport"))); } @@ -4247,17 +4245,16 @@ bool Node3DEditorViewport::_apply_preview_material(ObjectID p_target, const Poin return false; } - if (spatial_editor->get_preview_material() != mesh_instance->get_surface_override_material(closest_surface)) { - spatial_editor->set_preview_material_surface(closest_surface); - spatial_editor->set_preview_reset_material(mesh_instance->get_surface_override_material(closest_surface)); - mesh_instance->set_surface_override_material(closest_surface, spatial_editor->get_preview_material()); - } + spatial_editor->set_preview_material_surface(closest_surface); + spatial_editor->set_preview_reset_material(mesh_instance->get_surface_override_material(closest_surface)); + mesh_instance->set_surface_override_material(closest_surface, spatial_editor->get_preview_material()); return true; } GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(target_inst); - if (geometry_instance && spatial_editor->get_preview_material() != geometry_instance->get_material_override()) { + if (geometry_instance) { + spatial_editor->set_preview_material_surface(-1); spatial_editor->set_preview_reset_material(geometry_instance->get_material_override()); geometry_instance->set_material_override(spatial_editor->get_preview_material()); return true; @@ -4277,7 +4274,6 @@ void Node3DEditorViewport::_reset_preview_material() const { GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(last_target_inst); if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) { mesh_instance->set_surface_override_material(spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material()); - spatial_editor->set_preview_material_surface(-1); } else if (geometry_instance) { geometry_instance->set_material_override(spatial_editor->get_preview_reset_material()); } @@ -6489,25 +6485,91 @@ void Node3DEditor::_init_indicators() { origin_enabled = true; grid_enabled = true; - indicator_mat.instantiate(); - indicator_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - indicator_mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - indicator_mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); - indicator_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); - indicator_mat->set_transparency(StandardMaterial3D::Transparency::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS); + Ref<Shader> origin_shader = memnew(Shader); + origin_shader->set_code(R"( +// 3D editor origin line shader. + +shader_type spatial; +render_mode blend_mix,cull_disabled,unshaded, fog_disabled; + +void vertex() { + vec3 point_a = MODEL_MATRIX[3].xyz; + // Encoded in scale. + vec3 point_b = vec3(MODEL_MATRIX[0].x, MODEL_MATRIX[1].y, MODEL_MATRIX[2].z); + + // Points are already in world space, so no need for MODEL_MATRIX anymore. + vec4 clip_a = PROJECTION_MATRIX * (VIEW_MATRIX * vec4(point_a, 1.0)); + vec4 clip_b = PROJECTION_MATRIX * (VIEW_MATRIX * vec4(point_b, 1.0)); + + vec2 screen_a = VIEWPORT_SIZE * (0.5 * clip_a.xy / clip_a.w + 0.5); + vec2 screen_b = VIEWPORT_SIZE * (0.5 * clip_b.xy / clip_b.w + 0.5); + + vec2 x_basis = normalize(screen_b - screen_a); + vec2 y_basis = vec2(-x_basis.y, x_basis.x); + + float width = 3.0; + vec2 screen_point_a = screen_a + width * (VERTEX.x * x_basis + VERTEX.y * y_basis); + vec2 screen_point_b = screen_b + width * (VERTEX.x * x_basis + VERTEX.y * y_basis); + vec2 screen_point_final = mix(screen_point_a, screen_point_b, VERTEX.z); + + vec4 clip_final = mix(clip_a, clip_b, VERTEX.z); + + POSITION = vec4(clip_final.w * ((2.0 * screen_point_final) / VIEWPORT_SIZE - 1.0), clip_final.z, clip_final.w); + UV = VERTEX.yz * clip_final.w; + + if (!OUTPUT_IS_SRGB) { + COLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045))); + } +} + +void fragment() { + // Multiply by 0.5 since UV is actually UV is [-1, 1]. + float line_width = fwidth(UV.x * 0.5); + float line_uv = abs(UV.x * 0.5); + float line = smoothstep(line_width * 1.0, line_width * 0.25, line_uv); + + ALBEDO = COLOR.rgb; + ALPHA *= COLOR.a * line; +} +)"); + + origin_mat.instantiate(); + origin_mat->set_shader(origin_shader); - Vector<Color> origin_colors; Vector<Vector3> origin_points; + origin_points.resize(6); + + origin_points.set(0, Vector3(0.0, -0.5, 0.0)); + origin_points.set(1, Vector3(0.0, -0.5, 1.0)); + origin_points.set(2, Vector3(0.0, 0.5, 1.0)); + + origin_points.set(3, Vector3(0.0, -0.5, 0.0)); + origin_points.set(4, Vector3(0.0, 0.5, 1.0)); + origin_points.set(5, Vector3(0.0, 0.5, 0.0)); + + Array d; + d.resize(RS::ARRAY_MAX); + d[RenderingServer::ARRAY_VERTEX] = origin_points; - const int count_of_elements = 3 * 6; - origin_colors.resize(count_of_elements); - origin_points.resize(count_of_elements); + origin_mesh = RenderingServer::get_singleton()->mesh_create(); - int x = 0; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(origin_mesh, RenderingServer::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(origin_mesh, 0, origin_mat->get_rid()); + + origin_multimesh = RenderingServer::get_singleton()->multimesh_create(); + RenderingServer::get_singleton()->multimesh_set_mesh(origin_multimesh, origin_mesh); + RenderingServer::get_singleton()->multimesh_allocate_data(origin_multimesh, 12, RS::MultimeshTransformFormat::MULTIMESH_TRANSFORM_3D, true, false); + RenderingServer::get_singleton()->multimesh_set_visible_instances(origin_multimesh, -1); + + LocalVector<float> distances; + distances.resize(5); + distances[0] = -1000000.0; + distances[1] = -1000.0; + distances[2] = 0.0; + distances[3] = 1000.0; + distances[4] = 1000000.0; for (int i = 0; i < 3; i++) { - Vector3 axis; - axis[i] = 1; Color origin_color; switch (i) { case 0: @@ -6524,27 +6586,26 @@ void Node3DEditor::_init_indicators() { break; } - grid_enable[i] = false; - grid_visible[i] = false; + Vector3 axis; + axis[i] = 1; - origin_colors.set(x, origin_color); - origin_colors.set(x + 1, origin_color); - origin_colors.set(x + 2, origin_color); - origin_colors.set(x + 3, origin_color); - origin_colors.set(x + 4, origin_color); - origin_colors.set(x + 5, origin_color); - // To both allow having a large origin size and avoid jitter - // at small scales, we should segment the line into pieces. - // 3 pieces seems to do the trick, and let's use powers of 2. - origin_points.set(x, axis * 1048576); - origin_points.set(x + 1, axis * 1024); - origin_points.set(x + 2, axis * 1024); - origin_points.set(x + 3, axis * -1024); - origin_points.set(x + 4, axis * -1024); - origin_points.set(x + 5, axis * -1048576); - x += 6; + for (int j = 0; j < 4; j++) { + Transform3D t = Transform3D(); + t = t.scaled(axis * distances[j + 1]); + t = t.translated(axis * distances[j]); + RenderingServer::get_singleton()->multimesh_instance_set_transform(origin_multimesh, i * 4 + j, t); + RenderingServer::get_singleton()->multimesh_instance_set_color(origin_multimesh, i * 4 + j, origin_color); + } } + origin_instance = RenderingServer::get_singleton()->instance_create2(origin_multimesh, get_tree()->get_root()->get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); + RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); + RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); + RS::get_singleton()->instance_set_ignore_culling(origin_instance, true); + + RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, RS::SHADOW_CASTING_SETTING_OFF); + Ref<Shader> grid_shader = memnew(Shader); grid_shader->set_code(R"( // 3D editor grid shader. @@ -6593,22 +6654,6 @@ void fragment() { grid_visible[2] = grid_enable[2]; _init_grid(); - - origin = RenderingServer::get_singleton()->mesh_create(); - Array d; - d.resize(RS::ARRAY_MAX); - d[RenderingServer::ARRAY_VERTEX] = origin_points; - d[RenderingServer::ARRAY_COLOR] = origin_colors; - - RenderingServer::get_singleton()->mesh_add_surface_from_arrays(origin, RenderingServer::PRIMITIVE_LINES, d); - RenderingServer::get_singleton()->mesh_surface_set_material(origin, 0, indicator_mat->get_rid()); - - origin_instance = RenderingServer::get_singleton()->instance_create2(origin, get_tree()->get_root()->get_world_3d()->get_scenario()); - RS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); - RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); - RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); - - RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, RS::SHADOW_CASTING_SETTING_OFF); } { @@ -7226,7 +7271,8 @@ void Node3DEditor::_init_grid() { void Node3DEditor::_finish_indicators() { RenderingServer::get_singleton()->free(origin_instance); - RenderingServer::get_singleton()->free(origin); + RenderingServer::get_singleton()->free(origin_multimesh); + RenderingServer::get_singleton()->free(origin_mesh); _finish_grid(); } @@ -8013,6 +8059,8 @@ void Node3DEditor::_bind_methods() { ClassDB::bind_method("_clear_subgizmo_selection", &Node3DEditor::_clear_subgizmo_selection); ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons); + ClassDB::bind_method("update_all_gizmos", &Node3DEditor::update_all_gizmos); + ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); ADD_SIGNAL(MethodInfo("item_group_status_changed")); @@ -8300,7 +8348,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(tool_button[TOOL_GROUP_SELECTED]); tool_button[TOOL_GROUP_SELECTED]->set_theme_type_variation("FlatButton"); tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_GROUP_SELECTED)); - tool_button[TOOL_GROUP_SELECTED]->set_tooltip_text(TTR("Make selected node's children not selectable.")); + tool_button[TOOL_GROUP_SELECTED]->set_tooltip_text(TTR("Groups the selected node with its children. This selects the parent when any child node is clicked in 2D and 3D view.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | Key::G)); @@ -8308,7 +8356,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(tool_button[TOOL_UNGROUP_SELECTED]); tool_button[TOOL_UNGROUP_SELECTED]->set_theme_type_variation("FlatButton"); tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNGROUP_SELECTED)); - tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip_text(TTR("Make selected node's children selectable.")); + tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip_text(TTR("Ungroups the selected node from its children. Child nodes will be individual items in 2D and 3D view.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::G)); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 1ce09a2bcb..455376b659 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -32,8 +32,8 @@ #define NODE_3D_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "editor/editor_scale.h" #include "editor/plugins/node_3d_editor_gizmos.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/spin_box.h" @@ -597,7 +597,8 @@ private: ToolMode tool_mode; - RID origin; + RID origin_mesh; + RID origin_multimesh; RID origin_instance; bool origin_enabled = false; RID grid[3]; @@ -631,7 +632,7 @@ private: RID indicators_instance; RID cursor_mesh; RID cursor_instance; - Ref<StandardMaterial3D> indicator_mat; + Ref<ShaderMaterial> origin_mat; Ref<ShaderMaterial> grid_mat[3]; Ref<StandardMaterial3D> cursor_material; diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp index 7cb5244af9..c5c791ca8e 100644 --- a/editor/plugins/packed_scene_translation_parser_plugin.cpp +++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp @@ -52,9 +52,11 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, Ref<SceneState> state = Ref<PackedScene>(loaded_res)->get_state(); Vector<String> parsed_strings; + List<String> tabcontainer_paths; for (int i = 0; i < state->get_node_count(); i++) { String node_type = state->get_node_type(i); - if (!ClassDB::is_parent_class(node_type, "Control") && !ClassDB::is_parent_class(node_type, "Window")) { + bool is_control = ClassDB::is_parent_class(node_type, "Control"); + if (!is_control && !ClassDB::is_parent_class(node_type, "Window")) { continue; } @@ -66,10 +68,28 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, break; } } + + // Parse the names of children of `TabContainer`s, as they are used for tab titles. + if (!tabcontainer_paths.is_empty()) { + String parent_path = state->get_node_path(i, true); + if (!parent_path.begins_with(tabcontainer_paths[tabcontainer_paths.size() - 1])) { + // Switch to the previous `TabContainer` this was nested in, if that was the case. + tabcontainer_paths.pop_back(); + } + + if (is_control && auto_translating && !tabcontainer_paths.is_empty() && parent_path == tabcontainer_paths[tabcontainer_paths.size() - 1]) { + parsed_strings.push_back(state->get_node_name(i)); + } + } + if (!auto_translating) { continue; } + if (node_type == "TabContainer") { + tabcontainer_paths.push_back(state->get_node_path(i)); + } + for (int j = 0; j < state->get_node_property_count(i); j++) { String property_name = state->get_node_property_name(i, j); if (!lookup_properties.has(property_name) || (exception_list.has(node_type) && exception_list[node_type].has(property_name))) { diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 0d6086bb4d..a772dba6ae 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -34,9 +34,10 @@ #include "core/io/file_access.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" +#include "scene/gui/dialogs.h" #include "scene/gui/menu_button.h" void Path2DEditor::_notification(int p_what) { @@ -48,6 +49,7 @@ void Path2DEditor::_notification(int p_what) { curve_create->set_icon(get_editor_theme_icon(SNAME("CurveCreate"))); curve_del->set_icon(get_editor_theme_icon(SNAME("CurveDelete"))); curve_close->set_icon(get_editor_theme_icon(SNAME("CurveClose"))); + curve_clear_points->set_icon(get_editor_theme_icon(SNAME("Clear"))); } break; } } @@ -68,7 +70,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } - if (!node->get_curve().is_valid()) { + if (node->get_curve().is_null()) { return false; } @@ -121,7 +123,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { // Check for point deletion. EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - if ((mb->get_button_index() == MouseButton::RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == MouseButton::LEFT && mode == MODE_DELETE)) { + if ((mb->get_button_index() == MouseButton::RIGHT && (mode == MODE_EDIT || mode == MODE_CREATE)) || (mb->get_button_index() == MouseButton::LEFT && mode == MODE_DELETE)) { if (dist_to_p < grab_threshold) { undo_redo->create_action(TTR("Remove Point from Curve")); undo_redo->add_do_method(curve.ptr(), "remove_point", i); @@ -154,16 +156,14 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { // Check for point creation. if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && ((mb->is_command_or_control_pressed() && mode == MODE_EDIT) || mode == MODE_CREATE)) { Ref<Curve2D> curve = node->get_curve(); + curve->add_point(cpoint); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Add Point to Curve")); undo_redo->add_do_method(curve.ptr(), "add_point", cpoint); - undo_redo->add_undo_method(curve.ptr(), "remove_point", curve->get_point_count()); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - undo_redo->commit_action(); + undo_redo->add_undo_method(curve.ptr(), "remove_point", curve->get_point_count() - 1); - action = ACTION_MOVING_POINT; + action = ACTION_MOVING_NEW_POINT; action_point = curve->get_point_count() - 1; moving_from = curve->get_point_position(action_point); moving_screen_from = gpoint; @@ -191,15 +191,15 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { insertion_point = curve->get_point_count() - 2; } + const Vector2 new_point = xform.affine_inverse().xform(gpoint2); + curve->add_point(new_point, Vector2(0, 0), Vector2(0, 0), insertion_point + 1); + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Split Curve")); - undo_redo->add_do_method(curve.ptr(), "add_point", xform.affine_inverse().xform(gpoint2), Vector2(0, 0), Vector2(0, 0), insertion_point + 1); + undo_redo->add_do_method(curve.ptr(), "add_point", new_point, Vector2(0, 0), Vector2(0, 0), insertion_point + 1); undo_redo->add_undo_method(curve.ptr(), "remove_point", insertion_point + 1); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - undo_redo->commit_action(); - action = ACTION_MOVING_POINT; + action = ACTION_MOVING_NEW_POINT; action_point = insertion_point + 1; moving_from = curve->get_point_position(action_point); moving_screen_from = gpoint2; @@ -222,13 +222,16 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { // N/A, handled in above condition. break; - case ACTION_MOVING_POINT: { - undo_redo->create_action(TTR("Move Point in Curve")); + case ACTION_MOVING_POINT: + case ACTION_MOVING_NEW_POINT: { + if (action == ACTION_MOVING_POINT) { + undo_redo->create_action(TTR("Move Point in Curve")); + undo_redo->add_undo_method(curve.ptr(), "set_point_position", action_point, moving_from); + } undo_redo->add_do_method(curve.ptr(), "set_point_position", action_point, cpoint); - undo_redo->add_undo_method(curve.ptr(), "set_point_position", action_point, moving_from); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - undo_redo->commit_action(); + undo_redo->commit_action(false); } break; @@ -334,7 +337,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { // N/A, handled in above condition. break; - case ACTION_MOVING_POINT: { + case ACTION_MOVING_POINT: + case ACTION_MOVING_NEW_POINT: { curve->set_point_position(action_point, cpoint); } break; @@ -364,7 +368,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { - if (!node || !node->is_visible_in_tree() || !node->get_curve().is_valid()) { + if (!node || !node->is_visible_in_tree() || node->get_curve().is_null()) { return; } @@ -437,12 +441,12 @@ void Path2DEditor::edit(Node *p_path2d) { if (p_path2d) { node = Object::cast_to<Path2D>(p_path2d); + if (!node->is_connected("visibility_changed", callable_mp(this, &Path2DEditor::_node_visibility_changed))) { node->connect("visibility_changed", callable_mp(this, &Path2DEditor::_node_visibility_changed)); } - } else { - // node may have been deleted at this point + // The node may have been deleted at this point. if (node && node->is_connected("visibility_changed", callable_mp(this, &Path2DEditor::_node_visibility_changed))) { node->disconnect("visibility_changed", callable_mp(this, &Path2DEditor::_node_visibility_changed)); } @@ -452,6 +456,8 @@ void Path2DEditor::edit(Node *p_path2d) { void Path2DEditor::_bind_methods() { //ClassDB::bind_method(D_METHOD("_menu_option"),&Path2DEditor::_menu_option); + ClassDB::bind_method(D_METHOD("_clear_curve_points"), &Path2DEditor::_clear_curve_points); + ClassDB::bind_method(D_METHOD("_restore_curve_points"), &Path2DEditor::_restore_curve_points); } void Path2DEditor::_mode_selected(int p_mode) { @@ -475,32 +481,46 @@ void Path2DEditor::_mode_selected(int p_mode) { curve_edit->set_pressed(false); curve_edit_curve->set_pressed(false); curve_del->set_pressed(true); - } else if (p_mode == ACTION_CLOSE) { - //? - - if (!node->get_curve().is_valid()) { + } else if (p_mode == MODE_CLOSE) { + if (node->get_curve().is_null()) { return; } if (node->get_curve()->get_point_count() < 3) { return; } - Vector2 begin = node->get_curve()->get_point_position(0); Vector2 end = node->get_curve()->get_point_position(node->get_curve()->get_point_count() - 1); + if (begin.is_equal_approx(end)) { return; } - EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Remove Point from Curve")); + + undo_redo->create_action(TTR("Close the Curve")); undo_redo->add_do_method(node->get_curve().ptr(), "add_point", begin); undo_redo->add_undo_method(node->get_curve().ptr(), "remove_point", node->get_curve()->get_point_count()); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); return; - } + } else if (p_mode == MODE_CLEAR_POINTS) { + if (node->get_curve().is_null()) { + return; + } + if (node->get_curve()->get_point_count() == 0) { + return; + } + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + PackedVector2Array points = node->get_curve()->get_points().duplicate(); + undo_redo->create_action(TTR("Clear Curve Points"), UndoRedo::MERGE_DISABLE, node); + undo_redo->add_do_method(this, "_clear_curve_points", node); + undo_redo->add_undo_method(this, "_restore_curve_points", node, points); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); + undo_redo->commit_action(); + return; + } mode = Mode(p_mode); } @@ -523,6 +543,52 @@ void Path2DEditor::_handle_option_pressed(int p_option) { } } +void Path2DEditor::_confirm_clear_points() { + if (!node || node->get_curve().is_null()) { + return; + } + if (node->get_curve()->get_point_count() == 0) { + return; + } + clear_points_dialog->reset_size(); + clear_points_dialog->popup_centered(); +} + +void Path2DEditor::_clear_curve_points(Path2D *p_path2d) { + if (!p_path2d || p_path2d->get_curve().is_null()) { + return; + } + Ref<Curve2D> curve = p_path2d->get_curve(); + + if (curve->get_point_count() == 0) { + return; + } + curve->clear_points(); + + if (node == p_path2d) { + _mode_selected(MODE_CREATE); + } +} + +void Path2DEditor::_restore_curve_points(Path2D *p_path2d, const PackedVector2Array &p_points) { + if (!p_path2d || p_path2d->get_curve().is_null()) { + return; + } + Ref<Curve2D> curve = p_path2d->get_curve(); + + if (curve->get_point_count() > 0) { + curve->clear_points(); + } + + for (int i = 0; i < p_points.size(); i += 3) { + curve->add_point(p_points[i + 2], p_points[i], p_points[i + 1]); // The Curve2D::points pattern is [point_in, point_out, point_position]. + } + + if (node == p_path2d) { + _mode_selected(MODE_EDIT); + } +} + Path2DEditor::Path2DEditor() { canvas_item_editor = nullptr; mirror_handle_angle = true; @@ -553,7 +619,7 @@ Path2DEditor::Path2DEditor() { curve_create->set_theme_type_variation("FlatButton"); curve_create->set_toggle_mode(true); curve_create->set_focus_mode(Control::FOCUS_NONE); - curve_create->set_tooltip_text(TTR("Add Point (in empty space)")); + curve_create->set_tooltip_text(TTR("Add Point (in empty space)") + "\n" + TTR("Right Click: Delete Point")); curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_CREATE)); add_child(curve_create); @@ -569,9 +635,22 @@ Path2DEditor::Path2DEditor() { curve_close->set_theme_type_variation("FlatButton"); curve_close->set_focus_mode(Control::FOCUS_NONE); curve_close->set_tooltip_text(TTR("Close Curve")); - curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(ACTION_CLOSE)); + curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_CLOSE)); add_child(curve_close); + curve_clear_points = memnew(Button); + curve_clear_points->set_theme_type_variation("FlatButton"); + curve_clear_points->set_focus_mode(Control::FOCUS_NONE); + curve_clear_points->set_tooltip_text(TTR("Clear Points")); + curve_clear_points->connect("pressed", callable_mp(this, &Path2DEditor::_confirm_clear_points)); + add_child(curve_clear_points); + + clear_points_dialog = memnew(ConfirmationDialog); + clear_points_dialog->set_title(TTR("Please Confirm...")); + clear_points_dialog->set_text(TTR("Remove all curve points?")); + clear_points_dialog->connect("confirmed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_CLEAR_POINTS)); + add_child(clear_points_dialog); + PopupMenu *menu; handle_menu = memnew(MenuButton); diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index b8816d9b1e..af9f307cc8 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -36,45 +36,51 @@ #include "scene/gui/box_container.h" class CanvasItemEditor; +class ConfirmationDialog; class MenuButton; class Path2DEditor : public HBoxContainer { GDCLASS(Path2DEditor, HBoxContainer); + friend class Path2DEditorPlugin; + CanvasItemEditor *canvas_item_editor = nullptr; Panel *panel = nullptr; Path2D *node = nullptr; - HBoxContainer *base_hb = nullptr; - enum Mode { MODE_CREATE, MODE_EDIT, MODE_EDIT_CURVE, MODE_DELETE, - ACTION_CLOSE + MODE_CLOSE, + MODE_CLEAR_POINTS, }; Mode mode; + Button *curve_clear_points = nullptr; + Button *curve_close = nullptr; Button *curve_create = nullptr; + Button *curve_del = nullptr; Button *curve_edit = nullptr; Button *curve_edit_curve = nullptr; - Button *curve_del = nullptr; - Button *curve_close = nullptr; MenuButton *handle_menu = nullptr; + ConfirmationDialog *clear_points_dialog = nullptr; + bool mirror_handle_angle; bool mirror_handle_length; bool on_edge; enum HandleOption { HANDLE_OPTION_ANGLE, - HANDLE_OPTION_LENGTH + HANDLE_OPTION_LENGTH, }; enum Action { ACTION_NONE, ACTION_MOVING_POINT, + ACTION_MOVING_NEW_POINT, ACTION_MOVING_IN, ACTION_MOVING_OUT, }; @@ -91,7 +97,10 @@ class Path2DEditor : public HBoxContainer { void _handle_option_pressed(int p_option); void _node_visibility_changed(); - friend class Path2DEditorPlugin; + + void _confirm_clear_points(); + void _clear_curve_points(Path2D *p_path2d); + void _restore_curve_points(Path2D *p_path2d, const PackedVector2Array &p_points); protected: void _notification(int p_what); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index f8e6c71a4c..e56fc94a55 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -33,10 +33,11 @@ #include "core/input/input_event.h" #include "core/math/geometry_2d.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/gui/editor_zoom_widget.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/skeleton_2d.h" #include "scene/gui/check_box.h" #include "scene/gui/dialogs.h" @@ -96,10 +97,14 @@ void Polygon2DEditor::_notification(int p_what) { b_snap_grid->set_icon(get_editor_theme_icon(SNAME("Grid"))); b_snap_enable->set_icon(get_editor_theme_icon(SNAME("SnapGrid"))); - uv_icon_zoom->set_texture(get_editor_theme_icon(SNAME("Zoom"))); uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE); uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE); + // Avoid scrollbar overlapping. + Size2 hmin = uv_hscroll->get_combined_minimum_size(); + Size2 vmin = uv_vscroll->get_combined_minimum_size(); + uv_hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, -vmin.width); + uv_vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -hmin.height); [[fallthrough]]; } case NOTIFICATION_THEME_CHANGED: { @@ -317,6 +322,7 @@ void Polygon2DEditor::_menu_option(int p_option) { uv_edit->popup_centered_ratio(0.85); } _update_bone_list(); + get_tree()->connect("process_frame", callable_mp(this, &Polygon2DEditor::_center_view), CONNECT_ONE_SHOT); } break; case UVEDIT_POLYGON_TO_UV: { Vector<Vector2> points = node->get_polygon(); @@ -470,7 +476,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } Transform2D mtx; - mtx.columns[2] = -uv_draw_ofs; + mtx.columns[2] = -uv_draw_ofs * uv_draw_zoom; mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom)); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); @@ -941,36 +947,79 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_edit_draw->queue_redraw(); } } +} - Ref<InputEventMagnifyGesture> magnify_gesture = p_input; - if (magnify_gesture.is_valid()) { - uv_zoom->set_value(uv_zoom->get_value() * magnify_gesture->get_factor()); +void Polygon2DEditor::_center_view() { + Size2 texture_size; + if (node->get_texture().is_valid()) { + texture_size = node->get_texture()->get_size(); + Vector2 zoom_factor = (uv_edit_draw->get_size() - Vector2(1, 1) * 50 * EDSCALE) / texture_size; + zoom_widget->set_zoom(MIN(zoom_factor.x, zoom_factor.y)); + } else { + zoom_widget->set_zoom(EDSCALE); } + // Recalculate scroll limits. + _update_zoom_and_pan(false); - Ref<InputEventPanGesture> pan_gesture = p_input; - if (pan_gesture.is_valid()) { - uv_hscroll->set_value(uv_hscroll->get_value() + uv_hscroll->get_page() * pan_gesture->get_delta().x / 8); - uv_vscroll->set_value(uv_vscroll->get_value() + uv_vscroll->get_page() * pan_gesture->get_delta().y / 8); - } + Size2 offset = (texture_size - uv_edit_draw->get_size() / uv_draw_zoom) / 2; + uv_hscroll->set_value_no_signal(offset.x); + uv_vscroll->set_value_no_signal(offset.y); + _update_zoom_and_pan(false); } void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) { - uv_hscroll->set_value(uv_hscroll->get_value() - p_scroll_vec.x); - uv_vscroll->set_value(uv_vscroll->get_value() - p_scroll_vec.y); + uv_hscroll->set_value_no_signal(uv_hscroll->get_value() - p_scroll_vec.x / uv_draw_zoom); + uv_vscroll->set_value_no_signal(uv_vscroll->get_value() - p_scroll_vec.y / uv_draw_zoom); + _update_zoom_and_pan(false); } void Polygon2DEditor::_uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) { - uv_zoom->set_value(uv_zoom->get_value() * p_zoom_factor); + zoom_widget->set_zoom(uv_draw_zoom * p_zoom_factor); + uv_draw_ofs += p_origin / uv_draw_zoom - p_origin / zoom_widget->get_zoom(); + uv_hscroll->set_value_no_signal(uv_draw_ofs.x); + uv_vscroll->set_value_no_signal(uv_draw_ofs.y); + _update_zoom_and_pan(false); } -void Polygon2DEditor::_uv_scroll_changed(real_t) { - if (updating_uv_scroll) { - return; +void Polygon2DEditor::_update_zoom_and_pan(bool p_zoom_at_center) { + uv_draw_ofs = Vector2(uv_hscroll->get_value(), uv_vscroll->get_value()); + real_t previous_zoom = uv_draw_zoom; + uv_draw_zoom = zoom_widget->get_zoom(); + if (p_zoom_at_center) { + Vector2 center = uv_edit_draw->get_size() / 2; + uv_draw_ofs += center / previous_zoom - center / uv_draw_zoom; + } + + Point2 min_corner; + Point2 max_corner; + if (node->get_texture().is_valid()) { + max_corner += node->get_texture()->get_size(); + } + + Vector<Vector2> points = uv_edit_mode[0]->is_pressed() ? node->get_uv() : node->get_polygon(); + for (int i = 0; i < points.size(); i++) { + min_corner = min_corner.min(points[i]); + max_corner = max_corner.max(points[i]); } + Size2 page_size = uv_edit_draw->get_size() / uv_draw_zoom; + Vector2 margin = Vector2(50, 50) * EDSCALE / uv_draw_zoom; + min_corner -= page_size - margin; + max_corner += page_size - margin; + + uv_hscroll->set_block_signals(true); + uv_hscroll->set_min(min_corner.x); + uv_hscroll->set_max(max_corner.x); + uv_hscroll->set_page(page_size.x); + uv_hscroll->set_value(uv_draw_ofs.x); + uv_hscroll->set_block_signals(false); + + uv_vscroll->set_block_signals(true); + uv_vscroll->set_min(min_corner.y); + uv_vscroll->set_max(max_corner.y); + uv_vscroll->set_page(page_size.y); + uv_vscroll->set_value(uv_draw_ofs.y); + uv_vscroll->set_block_signals(false); - uv_draw_ofs.x = uv_hscroll->get_value(); - uv_draw_ofs.y = uv_vscroll->get_value(); - uv_draw_zoom = uv_zoom->get_value(); uv_edit_draw->queue_redraw(); } @@ -987,7 +1036,7 @@ void Polygon2DEditor::_uv_draw() { String warning; Transform2D mtx; - mtx.columns[2] = -uv_draw_ofs; + mtx.columns[2] = -uv_draw_ofs * uv_draw_zoom; mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom)); // Draw texture as a background if editing uvs or no uv mapping exist. @@ -1094,7 +1143,6 @@ void Polygon2DEditor::_uv_draw() { polygon_fill_color.push_back(pf); } Color prev_color = Color(0.5, 0.5, 0.5); - Rect2 rect; int uv_draw_max = uvs.size(); @@ -1222,40 +1270,6 @@ void Polygon2DEditor::_uv_draw() { //draw paint circle uv_edit_draw->draw_circle(bone_paint_pos, bone_paint_radius->get_value() * EDSCALE, Color(1, 1, 1, 0.1)); } - - rect.position = -uv_edit_draw->get_size(); - rect.size = uv_edit_draw->get_size() * 2.0 + base_tex->get_size() * uv_draw_zoom; - - updating_uv_scroll = true; - - uv_hscroll->set_min(rect.position.x); - uv_hscroll->set_max(rect.position.x + rect.size.x); - if (ABS(rect.position.x - (rect.position.x + rect.size.x)) <= uv_edit_draw->get_size().x) { - uv_hscroll->hide(); - } else { - uv_hscroll->show(); - uv_hscroll->set_page(uv_edit_draw->get_size().x); - uv_hscroll->set_value(uv_draw_ofs.x); - } - - uv_vscroll->set_min(rect.position.y); - uv_vscroll->set_max(rect.position.y + rect.size.y); - if (ABS(rect.position.y - (rect.position.y + rect.size.y)) <= uv_edit_draw->get_size().y) { - uv_vscroll->hide(); - } else { - uv_vscroll->show(); - uv_vscroll->set_page(uv_edit_draw->get_size().y); - uv_vscroll->set_value(uv_draw_ofs.y); - } - - Size2 hmin = uv_hscroll->get_combined_minimum_size(); - Size2 vmin = uv_vscroll->get_combined_minimum_size(); - - // Avoid scrollbar overlapping. - uv_hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, uv_vscroll->is_visible() ? -vmin.width : 0); - uv_vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, uv_hscroll->is_visible() ? -hmin.height : 0); - - updating_uv_scroll = false; } void Polygon2DEditor::_bind_methods() { @@ -1480,33 +1494,20 @@ Polygon2DEditor::Polygon2DEditor() { sb_step_y->connect("value_changed", callable_mp(this, &Polygon2DEditor::_set_snap_step_y)); grid_settings_vb->add_margin_child(TTR("Grid Step Y:"), sb_step_y); - uv_mode_hb->add_child(memnew(VSeparator)); - uv_icon_zoom = memnew(TextureRect); - uv_icon_zoom->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); - uv_mode_hb->add_child(uv_icon_zoom); - uv_zoom = memnew(HSlider); - uv_zoom->set_min(0.01); - uv_zoom->set_max(16); - uv_zoom->set_value(1); - uv_zoom->set_step(0.01); - uv_zoom->set_v_size_flags(SIZE_SHRINK_CENTER); - - uv_mode_hb->add_child(uv_zoom); - uv_zoom->set_custom_minimum_size(Size2(80 * EDSCALE, 0)); - uv_zoom_value = memnew(SpinBox); - uv_zoom->share(uv_zoom_value); - uv_zoom_value->set_custom_minimum_size(Size2(50, 0)); - uv_mode_hb->add_child(uv_zoom_value); - uv_zoom->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed)); + zoom_widget = memnew(EditorZoomWidget); + uv_edit_draw->add_child(zoom_widget); + zoom_widget->set_anchors_and_offsets_preset(Control::PRESET_TOP_LEFT, Control::PRESET_MODE_MINSIZE, 2 * EDSCALE); + zoom_widget->connect("zoom_changed", callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(true)); + zoom_widget->set_shortcut_context(nullptr); uv_vscroll = memnew(VScrollBar); uv_vscroll->set_step(0.001); uv_edit_draw->add_child(uv_vscroll); - uv_vscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed)); + uv_vscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(false)); uv_hscroll = memnew(HScrollBar); uv_hscroll->set_step(0.001); uv_edit_draw->add_child(uv_hscroll); - uv_hscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed)); + uv_hscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(false)); bone_scroll_main_vb = memnew(VBoxContainer); bone_scroll_main_vb->hide(); @@ -1535,7 +1536,6 @@ Polygon2DEditor::Polygon2DEditor() { point_drag_index = -1; uv_drag = false; uv_create = false; - updating_uv_scroll = false; bone_painting = false; error = memnew(AcceptDialog); diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index 8c52984b59..164aa3eccc 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -35,6 +35,7 @@ class AcceptDialog; class ButtonGroup; +class EditorZoomWidget; class HScrollBar; class HSlider; class Label; @@ -85,12 +86,10 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { Panel *uv_edit_background = nullptr; Polygon2D *preview_polygon = nullptr; Control *uv_edit_draw = nullptr; - HSlider *uv_zoom = nullptr; - SpinBox *uv_zoom_value = nullptr; + EditorZoomWidget *zoom_widget = nullptr; HScrollBar *uv_hscroll = nullptr; VScrollBar *uv_vscroll = nullptr; MenuButton *uv_menu = nullptr; - TextureRect *uv_icon_zoom = nullptr; Ref<ViewPanner> uv_panner; void _uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event); @@ -129,7 +128,6 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { Vector<int> polygon_create; UVMode uv_move_current; Vector2 uv_drag_from; - bool updating_uv_scroll; AcceptDialog *error = nullptr; @@ -145,7 +143,8 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { void _cancel_editing(); void _update_polygon_editing_state(); - void _uv_scroll_changed(real_t); + void _center_view(); + void _update_zoom_and_pan(bool p_zoom_at_center); void _uv_input(const Ref<InputEvent> &p_input); void _uv_draw(); void _uv_mode(int p_mode); diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index ee7ad739b8..9b31e40e94 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -34,10 +34,10 @@ #include "core/io/resource_loader.h" #include "editor/editor_interface.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" void ResourcePreloaderEditor::_notification(int p_what) { switch (p_what) { @@ -50,7 +50,7 @@ void ResourcePreloaderEditor::_notification(int p_what) { void ResourcePreloaderEditor::_files_load_request(const Vector<String> &p_paths) { for (int i = 0; i < p_paths.size(); i++) { - String path = p_paths[i]; + const String &path = p_paths[i]; Ref<Resource> resource; resource = ResourceLoader::load(path); diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index bc6507155a..13928710bb 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -31,7 +31,8 @@ #include "root_motion_editor_plugin.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" +#include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_mixer.h" #include "scene/gui/button.h" #include "scene/gui/dialogs.h" diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index c1a65b7bb7..55191f44d4 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -45,7 +45,6 @@ #include "editor/editor_interface.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_script.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" @@ -58,6 +57,7 @@ #include "editor/node_dock.h" #include "editor/plugins/shader_editor_plugin.h" #include "editor/plugins/text_shader_editor.h" +#include "editor/themes/editor_scale.h" #include "editor/window_wrapper.h" #include "scene/main/node.h" #include "scene/main/window.h" @@ -733,7 +733,7 @@ void ScriptEditor::_open_recent_script(int p_idx) { // clear button if (p_idx == recent_scripts->get_item_count() - 1) { EditorSettings::get_singleton()->set_project_metadata("recent_files", "scripts", Array()); - call_deferred(SNAME("_update_recent_scripts")); + callable_mp(this, &ScriptEditor::_update_recent_scripts).call_deferred(); return; } @@ -1001,7 +1001,10 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource> &p_res) { } _update_script_names(); - trigger_live_script_reload(); + Ref<Script> scr = p_res; + if (scr.is_valid()) { + trigger_live_script_reload(scr->get_path()); + } } void ScriptEditor::_scene_saved_callback(const String &p_path) { @@ -1029,16 +1032,33 @@ void ScriptEditor::_scene_saved_callback(const String &p_path) { } } -void ScriptEditor::trigger_live_script_reload() { +void ScriptEditor::trigger_live_script_reload(const String &p_script_path) { + if (!script_paths_to_reload.has(p_script_path)) { + script_paths_to_reload.append(p_script_path); + } + if (!pending_auto_reload && auto_reload_running_scripts) { + callable_mp(this, &ScriptEditor::_live_auto_reload_running_scripts).call_deferred(); + pending_auto_reload = true; + } +} + +void ScriptEditor::trigger_live_script_reload_all() { if (!pending_auto_reload && auto_reload_running_scripts) { call_deferred(SNAME("_live_auto_reload_running_scripts")); pending_auto_reload = true; + reload_all_scripts = true; } } void ScriptEditor::_live_auto_reload_running_scripts() { pending_auto_reload = false; - EditorDebuggerNode::get_singleton()->reload_scripts(); + if (reload_all_scripts) { + EditorDebuggerNode::get_singleton()->reload_all_scripts(); + } else { + EditorDebuggerNode::get_singleton()->reload_scripts(script_paths_to_reload); + } + reload_all_scripts = false; + script_paths_to_reload.clear(); } bool ScriptEditor::_test_script_times_on_disk(Ref<Resource> p_for_script) { @@ -1082,7 +1102,7 @@ bool ScriptEditor::_test_script_times_on_disk(Ref<Resource> p_for_script) { script_editor->reload_scripts(); need_reload = false; } else { - disk_changed->call_deferred(SNAME("popup_centered_ratio"), 0.3); + callable_mp((Window *)disk_changed, &Window::popup_centered_ratio).call_deferred(0.3); } } @@ -2873,7 +2893,7 @@ void ScriptEditor::_tree_changed() { } waiting_update_names = true; - call_deferred(SNAME("_update_script_names")); + callable_mp(this, &ScriptEditor::_update_script_names).call_deferred(); } void ScriptEditor::_split_dragged(float) { @@ -2963,7 +2983,7 @@ bool ScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data } for (int i = 0; i < files.size(); i++) { - String file = files[i]; + const String &file = files[i]; if (file.is_empty() || !FileAccess::exists(file)) { continue; } @@ -3043,7 +3063,7 @@ void ScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Co } int num_tabs_before = tab_container->get_tab_count(); for (int i = 0; i < files.size(); i++) { - String file = files[i]; + const String &file = files[i]; if (file.is_empty() || !FileAccess::exists(file)) { continue; } @@ -3386,7 +3406,6 @@ void ScriptEditor::_help_class_goto(const String &p_desc) { eh->set_name(cname); tab_container->add_child(eh); - _go_to_tab(tab_container->get_tab_count() - 1); eh->go_to_help(p_desc); eh->connect("go_to_help", callable_mp(this, &ScriptEditor::_help_class_goto)); _add_recent_script(eh->get_class()); @@ -3394,7 +3413,7 @@ void ScriptEditor::_help_class_goto(const String &p_desc) { _update_script_names(); _save_layout(); - call_deferred("_help_tab_goto", cname, p_desc); + callable_mp(this, &ScriptEditor::_help_tab_goto).call_deferred(cname, p_desc); } bool ScriptEditor::_help_tab_goto(const String &p_name, const String &p_desc) { @@ -3792,18 +3811,7 @@ void ScriptEditor::_filter_methods_text_changed(const String &p_newtext) { } void ScriptEditor::_bind_methods() { - ClassDB::bind_method("_close_docs_tab", &ScriptEditor::_close_docs_tab); - ClassDB::bind_method("_close_all_tabs", &ScriptEditor::_close_all_tabs); - ClassDB::bind_method("_close_other_tabs", &ScriptEditor::_close_other_tabs); - ClassDB::bind_method("_goto_script_line2", &ScriptEditor::_goto_script_line2); - ClassDB::bind_method("_copy_script_path", &ScriptEditor::_copy_script_path); - - ClassDB::bind_method("_help_class_open", &ScriptEditor::_help_class_open); ClassDB::bind_method("_help_tab_goto", &ScriptEditor::_help_tab_goto); - ClassDB::bind_method("_live_auto_reload_running_scripts", &ScriptEditor::_live_auto_reload_running_scripts); - ClassDB::bind_method("_update_members_overview", &ScriptEditor::_update_members_overview); - ClassDB::bind_method("_update_recent_scripts", &ScriptEditor::_update_recent_scripts); - ClassDB::bind_method("get_current_editor", &ScriptEditor::_get_current_editor); ClassDB::bind_method("get_open_script_editors", &ScriptEditor::_get_open_script_editors); @@ -3860,6 +3868,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) { scripts_vbox->add_child(filter_scripts); script_list = memnew(ItemList); + script_list->set_auto_translate(false); scripts_vbox->add_child(script_list); script_list->set_custom_minimum_size(Size2(150, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing script_list->set_v_size_flags(SIZE_EXPAND_FILL); @@ -3904,6 +3913,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) { overview_vbox->add_child(filter_methods); members_overview = memnew(ItemList); + members_overview->set_auto_translate(false); overview_vbox->add_child(members_overview); members_overview->set_allow_reselect(true); @@ -3912,6 +3922,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) { members_overview->set_allow_rmb_select(true); help_overview = memnew(ItemList); + help_overview->set_auto_translate(false); overview_vbox->add_child(help_overview); help_overview->set_allow_reselect(true); help_overview->set_custom_minimum_size(Size2(0, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 4a814ea1bc..68eb23c838 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -382,6 +382,8 @@ class ScriptEditor : public PanelContainer { bool pending_auto_reload; bool auto_reload_running_scripts; + bool reload_all_scripts = false; + Vector<String> script_paths_to_reload; void _live_auto_reload_running_scripts(); void _update_selected_editor_menu(); @@ -542,7 +544,8 @@ public: void clear_docs_from_script(const Ref<Script> &p_script); void update_docs_from_script(const Ref<Script> &p_script); - void trigger_live_script_reload(); + void trigger_live_script_reload(const String &p_script_path); + void trigger_live_script_reload_all(); bool can_take_away_focus() const; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index eb934da4dd..5bd6f83616 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -36,10 +36,10 @@ #include "editor/debugger/editor_debugger_node.h" #include "editor/editor_command_palette.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_toaster.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/rich_text_label.h" #include "scene/gui/split_container.h" @@ -788,9 +788,7 @@ static void _find_changed_scripts_for_external_editor(Node *p_base, Node *p_curr } void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_for_script) { - if (!bool(EDITOR_GET("text_editor/external/use_external_editor"))) { - return; - } + bool use_external_editor = bool(EDITOR_GET("text_editor/external/use_external_editor")); ERR_FAIL_NULL(get_tree()); @@ -804,6 +802,10 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo for (const Ref<Script> &E : scripts) { Ref<Script> scr = E; + if (!use_external_editor && !scr->get_language()->overrides_external_editor()) { + continue; // We're not using an external editor for this script. + } + if (p_for_script.is_valid() && p_for_script != scr) { continue; } @@ -822,7 +824,7 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo scr->set_last_modified_time(rel_scr->get_last_modified_time()); scr->update_exports(); - trigger_live_script_reload(); + trigger_live_script_reload(scr->get_path()); } } } @@ -884,7 +886,7 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) { _edit_option(breakpoints_menu->get_item_id(p_idx)); } else { code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx)); - code_editor->get_text_editor()->call_deferred(SNAME("center_viewport_to_caret")); //Need to be deferred, because goto uses call_deferred(). + callable_mp((TextEdit *)code_editor->get_text_editor(), &TextEdit::center_viewport_to_caret).call_deferred(0); // Needs to be deferred, because goto uses call_deferred(). } } @@ -1271,27 +1273,27 @@ void ScriptTextEditor::_edit_option(int p_op) { switch (p_op) { case EDIT_UNDO: { tx->undo(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_REDO: { tx->redo(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_CUT: { tx->cut(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_COPY: { tx->copy(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_PASTE: { tx->paste(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_SELECT_ALL: { tx->select_all(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_MOVE_LINE_UP: { code_editor->move_lines_up(); @@ -1409,7 +1411,7 @@ void ScriptTextEditor::_edit_option(int p_op) { PackedStringArray results; for (int i = 0; i < lines.size(); i++) { - String line = lines[i]; + const String &line = lines[i]; String whitespace = line.substr(0, line.size() - line.strip_edges(true, false).size()); // Extract the whitespace at the beginning. if (expression.parse(line) == OK) { Variant result = expression.execute(Array(), Variant(), false, true); @@ -2447,7 +2449,7 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/indent", TTR("Indent"), Key::NONE); ED_SHORTCUT("script_text_editor/unindent", TTR("Unindent"), KeyModifierMask::SHIFT | Key::TAB); - ED_SHORTCUT_ARRAY("script_text_editor/toggle_comment", TTR("Toggle Comment"), { int32_t(KeyModifierMask::CMD_OR_CTRL | Key::K), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::SLASH) }); + ED_SHORTCUT_ARRAY("script_text_editor/toggle_comment", TTR("Toggle Comment"), { int32_t(KeyModifierMask::CMD_OR_CTRL | Key::K), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::SLASH), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KP_DIVIDE), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::NUMBERSIGN) }); ED_SHORTCUT("script_text_editor/toggle_fold_line", TTR("Fold/Unfold Line"), KeyModifierMask::ALT | Key::F); ED_SHORTCUT_OVERRIDE("script_text_editor/toggle_fold_line", "macos", KeyModifierMask::CTRL | KeyModifierMask::META | Key::F); ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), Key::NONE); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 9da201f9f1..5798ff9d99 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -32,7 +32,6 @@ #include "editor/editor_command_palette.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" @@ -40,6 +39,7 @@ #include "editor/plugins/text_shader_editor.h" #include "editor/plugins/visual_shader_editor_plugin.h" #include "editor/shader_create_dialog.h" +#include "editor/themes/editor_scale.h" #include "editor/window_wrapper.h" #include "scene/gui/item_list.h" #include "scene/gui/texture_rect.h" @@ -84,7 +84,8 @@ void ShaderEditorPlugin::_update_shader_list() { Ref<Texture2D> icon = shader_list->get_editor_theme_icon(_class); shader_list->add_item(text, icon); - shader_list->set_item_tooltip(shader_list->get_item_count() - 1, path); + shader_list->set_item_tooltip(-1, path); + edited_shader.name = text; } if (shader_tabs->get_tab_count()) { @@ -292,11 +293,6 @@ void ShaderEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) { } String ShaderEditorPlugin::get_unsaved_status(const String &p_for_scene) const { - if (!p_for_scene.is_empty()) { - // TODO: handle built-in shaders. - return String(); - } - // TODO: This should also include visual shaders and shader includes, but save_external_data() doesn't seem to save them... PackedStringArray unsaved_shaders; for (uint32_t i = 0; i < edited_shaders.size(); i++) { @@ -305,10 +301,30 @@ String ShaderEditorPlugin::get_unsaved_status(const String &p_for_scene) const { if (unsaved_shaders.is_empty()) { unsaved_shaders.append(TTR("Save changes to the following shaders(s) before quitting?")); } - unsaved_shaders.append(edited_shaders[i].shader_editor->get_name()); + unsaved_shaders.append(edited_shaders[i].name.trim_suffix("(*)")); + } + } + } + + if (!p_for_scene.is_empty()) { + PackedStringArray unsaved_built_in_shaders; + + const String scene_file = p_for_scene.get_file(); + for (const String &E : unsaved_shaders) { + if (!E.is_resource_file() && E.contains(scene_file)) { + if (unsaved_built_in_shaders.is_empty()) { + unsaved_built_in_shaders.append(TTR("There are unsaved changes in the following built-in shaders(s):")); + } + unsaved_built_in_shaders.append(E); } } + + if (!unsaved_built_in_shaders.is_empty()) { + return String("\n").join(unsaved_built_in_shaders); + } + return String(); } + return String("\n").join(unsaved_shaders); } @@ -517,7 +533,7 @@ bool ShaderEditorPlugin::can_drop_data_fw(const Point2 &p_point, const Variant & } for (int i = 0; i < files.size(); i++) { - String file = files[i]; + const String &file = files[i]; if (ResourceLoader::exists(file, "Shader")) { Ref<Shader> shader = ResourceLoader::load(file); if (shader.is_valid()) { @@ -558,7 +574,7 @@ void ShaderEditorPlugin::drop_data_fw(const Point2 &p_point, const Variant &p_da Vector<String> files = d["files"]; for (int i = 0; i < files.size(); i++) { - String file = files[i]; + const String &file = files[i]; Ref<Resource> res; if (ResourceLoader::exists(file, "Shader") || ResourceLoader::exists(file, "ShaderInclude")) { res = ResourceLoader::load(file); @@ -586,6 +602,7 @@ void ShaderEditorPlugin::_file_removed(const String &p_removed_file) { void ShaderEditorPlugin::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { + EditorNode::get_singleton()->connect("resource_saved", callable_mp(this, &ShaderEditorPlugin::_resource_saved), CONNECT_DEFERRED); EditorNode::get_singleton()->connect("scene_closed", callable_mp(this, &ShaderEditorPlugin::_close_builtin_shaders_from_scene)); FileSystemDock::get_singleton()->connect("file_removed", callable_mp(this, &ShaderEditorPlugin::_file_removed)); } break; @@ -641,6 +658,7 @@ ShaderEditorPlugin::ShaderEditorPlugin() { } shader_list = memnew(ItemList); + shader_list->set_auto_translate(false); shader_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); vb->add_child(shader_list); shader_list->connect("item_selected", callable_mp(this, &ShaderEditorPlugin::_shader_selected)); @@ -660,9 +678,6 @@ ShaderEditorPlugin::ShaderEditorPlugin() { button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Shader Editor"), window_wrapper); - // Defer connect because Editor class is not in the binding system yet. - EditorNode::get_singleton()->call_deferred("connect", "resource_saved", callable_mp(this, &ShaderEditorPlugin::_resource_saved), CONNECT_DEFERRED); - shader_create_dialog = memnew(ShaderCreateDialog); vb->add_child(shader_create_dialog); shader_create_dialog->connect("shader_created", callable_mp(this, &ShaderEditorPlugin::_shader_created)); diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 073b0ee192..ea50d62b8f 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -55,6 +55,7 @@ class ShaderEditorPlugin : public EditorPlugin { TextShaderEditor *shader_editor = nullptr; VisualShaderEditor *visual_shader_editor = nullptr; String path; + String name; }; LocalVector<EditedShader> edited_shaders; diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp index 11bec4f61c..69ad274114 100644 --- a/editor/plugins/shader_file_editor_plugin.cpp +++ b/editor/plugins/shader_file_editor_plugin.cpp @@ -35,9 +35,9 @@ #include "core/os/keyboard.h" #include "core/os/os.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/item_list.h" #include "scene/gui/split_container.h" #include "servers/display_server.h" @@ -256,6 +256,7 @@ ShaderFileEditor::ShaderFileEditor() { add_child(main_hs); versions = memnew(ItemList); + versions->set_auto_translate(false); versions->connect("item_selected", callable_mp(this, &ShaderFileEditor::_version_selected)); versions->set_custom_minimum_size(Size2i(200 * EDSCALE, 0)); main_hs->add_child(versions); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 9a709e8dda..53fdde9e14 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -34,12 +34,12 @@ #include "editor/editor_node.h" #include "editor/editor_properties.h" #include "editor/editor_properties_vector.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/animation_player_editor_plugin.h" -#include "node_3d_editor_plugin.h" +#include "editor/plugins/node_3d_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/3d/collision_shape_3d.h" #include "scene/3d/joint_3d.h" #include "scene/3d/mesh_instance_3d.h" @@ -837,10 +837,10 @@ void Skeleton3DEditor::_notification(int p_what) { joint_tree->connect("item_selected", callable_mp(this, &Skeleton3DEditor::_joint_tree_selection_changed)); joint_tree->connect("item_mouse_selected", callable_mp(this, &Skeleton3DEditor::_joint_tree_rmb_select)); #ifdef TOOLS_ENABLED - skeleton->connect("pose_updated", callable_mp(this, &Skeleton3DEditor::_draw_gizmo)); - skeleton->connect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties)); - skeleton->connect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed)); - skeleton->connect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible)); + skeleton->connect(SceneStringNames::get_singleton()->pose_updated, callable_mp(this, &Skeleton3DEditor::_draw_gizmo)); + skeleton->connect(SceneStringNames::get_singleton()->pose_updated, callable_mp(this, &Skeleton3DEditor::_update_properties)); + skeleton->connect(SceneStringNames::get_singleton()->bone_enabled_changed, callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed)); + skeleton->connect(SceneStringNames::get_singleton()->show_rest_only_changed, callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible)); #endif get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Object::CONNECT_ONE_SHOT); @@ -865,10 +865,10 @@ void Skeleton3DEditor::_notification(int p_what) { if (skeleton) { select_bone(-1); // Requires that the joint_tree has not been deleted. #ifdef TOOLS_ENABLED - skeleton->disconnect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible)); - skeleton->disconnect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed)); - skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_draw_gizmo)); - skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties)); + skeleton->disconnect(SceneStringNames::get_singleton()->show_rest_only_changed, callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible)); + skeleton->disconnect(SceneStringNames::get_singleton()->bone_enabled_changed, callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed)); + skeleton->disconnect(SceneStringNames::get_singleton()->pose_updated, callable_mp(this, &Skeleton3DEditor::_draw_gizmo)); + skeleton->disconnect(SceneStringNames::get_singleton()->pose_updated, callable_mp(this, &Skeleton3DEditor::_update_properties)); skeleton->set_transform_gizmo_visible(true); #endif if (handles_mesh_instance->get_parent()) { @@ -889,18 +889,6 @@ void Skeleton3DEditor::_node_removed(Node *p_node) { _update_properties(); } -void Skeleton3DEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_node_removed"), &Skeleton3DEditor::_node_removed); - ClassDB::bind_method(D_METHOD("_joint_tree_selection_changed"), &Skeleton3DEditor::_joint_tree_selection_changed); - ClassDB::bind_method(D_METHOD("_joint_tree_rmb_select"), &Skeleton3DEditor::_joint_tree_rmb_select); - ClassDB::bind_method(D_METHOD("_update_properties"), &Skeleton3DEditor::_update_properties); - ClassDB::bind_method(D_METHOD("_on_click_skeleton_option"), &Skeleton3DEditor::_on_click_skeleton_option); - - ClassDB::bind_method(D_METHOD("move_skeleton_bone"), &Skeleton3DEditor::move_skeleton_bone); - - ClassDB::bind_method(D_METHOD("_draw_gizmo"), &Skeleton3DEditor::_draw_gizmo); -} - void Skeleton3DEditor::edit_mode_toggled(const bool pressed) { edit_mode = pressed; _update_gizmo_visible(); diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h index 3cc7c85492..839061a2fe 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.h +++ b/editor/plugins/skeleton_3d_editor_plugin.h @@ -198,7 +198,6 @@ class Skeleton3DEditor : public VBoxContainer { protected: void _notification(int p_what); void _node_removed(Node *p_node); - static void _bind_methods(); public: static Skeleton3DEditor *get_singleton() { return singleton; } diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp index 7c1c6a8f82..c1e7070451 100644 --- a/editor/plugins/sprite_2d_editor_plugin.cpp +++ b/editor/plugins/sprite_2d_editor_plugin.cpp @@ -33,15 +33,19 @@ #include "canvas_item_editor_plugin.h" #include "core/math/geometry_2d.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/gui/editor_zoom_widget.h" #include "editor/scene_tree_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/collision_polygon_2d.h" #include "scene/2d/light_occluder_2d.h" #include "scene/2d/mesh_instance_2d.h" #include "scene/2d/polygon_2d.h" #include "scene/gui/box_container.h" #include "scene/gui/menu_button.h" +#include "scene/gui/panel.h" +#include "scene/gui/view_panner.h" #include "thirdparty/misc/clipper.hpp" void Sprite2DEditor::_node_removed(Node *p_node) { @@ -168,6 +172,8 @@ void Sprite2DEditor::_popup_debug_uv_dialog() { _update_mesh_data(); debug_uv_dialog->popup_centered(); + get_tree()->connect("process_frame", callable_mp(this, &Sprite2DEditor::_center_view), CONNECT_ONE_SHOT); + debug_uv->set_texture_filter(node->get_texture_filter_in_tree()); debug_uv->queue_redraw(); } @@ -460,17 +466,19 @@ void Sprite2DEditor::_add_as_sibling_or_child(Node *p_own_node, Node *p_new_node p_new_node->set_owner(this->get_tree()->get_edited_scene_root()); } +void Sprite2DEditor::_debug_uv_input(const Ref<InputEvent> &p_input) { + if (panner->gui_input(p_input)) { + accept_event(); + } +} + void Sprite2DEditor::_debug_uv_draw() { + debug_uv->draw_set_transform(-draw_offset * draw_zoom, 0, Vector2(draw_zoom, draw_zoom)); + Ref<Texture2D> tex = node->get_texture(); ERR_FAIL_COND(!tex.is_valid()); - Point2 draw_pos_offset = Point2(1.0, 1.0); - Size2 draw_size_offset = Size2(2.0, 2.0); - - debug_uv->set_clip_contents(true); - debug_uv->draw_texture(tex, draw_pos_offset); - debug_uv->set_custom_minimum_size(tex->get_size() + draw_size_offset); - debug_uv->draw_set_transform(draw_pos_offset, 0, Size2(1.0, 1.0)); + debug_uv->draw_texture(tex, Point2()); Color color = Color(1.0, 0.8, 0.7); @@ -487,8 +495,86 @@ void Sprite2DEditor::_debug_uv_draw() { } } +void Sprite2DEditor::_center_view() { + Ref<Texture2D> tex = node->get_texture(); + ERR_FAIL_COND(!tex.is_valid()); + Vector2 zoom_factor = (debug_uv->get_size() - Vector2(1, 1) * 50 * EDSCALE) / tex->get_size(); + zoom_widget->set_zoom(MIN(zoom_factor.x, zoom_factor.y)); + // Recalculate scroll limits. + _update_zoom_and_pan(false); + + Vector2 offset = (tex->get_size() - debug_uv->get_size() / zoom_widget->get_zoom()) / 2; + h_scroll->set_value_no_signal(offset.x); + v_scroll->set_value_no_signal(offset.y); + _update_zoom_and_pan(false); +} + +void Sprite2DEditor::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) { + h_scroll->set_value_no_signal(h_scroll->get_value() - p_scroll_vec.x / draw_zoom); + v_scroll->set_value_no_signal(v_scroll->get_value() - p_scroll_vec.y / draw_zoom); + _update_zoom_and_pan(false); +} + +void Sprite2DEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) { + const real_t prev_zoom = draw_zoom; + zoom_widget->set_zoom(draw_zoom * p_zoom_factor); + draw_offset += p_origin / prev_zoom - p_origin / zoom_widget->get_zoom(); + h_scroll->set_value_no_signal(draw_offset.x); + v_scroll->set_value_no_signal(draw_offset.y); + _update_zoom_and_pan(false); +} + +void Sprite2DEditor::_update_zoom_and_pan(bool p_zoom_at_center) { + real_t previous_zoom = draw_zoom; + draw_zoom = zoom_widget->get_zoom(); + draw_offset = Vector2(h_scroll->get_value(), v_scroll->get_value()); + if (p_zoom_at_center) { + Vector2 center = debug_uv->get_size() / 2; + draw_offset += center / previous_zoom - center / draw_zoom; + } + + Ref<Texture2D> tex = node->get_texture(); + ERR_FAIL_COND(!tex.is_valid()); + + Point2 min_corner; + Point2 max_corner = tex->get_size(); + Size2 page_size = debug_uv->get_size() / draw_zoom; + Vector2 margin = Vector2(50, 50) * EDSCALE / draw_zoom; + min_corner -= page_size - margin; + max_corner += page_size - margin; + + h_scroll->set_block_signals(true); + h_scroll->set_min(min_corner.x); + h_scroll->set_max(max_corner.x); + h_scroll->set_page(page_size.x); + h_scroll->set_value(draw_offset.x); + h_scroll->set_block_signals(false); + + v_scroll->set_block_signals(true); + v_scroll->set_min(min_corner.y); + v_scroll->set_max(max_corner.y); + v_scroll->set_page(page_size.y); + v_scroll->set_value(draw_offset.y); + v_scroll->set_block_signals(false); + + debug_uv->queue_redraw(); +} + void Sprite2DEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_READY: { + v_scroll->set_anchors_and_offsets_preset(Control::PRESET_RIGHT_WIDE); + h_scroll->set_anchors_and_offsets_preset(Control::PRESET_BOTTOM_WIDE); + // Avoid scrollbar overlapping. + Size2 hmin = h_scroll->get_combined_minimum_size(); + Size2 vmin = v_scroll->get_combined_minimum_size(); + h_scroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, -vmin.width); + v_scroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -hmin.height); + [[fallthrough]]; + } + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EDITOR_GET("editors/panning/simple_panning"))); + } break; case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { options->set_icon(get_editor_theme_icon(SNAME("Sprite2D"))); @@ -526,12 +612,29 @@ Sprite2DEditor::Sprite2DEditor() { debug_uv_dialog = memnew(ConfirmationDialog); VBoxContainer *vb = memnew(VBoxContainer); debug_uv_dialog->add_child(vb); - ScrollContainer *scroll = memnew(ScrollContainer); - scroll->set_custom_minimum_size(Size2(800, 500) * EDSCALE); - vb->add_margin_child(TTR("Preview:"), scroll, true); - debug_uv = memnew(Control); + debug_uv = memnew(Panel); + debug_uv->connect("gui_input", callable_mp(this, &Sprite2DEditor::_debug_uv_input)); debug_uv->connect("draw", callable_mp(this, &Sprite2DEditor::_debug_uv_draw)); - scroll->add_child(debug_uv); + debug_uv->set_custom_minimum_size(Size2(800, 500) * EDSCALE); + debug_uv->set_clip_contents(true); + vb->add_margin_child(TTR("Preview:"), debug_uv, true); + + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &Sprite2DEditor::_pan_callback), callable_mp(this, &Sprite2DEditor::_zoom_callback)); + + zoom_widget = memnew(EditorZoomWidget); + debug_uv->add_child(zoom_widget); + zoom_widget->set_anchors_and_offsets_preset(Control::PRESET_TOP_LEFT, Control::PRESET_MODE_MINSIZE, 2 * EDSCALE); + zoom_widget->connect("zoom_changed", callable_mp(this, &Sprite2DEditor::_update_zoom_and_pan).unbind(1).bind(true)); + zoom_widget->set_shortcut_context(nullptr); + + v_scroll = memnew(VScrollBar); + debug_uv->add_child(v_scroll); + v_scroll->connect("value_changed", callable_mp(this, &Sprite2DEditor::_update_zoom_and_pan).unbind(1).bind(false)); + h_scroll = memnew(HScrollBar); + debug_uv->add_child(h_scroll); + h_scroll->connect("value_changed", callable_mp(this, &Sprite2DEditor::_update_zoom_and_pan).unbind(1).bind(false)); + debug_uv_dialog->connect("confirmed", callable_mp(this, &Sprite2DEditor::_create_node)); HBoxContainer *hb = memnew(HBoxContainer); diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h index 52e4b2b264..1121481341 100644 --- a/editor/plugins/sprite_2d_editor_plugin.h +++ b/editor/plugins/sprite_2d_editor_plugin.h @@ -37,7 +37,10 @@ class AcceptDialog; class ConfirmationDialog; +class EditorZoomWidget; class MenuButton; +class Panel; +class ViewPanner; class Sprite2DEditor : public Control { GDCLASS(Sprite2DEditor, Control); @@ -60,7 +63,7 @@ class Sprite2DEditor : public Control { AcceptDialog *err_dialog = nullptr; ConfirmationDialog *debug_uv_dialog = nullptr; - Control *debug_uv = nullptr; + Panel *debug_uv = nullptr; Vector<Vector2> uv_lines; Vector<Vector<Vector2>> outline_lines; Vector<Vector<Vector2>> computed_outline_lines; @@ -68,6 +71,13 @@ class Sprite2DEditor : public Control { Vector<Vector2> computed_uv; Vector<int> computed_indices; + HScrollBar *h_scroll = nullptr; + VScrollBar *v_scroll = nullptr; + EditorZoomWidget *zoom_widget = nullptr; + Ref<ViewPanner> panner; + Vector2 draw_offset; + real_t draw_zoom = 1.0; + SpinBox *simplification = nullptr; SpinBox *grow_pixels = nullptr; SpinBox *shrink_pixels = nullptr; @@ -78,8 +88,13 @@ class Sprite2DEditor : public Control { //void _create_uv_lines(); friend class Sprite2DEditorPlugin; + void _debug_uv_input(const Ref<InputEvent> &p_input); void _debug_uv_draw(); void _popup_debug_uv_dialog(); + void _center_view(); + void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event); + void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event); + void _update_zoom_and_pan(bool p_zoom_at_center); void _update_mesh_data(); void _create_node(); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index a1241ae662..3672142b35 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -35,12 +35,12 @@ #include "core/os/keyboard.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" #include "editor/scene_tree_dock.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/center_container.h" #include "scene/gui/flow_container.h" #include "scene/gui/margin_container.h" @@ -1425,7 +1425,7 @@ bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant & } for (int i = 0; i < files.size(); i++) { - String f = files[i]; + const String &f = files[i]; String ftype = EditorFileSystem::get_singleton()->get_file_type(f); if (!ClassDB::is_parent_class(ftype, "Texture2D")) { @@ -1880,6 +1880,7 @@ SpriteFramesEditor::SpriteFramesEditor() { add_child(file); frame_list = memnew(ItemList); + frame_list->set_auto_translate(false); frame_list->set_v_size_flags(SIZE_EXPAND_FILL); frame_list->set_icon_mode(ItemList::ICON_MODE_TOP); frame_list->set_texture_filter(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp index 9b1c208a9f..6ecbff3bb4 100644 --- a/editor/plugins/style_box_editor_plugin.cpp +++ b/editor/plugins/style_box_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "style_box_editor_plugin.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/resources/style_box_texture.h" diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index c7945e44f0..475aba0eeb 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -352,27 +352,27 @@ void TextEditor::_edit_option(int p_op) { switch (p_op) { case EDIT_UNDO: { tx->undo(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_REDO: { tx->redo(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_CUT: { tx->cut(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_COPY: { tx->copy(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_PASTE: { tx->paste(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_SELECT_ALL: { tx->select_all(); - tx->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)tx, &Control::grab_focus).call_deferred(); } break; case EDIT_MOVE_LINE_UP: { code_editor->move_lines_up(); diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp index 3a2ddeb94e..98d83b6e95 100644 --- a/editor/plugins/text_shader_editor.cpp +++ b/editor/plugins/text_shader_editor.cpp @@ -32,11 +32,11 @@ #include "core/version_generated.gen.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/filesystem_dock.h" #include "editor/project_settings_editor.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/split_container.h" #include "servers/rendering/shader_preprocessor.h" #include "servers/rendering/shader_types.h" @@ -170,8 +170,8 @@ void ShaderTextEditor::set_edited_code(const String &p_code) { get_text_editor()->set_text(p_code); get_text_editor()->clear_undo_history(); - get_text_editor()->call_deferred(SNAME("set_h_scroll"), 0); - get_text_editor()->call_deferred(SNAME("set_v_scroll"), 0); + callable_mp((TextEdit *)get_text_editor(), &TextEdit::set_h_scroll).call_deferred(0); + callable_mp((TextEdit *)get_text_editor(), &TextEdit::set_v_scroll).call_deferred(0); get_text_editor()->tag_saved_version(); _validate_script(); @@ -719,7 +719,7 @@ void TextShaderEditor::_menu_option(int p_option) { } break; } if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) { - shader_editor->get_text_editor()->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)shader_editor->get_text_editor(), &Control::grab_focus).call_deferred(); } } @@ -820,7 +820,7 @@ void TextShaderEditor::_check_for_external_edit() { if (use_autoreload) { _reload_shader_include_from_disk(); } else { - disk_changed->call_deferred(SNAME("popup_centered")); + callable_mp((Window *)disk_changed, &Window::popup_centered).call_deferred(Size2i()); } } return; @@ -834,7 +834,7 @@ void TextShaderEditor::_check_for_external_edit() { if (use_autoreload) { _reload_shader_from_disk(); } else { - disk_changed->call_deferred(SNAME("popup_centered")); + callable_mp((Window *)disk_changed, &Window::popup_centered).call_deferred(Size2i()); } } } diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index ec5785e605..38d9bb84f4 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -30,14 +30,15 @@ #include "texture_editor_plugin.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/label.h" #include "scene/gui/texture_rect.h" #include "scene/resources/animated_texture.h" #include "scene/resources/atlas_texture.h" #include "scene/resources/compressed_texture.h" #include "scene/resources/image_texture.h" +#include "scene/resources/portable_compressed_texture.h" TextureRect *TexturePreview::get_texture_display() { return texture_display; @@ -158,7 +159,7 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) { } bool EditorInspectorPluginTexture::can_handle(Object *p_object) { - return Object::cast_to<ImageTexture>(p_object) != nullptr || Object::cast_to<AtlasTexture>(p_object) != nullptr || Object::cast_to<CompressedTexture2D>(p_object) != nullptr || Object::cast_to<AnimatedTexture>(p_object) != nullptr || Object::cast_to<Image>(p_object) != nullptr; + return Object::cast_to<ImageTexture>(p_object) != nullptr || Object::cast_to<AtlasTexture>(p_object) != nullptr || Object::cast_to<CompressedTexture2D>(p_object) != nullptr || Object::cast_to<PortableCompressedTexture2D>(p_object) != nullptr || Object::cast_to<AnimatedTexture>(p_object) != nullptr || Object::cast_to<Image>(p_object) != nullptr; } void EditorInspectorPluginTexture::parse_begin(Object *p_object) { diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 73de15631a..09f6bf884e 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -33,10 +33,10 @@ #include "core/input/input.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_box.h" #include "scene/gui/option_button.h" #include "scene/gui/panel_container.h" diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 6c153f6113..8c3fe82f36 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -34,12 +34,12 @@ #include "editor/editor_help.h" #include "editor/editor_node.h" #include "editor/editor_resource_picker.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" #include "editor/inspector_dock.h" #include "editor/progress_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_button.h" #include "scene/gui/color_picker.h" #include "scene/gui/item_list.h" @@ -852,10 +852,9 @@ bool ThemeItemImportTree::has_selected_items() const { void ThemeItemImportTree::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { select_icons_warning_icon->set_texture(get_editor_theme_icon(SNAME("StatusWarning"))); - select_icons_warning->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + select_icons_warning->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); import_items_filter->set_right_icon(get_editor_theme_icon(SNAME("Search"))); @@ -2247,6 +2246,7 @@ ThemeTypeDialog::ThemeTypeDialog() { add_type_vb->add_child(add_type_options_label); add_type_options = memnew(ItemList); + add_type_options->set_auto_translate(false); add_type_options->set_v_size_flags(Control::SIZE_EXPAND_FILL); add_type_vb->add_child(add_type_options); add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeDialog::_add_type_options_cbk)); @@ -2373,7 +2373,7 @@ void ThemeTypeEditor::_update_type_list_debounced() { update_debounce_timer->start(); } -HashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) { +HashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(const StringName &, List<StringName> *) const, bool include_default) { HashMap<StringName, bool> items; List<StringName> names; @@ -2469,7 +2469,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled).bind(p_data_type, p_item_name, item_name_container)); item_rename_cancel_button->hide(); } else { - item_name->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + item_name->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); Button *item_override_button = memnew(Button); item_override_button->set_icon(get_editor_theme_icon(SNAME("Add"))); diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index cf8c5ceb28..8ad262da55 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -373,7 +373,7 @@ class ThemeTypeEditor : public MarginContainer { VBoxContainer *_create_item_list(Theme::DataType p_data_type); void _update_type_list(); void _update_type_list_debounced(); - HashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default); + HashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(const StringName &, List<StringName> *) const, bool include_default); HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable); void _add_focusable(Control *p_control); void _update_type_items(); diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp index 9825be9ae8..205a5e8a20 100644 --- a/editor/plugins/theme_editor_preview.cpp +++ b/editor/plugins/theme_editor_preview.cpp @@ -34,8 +34,8 @@ #include "core/input/input.h" #include "core/math/math_funcs.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/gui/check_box.h" #include "scene/gui/check_button.h" diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp index b91f32775f..d03445b412 100644 --- a/editor/plugins/tiles/atlas_merging_dialog.cpp +++ b/editor/plugins/tiles/atlas_merging_dialog.cpp @@ -31,9 +31,9 @@ #include "atlas_merging_dialog.h" #include "editor/editor_properties_vector.h" -#include "editor/editor_scale.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/control.h" #include "scene/gui/split_container.h" #include "scene/resources/image_texture.h" @@ -52,7 +52,7 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla // Compute the new texture region size. Vector2i new_texture_region_size; for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) { - Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index]; + const Ref<TileSetAtlasSource> &atlas_source = p_atlas_sources[source_index]; new_texture_region_size = new_texture_region_size.max(atlas_source->get_texture_region_size()); } @@ -60,7 +60,7 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla Vector2i atlas_offset; int line_height = 0; for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) { - Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index]; + const Ref<TileSetAtlasSource> &atlas_source = p_atlas_sources[source_index]; Ref<Image> input_image = atlas_source->get_texture()->get_image(); if (input_image->get_format() != Image::FORMAT_RGBA8) { input_image->convert(Image::FORMAT_RGBA8); @@ -111,7 +111,7 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla // Copy the tiles to the merged TileSetAtlasSource. for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) { - Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index]; + const Ref<TileSetAtlasSource> &atlas_source = p_atlas_sources[source_index]; for (KeyValue<Vector2i, Vector2i> tile_mapping : merged_mapping[source_index]) { // Create tiles and alternatives, then copy their properties. for (int alternative_index = 0; alternative_index < atlas_source->get_alternative_tiles_count(tile_mapping.key); alternative_index++) { @@ -311,6 +311,7 @@ AtlasMergingDialog::AtlasMergingDialog() { // Atlas sources item list. atlas_merging_atlases_list = memnew(ItemList); + atlas_merging_atlases_list->set_auto_translate(false); atlas_merging_atlases_list->set_fixed_icon_size(Size2(60, 60) * EDSCALE); atlas_merging_atlases_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); atlas_merging_atlases_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 039213e545..721186ef82 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -32,15 +32,14 @@ #include "core/input/input.h" #include "core/os/keyboard.h" +#include "editor/editor_settings.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/tile_map.h" #include "scene/gui/box_container.h" #include "scene/gui/label.h" #include "scene/gui/panel.h" #include "scene/gui/view_panner.h" -#include "editor/editor_scale.h" -#include "editor/editor_settings.h" - void TileAtlasView::gui_input(const Ref<InputEvent> &p_event) { if (panner->gui_input(p_event)) { accept_event(); diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 221833d450..bd44c2965b 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -37,10 +37,10 @@ #include "editor/editor_node.h" #include "editor/editor_properties.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/control.h" #include "scene/gui/label.h" @@ -53,7 +53,7 @@ void TileDataEditor::_tile_set_changed_plan_update() { _tile_set_changed_update_needed = true; - call_deferred(SNAME("_tile_set_changed_deferred_update")); + callable_mp(this, &TileDataEditor::_tile_set_changed_deferred_update).call_deferred(); } void TileDataEditor::_tile_set_changed_deferred_update() { @@ -80,8 +80,6 @@ TileData *TileDataEditor::_get_tile_data(TileMapCell p_cell) { } void TileDataEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_tile_set_changed_deferred_update"), &TileDataEditor::_tile_set_changed_deferred_update); - ADD_SIGNAL(MethodInfo("needs_redraw")); } @@ -112,16 +110,16 @@ bool DummyObject::_get(const StringName &p_name, Variant &r_ret) const { return false; } -bool DummyObject::has_dummy_property(StringName p_name) { +bool DummyObject::has_dummy_property(const StringName &p_name) { return properties.has(p_name); } -void DummyObject::add_dummy_property(StringName p_name) { +void DummyObject::add_dummy_property(const StringName &p_name) { ERR_FAIL_COND(properties.has(p_name)); properties[p_name] = Variant(); } -void DummyObject::remove_dummy_property(StringName p_name) { +void DummyObject::remove_dummy_property(const StringName &p_name) { ERR_FAIL_COND(!properties.has(p_name)); properties.erase(p_name); } @@ -719,11 +717,19 @@ void GenericTilePolygonEditor::set_tile_set(Ref<TileSet> p_tile_set) { Vector2 zoomed_tile = editor_zoom_widget->get_zoom() * tile_set->get_tile_size(); while (zoomed_tile.y < default_control_y_size) { editor_zoom_widget->set_zoom_by_increments(6, false); - zoomed_tile = editor_zoom_widget->get_zoom() * tile_set->get_tile_size(); + float current_zoom = editor_zoom_widget->get_zoom(); + zoomed_tile = current_zoom * tile_set->get_tile_size(); + if (Math::is_equal_approx(current_zoom, editor_zoom_widget->get_max_zoom())) { + break; + } } while (zoomed_tile.y > default_control_y_size) { editor_zoom_widget->set_zoom_by_increments(-6, false); - zoomed_tile = editor_zoom_widget->get_zoom() * tile_set->get_tile_size(); + float current_zoom = editor_zoom_widget->get_zoom(); + zoomed_tile = current_zoom * tile_set->get_tile_size(); + if (Math::is_equal_approx(current_zoom, editor_zoom_widget->get_min_zoom())) { + break; + } } editor_zoom_widget->set_zoom_by_increments(-6, false); _zoom_changed(); @@ -948,7 +954,7 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() { _set_snap_option(EditorSettings::get_singleton()->get_project_metadata("editor_metadata", "tile_snap_option", SNAP_NONE)); } -void TileDataDefaultEditor::_property_value_changed(StringName p_property, Variant p_value, StringName p_field) { +void TileDataDefaultEditor::_property_value_changed(const StringName &p_property, Variant p_value, const StringName &p_field) { ERR_FAIL_NULL(dummy_object); dummy_object->set(p_property, p_value); emit_signal(SNAME("needs_redraw")); @@ -981,7 +987,7 @@ Variant TileDataDefaultEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_s return tile_data->get(property); } -void TileDataDefaultEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) { +void TileDataDefaultEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, Variant p_new_value) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { Vector2i coords = E.key.get_atlas_coords(); @@ -1455,7 +1461,7 @@ Variant TileDataOcclusionShapeEditor::_get_value(TileSetAtlasSource *p_tile_set_ return tile_data->get_occluder(occlusion_layer); } -void TileDataOcclusionShapeEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) { +void TileDataOcclusionShapeEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, Variant p_new_value) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { Vector2i coords = E.key.get_atlas_coords(); @@ -1481,11 +1487,11 @@ TileDataOcclusionShapeEditor::TileDataOcclusionShapeEditor() { add_child(polygon_editor); } -void TileDataCollisionEditor::_property_value_changed(StringName p_property, Variant p_value, StringName p_field) { +void TileDataCollisionEditor::_property_value_changed(const StringName &p_property, Variant p_value, const StringName &p_field) { dummy_object->set(p_property, p_value); } -void TileDataCollisionEditor::_property_selected(StringName p_path, int p_focusable) { +void TileDataCollisionEditor::_property_selected(const StringName &p_path, int p_focusable) { // Deselect all other properties for (KeyValue<StringName, EditorProperty *> &editor : property_editors) { if (editor.key != p_path) { @@ -1634,10 +1640,10 @@ Variant TileDataCollisionEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas return dict; } -void TileDataCollisionEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) { +void TileDataCollisionEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, Variant p_new_value) { Dictionary new_dict = p_new_value; EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - for (KeyValue<TileMapCell, Variant> &E : p_previous_values) { + for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { Vector2i coords = E.key.get_atlas_coords(); Dictionary old_dict = E.value; @@ -1802,7 +1808,7 @@ void TileDataTerrainsEditor::_update_terrain_selector() { } } -void TileDataTerrainsEditor::_property_value_changed(StringName p_property, Variant p_value, StringName p_field) { +void TileDataTerrainsEditor::_property_value_changed(const StringName &p_property, Variant p_value, const StringName &p_field) { Variant old_value = dummy_object->get(p_property); dummy_object->set(p_property, p_value); if (p_property == "terrain_set") { @@ -2871,7 +2877,7 @@ Variant TileDataNavigationEditor::_get_value(TileSetAtlasSource *p_tile_set_atla return tile_data->get_navigation_polygon(navigation_layer); } -void TileDataNavigationEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) { +void TileDataNavigationEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, Variant p_new_value) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { Vector2i coords = E.key.get_atlas_coords(); diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h index 4bba5bb467..27fe4316a0 100644 --- a/editor/plugins/tiles/tile_data_editors.h +++ b/editor/plugins/tiles/tile_data_editors.h @@ -82,9 +82,9 @@ protected: bool _get(const StringName &p_name, Variant &r_ret) const; public: - bool has_dummy_property(StringName p_name); - void add_dummy_property(StringName p_name); - void remove_dummy_property(StringName p_name); + bool has_dummy_property(const StringName &p_name); + void add_dummy_property(const StringName &p_name); + void remove_dummy_property(const StringName &p_name); void clear_dummy_properties(); }; @@ -224,7 +224,7 @@ private: HashMap<TileMapCell, Variant, TileMapCell> drag_modified; Variant drag_painted_value; - void _property_value_changed(StringName p_property, Variant p_value, StringName p_field); + void _property_value_changed(const StringName &p_property, Variant p_value, const StringName &p_field); protected: DummyObject *dummy_object = memnew(DummyObject); @@ -238,7 +238,7 @@ protected: virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile); virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value); virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile); - virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value); + virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, Variant p_new_value); public: virtual Control *get_toolbar() override { return toolbar; }; @@ -291,7 +291,7 @@ private: virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override; virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; - virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override; + virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, Variant p_new_value) override; protected: virtual void _tile_set_changed() override; @@ -316,15 +316,15 @@ class TileDataCollisionEditor : public TileDataDefaultEditor { DummyObject *dummy_object = memnew(DummyObject); HashMap<StringName, EditorProperty *> property_editors; - void _property_value_changed(StringName p_property, Variant p_value, StringName p_field); - void _property_selected(StringName p_path, int p_focusable); + void _property_value_changed(const StringName &p_property, Variant p_value, const StringName &p_field); + void _property_selected(const StringName &p_path, int p_focusable); void _polygons_changed(); virtual Variant _get_painted_value() override; virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override; virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; - virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override; + virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, Variant p_new_value) override; protected: virtual void _tile_set_changed() override; @@ -368,7 +368,7 @@ private: EditorPropertyEnum *terrain_set_property_editor = nullptr; EditorPropertyEnum *terrain_property_editor = nullptr; - void _property_value_changed(StringName p_property, Variant p_value, StringName p_field); + void _property_value_changed(const StringName &p_property, Variant p_value, const StringName &p_field); void _update_terrain_selector(); @@ -405,7 +405,7 @@ private: virtual void _set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; virtual void _set_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile, Variant p_value) override; virtual Variant _get_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) override; - virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, HashMap<TileMapCell, Variant, TileMapCell> p_previous_values, Variant p_new_value) override; + virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, const HashMap<TileMapCell, Variant, TileMapCell> &p_previous_values, Variant p_new_value) override; protected: virtual void _tile_set_changed() override; diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 661af16ce8..c34878b54e 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -34,10 +34,10 @@ #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/camera_2d.h" #include "scene/gui/center_container.h" @@ -2421,6 +2421,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { sources_bottom_actions->add_child(source_sort_button); sources_list = memnew(ItemList); + sources_list->set_auto_translate(false); sources_list->set_fixed_icon_size(Size2(60, 60) * EDSCALE); sources_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); sources_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); @@ -2460,6 +2461,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { // Scenes collection source. scene_tiles_list = memnew(ItemList); + scene_tiles_list->set_auto_translate(false); scene_tiles_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); scene_tiles_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); scene_tiles_list->set_select_mode(ItemList::SELECT_MULTI); @@ -2485,6 +2487,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { int thumbnail_size = 64; patterns_item_list = memnew(ItemList); + patterns_item_list->set_auto_translate(false); patterns_item_list->set_max_columns(0); patterns_item_list->set_icon_mode(ItemList::ICON_MODE_TOP); patterns_item_list->set_fixed_column_width(thumbnail_size * 3 / 2); @@ -3560,6 +3563,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { tilemap_tab_terrains->add_child(terrains_tree); terrains_tile_list = memnew(ItemList); + terrains_tile_list->set_auto_translate(false); terrains_tile_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); terrains_tile_list->set_max_columns(0); terrains_tile_list->set_same_column_width(true); diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp index 0e244412ab..4a0b5e2117 100644 --- a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp +++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp @@ -31,9 +31,9 @@ #include "tile_proxies_manager_dialog.h" #include "editor/editor_properties_vector.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/dialogs.h" #include "scene/gui/popup_menu.h" #include "scene/gui/separator.h" @@ -345,6 +345,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() { vbox_container->add_child(source_level_label); source_level_list = memnew(ItemList); + source_level_list->set_auto_translate(false); source_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); source_level_list->set_select_mode(ItemList::SELECT_MULTI); source_level_list->set_allow_rmb_select(true); @@ -356,6 +357,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() { vbox_container->add_child(coords_level_label); coords_level_list = memnew(ItemList); + coords_level_list->set_auto_translate(false); coords_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); coords_level_list->set_select_mode(ItemList::SELECT_MULTI); coords_level_list->set_allow_rmb_select(true); @@ -367,6 +369,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() { vbox_container->add_child(alternative_level_label); alternative_level_list = memnew(ItemList); + alternative_level_list->set_auto_translate(false); alternative_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); alternative_level_list->set_select_mode(ItemList::SELECT_MULTI); alternative_level_list->set_allow_rmb_select(true); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index a3fc6aa5f7..e3710adc83 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -34,13 +34,13 @@ #include "editor/editor_inspector.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_toaster.h" #include "editor/plugins/tiles/tile_set_editor.h" #include "editor/progress_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" @@ -507,7 +507,7 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro } } -void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(Ref<TileSetAtlasSource> p_tile_set_atlas_source, RBSet<TileSelection> p_tiles) { +void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(Ref<TileSetAtlasSource> p_tile_set_atlas_source, const RBSet<TileSelection> &p_tiles) { ERR_FAIL_COND(!p_tile_set_atlas_source.is_valid()); ERR_FAIL_COND(p_tiles.is_empty()); for (const TileSelection &E : p_tiles) { @@ -735,7 +735,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { tile_data_editors["probability"] = tile_data_probability_editor; } - Color disabled_color = get_theme_color("disabled_font_color", EditorStringName(Editor)); + Color disabled_color = get_theme_color("font_disabled_color", EditorStringName(Editor)); // --- Physics --- ADD_TILE_DATA_EDITOR_GROUP(TTR("Physics")); @@ -954,7 +954,7 @@ void TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_pressed() { } void TileSetAtlasSourceEditor::_tile_data_editors_tree_selected() { - tile_data_editors_popup->call_deferred(SNAME("hide")); + callable_mp((Window *)tile_data_editors_popup, &Window::hide).call_deferred(); _update_current_tile_data_editor(); tile_atlas_control->queue_redraw(); tile_atlas_control_unscaled->queue_redraw(); @@ -1869,7 +1869,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() { for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) { Vector2i coords = tile_set_atlas_source->get_tile_id(i); Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(coords); - Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_data(coords, 0)->get_texture_origin(); + Vector2 position = ((Rect2)texture_region).get_center() + tile_set_atlas_source->get_tile_data(coords, 0)->get_texture_origin(); Transform2D xform = tile_atlas_control->get_parent_control()->get_transform(); xform.translate_local(position); @@ -1892,7 +1892,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() { continue; } Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(E.tile); - Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_data(E.tile, 0)->get_texture_origin(); + Vector2 position = ((Rect2)texture_region).get_center() + tile_set_atlas_source->get_tile_data(E.tile, 0)->get_texture_origin(); Transform2D xform = tile_atlas_control->get_parent_control()->get_transform(); xform.translate_local(position); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index 7f6bab804d..e1e6a3113c 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -105,7 +105,7 @@ public: RBSet<TileSelection> get_edited_tiles() const { return tiles; }; // Update the proxyed object. - void edit(Ref<TileSetAtlasSource> p_tile_set_atlas_source, RBSet<TileSelection> p_tiles = RBSet<TileSelection>()); + void edit(Ref<TileSetAtlasSource> p_tile_set_atlas_source, const RBSet<TileSelection> &p_tiles = RBSet<TileSelection>()); AtlasTileProxyObject(TileSetAtlasSourceEditor *p_tiles_set_atlas_source_editor) { tiles_set_atlas_source_editor = p_tiles_set_atlas_source_editor; diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index ef56e66e85..c43995d167 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -36,10 +36,10 @@ #include "editor/editor_file_system.h" #include "editor/editor_inspector.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/control.h" @@ -117,11 +117,11 @@ void TileSetEditor::_load_texture_files(const Vector<String> &p_paths) { // Actually create the new source. Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource); atlas_source->set_texture(texture); + atlas_source->set_texture_region_size(tile_set->get_tile_size()); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Add a new atlas source")); undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id); - undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size()); undo_redo->add_undo_method(*tile_set, "remove_source", source_id); undo_redo->commit_action(); @@ -854,6 +854,7 @@ TileSetEditor::TileSetEditor() { p->set_item_checked(TilesEditorUtils::SOURCE_SORT_ID, true); sources_list = memnew(ItemList); + sources_list->set_auto_translate(false); sources_list->set_fixed_icon_size(Size2(60, 60) * EDSCALE); sources_list->set_h_size_flags(SIZE_EXPAND_FILL); sources_list->set_v_size_flags(SIZE_EXPAND_FILL); @@ -933,6 +934,7 @@ TileSetEditor::TileSetEditor() { //// Patterns //// int thumbnail_size = 64; patterns_item_list = memnew(ItemList); + patterns_item_list->set_auto_translate(false); patterns_item_list->set_max_columns(0); patterns_item_list->set_icon_mode(ItemList::ICON_MODE_TOP); patterns_item_list->set_fixed_column_width(thumbnail_size * 3 / 2); diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index 1f4c3651e9..4895e1d291 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -33,11 +33,11 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/editor_file_dialog.h" #include "editor/plugins/tiles/tile_set_editor.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/gui/item_list.h" @@ -549,6 +549,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { split_container_right_side->add_child(right_vbox_container); scene_tiles_list = memnew(ItemList); + scene_tiles_list->set_auto_translate(false); scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL); scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL); SET_DRAG_FORWARDING_CDU(scene_tiles_list, TileSetScenesCollectionSourceEditor); diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index b96f3f21b8..057e6443d6 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -36,10 +36,10 @@ #include "editor/editor_interface.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/tile_map.h" #include "scene/gui/box_container.h" @@ -125,7 +125,7 @@ void TilesEditorUtils::_thread() { tile_map->set_position(-(scale * encompassing_rect.get_center()) + thumbnail_size2 / 2); // Add the viewport at the last moment to avoid rendering too early. - EditorNode::get_singleton()->call_deferred("add_child", viewport); + callable_mp((Node *)EditorNode::get_singleton(), &Node::add_child).call_deferred(viewport, false, Node::INTERNAL_MODE_DISABLED); RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorUtils *>(this), &TilesEditorUtils::_preview_frame_started), Object::CONNECT_ONE_SHOT); diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 2fa54ac1dc..d8d70e5b7d 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -33,14 +33,15 @@ #include "core/config/project_settings.h" #include "core/os/keyboard.h" #include "core/os/time.h" +#include "editor/editor_dock_manager.h" #include "editor/editor_file_system.h" #include "editor/editor_interface.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/filesystem_dock.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/separator.h" #define CHECK_PLUGIN_INITIALIZED() \ @@ -909,7 +910,7 @@ void VersionControlEditorPlugin::fetch_available_vcs_plugin_names() { } void VersionControlEditorPlugin::register_editor() { - EditorNode::get_singleton()->add_control_to_dock(EditorNode::DOCK_SLOT_RIGHT_UL, version_commit_dock); + EditorDockManager::get_singleton()->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, version_commit_dock); version_control_dock_button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock); @@ -929,7 +930,7 @@ void VersionControlEditorPlugin::shut_down() { memdelete(EditorVCSInterface::get_singleton()); EditorVCSInterface::set_singleton(nullptr); - EditorNode::get_singleton()->remove_control_from_dock(version_commit_dock); + EditorDockManager::get_singleton()->remove_control_from_dock(version_commit_dock); EditorNode::get_singleton()->remove_bottom_panel_item(version_control_dock); _set_vcs_ui_state(false); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 5c22e454ab..6de37172b3 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -37,7 +37,6 @@ #include "editor/editor_node.h" #include "editor/editor_properties.h" #include "editor/editor_properties_vector.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" @@ -45,6 +44,7 @@ #include "editor/inspector_dock.h" #include "editor/plugins/curve_editor_plugin.h" #include "editor/plugins/shader_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/gui/check_box.h" #include "scene/gui/code_edit.h" @@ -182,7 +182,7 @@ void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p } void VisualShaderGraphPlugin::update_node_deferred(VisualShader::Type p_type, int p_node_id) { - call_deferred(SNAME("update_node"), p_type, p_node_id); + callable_mp(this, &VisualShaderGraphPlugin::update_node).call_deferred(p_type, p_node_id); } void VisualShaderGraphPlugin::update_node(VisualShader::Type p_type, int p_node_id) { @@ -1492,14 +1492,14 @@ void VisualShaderEditor::_update_custom_script(const Ref<Script> &p_script) { if (!_block_update_options_menu) { _block_update_options_menu = true; - call_deferred(SNAME("_update_options_menu_deferred")); + callable_mp(this, &VisualShaderEditor::_update_options_menu_deferred); } // To prevent rebuilding the shader multiple times when multiple scripts are saved. if (need_rebuild && !_block_rebuild_shader) { _block_rebuild_shader = true; - call_deferred(SNAME("_rebuild_shader_deferred")); + callable_mp(this, &VisualShaderEditor::_rebuild_shader_deferred); } } @@ -1581,8 +1581,7 @@ void VisualShaderEditor::_resource_removed(const Ref<Resource> &p_resource) { if (!pending_custom_scripts_to_delete) { pending_custom_scripts_to_delete = true; - - call_deferred("_resources_removed"); + callable_mp(this, &VisualShaderEditor::_resources_removed).call_deferred(); } } @@ -3322,11 +3321,11 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri } if (is_curve) { - graph_plugin->call_deferred(SNAME("update_curve"), id_to_use); + callable_mp(graph_plugin.ptr(), &VisualShaderGraphPlugin::update_curve).call_deferred(id_to_use); } if (is_curve_xyz) { - graph_plugin->call_deferred(SNAME("update_curve_xyz"), id_to_use); + callable_mp(graph_plugin.ptr(), &VisualShaderGraphPlugin::update_curve_xyz).call_deferred(id_to_use); } if (p_resource_path.is_empty()) { @@ -3466,7 +3465,7 @@ void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_t VisualShader::Type type = get_current_shader_type(); drag_buffer.push_back({ type, p_node, p_from, p_to }); if (!drag_dirty) { - call_deferred(SNAME("_nodes_dragged")); + callable_mp(this, &VisualShaderEditor::_nodes_dragged).call_deferred(); } drag_dirty = true; } @@ -4094,7 +4093,7 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNod Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).max(Vector2()); members_dialog->set_position(members_dialog->get_position() - difference); - node_filter->call_deferred(SNAME("grab_focus")); // Still not visible. + callable_mp((Control *)node_filter, &Control::grab_focus).call_deferred(); // Still not visible. node_filter->select_all(); } @@ -5187,28 +5186,17 @@ void VisualShaderEditor::_visibility_changed() { void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_update_nodes", &VisualShaderEditor::_update_nodes); ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph); - ClassDB::bind_method("_add_node", &VisualShaderEditor::_add_node); - ClassDB::bind_method("_node_changed", &VisualShaderEditor::_node_changed); ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item); ClassDB::bind_method("_parameter_ref_select_item", &VisualShaderEditor::_parameter_ref_select_item); ClassDB::bind_method("_varying_select_item", &VisualShaderEditor::_varying_select_item); ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size); - ClassDB::bind_method("_clear_copy_buffer", &VisualShaderEditor::_clear_copy_buffer); ClassDB::bind_method("_update_parameters", &VisualShaderEditor::_update_parameters); ClassDB::bind_method("_update_varyings", &VisualShaderEditor::_update_varyings); ClassDB::bind_method("_update_varying_tree", &VisualShaderEditor::_update_varying_tree); ClassDB::bind_method("_set_mode", &VisualShaderEditor::_set_mode); - ClassDB::bind_method("_nodes_dragged", &VisualShaderEditor::_nodes_dragged); - ClassDB::bind_method("_float_constant_selected", &VisualShaderEditor::_float_constant_selected); ClassDB::bind_method("_update_constant", &VisualShaderEditor::_update_constant); ClassDB::bind_method("_update_parameter", &VisualShaderEditor::_update_parameter); - ClassDB::bind_method("_expand_output_port", &VisualShaderEditor::_expand_output_port); - ClassDB::bind_method("_update_options_menu_deferred", &VisualShaderEditor::_update_options_menu_deferred); - ClassDB::bind_method("_rebuild_shader_deferred", &VisualShaderEditor::_rebuild_shader_deferred); - ClassDB::bind_method("_resources_removed", &VisualShaderEditor::_resources_removed); ClassDB::bind_method("_update_next_previews", &VisualShaderEditor::_update_next_previews); - - ClassDB::bind_method("_is_available", &VisualShaderEditor::_is_available); } VisualShaderEditor::VisualShaderEditor() { diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp index ec044ee06e..3804bd8d5b 100644 --- a/editor/pot_generator.cpp +++ b/editor/pot_generator.cpp @@ -69,7 +69,7 @@ void POTGenerator::generate_pot(const String &p_file) { for (int i = 0; i < files.size(); i++) { Vector<String> msgids; Vector<Vector<String>> msgids_context_plural; - String file_path = files[i]; + const String &file_path = files[i]; String file_extension = file_path.get_extension(); if (EditorTranslationParser::get_singleton()->can_parse(file_extension)) { @@ -80,7 +80,7 @@ void POTGenerator::generate_pot(const String &p_file) { } for (int j = 0; j < msgids_context_plural.size(); j++) { - Vector<String> entry = msgids_context_plural[j]; + const Vector<String> &entry = msgids_context_plural[j]; _add_new_msgid(entry[0], entry[1], entry[2], file_path); } for (int j = 0; j < msgids.size(); j++) { @@ -141,7 +141,7 @@ void POTGenerator::_write_to_pot(const String &p_file) { // Write context. if (!context.is_empty()) { - file->store_line("msgctxt " + context.c_escape().quote()); + file->store_line("msgctxt " + context.json_escape().quote()); } // Write msgid. @@ -183,11 +183,11 @@ void POTGenerator::_write_msgid(Ref<FileAccess> r_file, const String &p_id, bool } for (int i = 0; i < lines.size() - 1; i++) { - r_file->store_line((lines[i] + "\n").c_escape().quote()); + r_file->store_line((lines[i] + "\n").json_escape().quote()); } if (!last_line.is_empty()) { - r_file->store_line(last_line.c_escape().quote()); + r_file->store_line(last_line.json_escape().quote()); } } diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp index 366d0cb2fc..ff8343fbeb 100644 --- a/editor/progress_dialog.cpp +++ b/editor/progress_dialog.cpp @@ -30,11 +30,10 @@ #include "progress_dialog.h" -#include "core/object/message_queue.h" #include "core/os/os.h" #include "editor/editor_interface.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #include "main/main.h" #include "servers/display_server.h" @@ -97,15 +96,8 @@ void BackgroundProgress::_end_task(const String &p_task) { tasks.erase(p_task); } -void BackgroundProgress::_bind_methods() { - ClassDB::bind_method("_add_task", &BackgroundProgress::_add_task); - ClassDB::bind_method("_task_step", &BackgroundProgress::_task_step); - ClassDB::bind_method("_end_task", &BackgroundProgress::_end_task); - ClassDB::bind_method("_update", &BackgroundProgress::_update); -} - void BackgroundProgress::add_task(const String &p_task, const String &p_label, int p_steps) { - MessageQueue::get_singleton()->push_call(this, "_add_task", p_task, p_label, p_steps); + callable_mp(this, &BackgroundProgress::_add_task).call_deferred(p_task, p_label, p_steps); } void BackgroundProgress::task_step(const String &p_task, int p_step) { @@ -117,7 +109,7 @@ void BackgroundProgress::task_step(const String &p_task, int p_step) { } if (no_updates) { - MessageQueue::get_singleton()->push_call(this, "_update"); + callable_mp(this, &BackgroundProgress::_update).call_deferred(); } { @@ -127,7 +119,7 @@ void BackgroundProgress::task_step(const String &p_task, int p_step) { } void BackgroundProgress::end_task(const String &p_task) { - MessageQueue::get_singleton()->push_call(this, "_end_task", p_task); + callable_mp(this, &BackgroundProgress::_end_task).call_deferred(p_task); } //////////////////////////////////////////////// @@ -242,9 +234,6 @@ void ProgressDialog::_cancel_pressed() { canceled = true; } -void ProgressDialog::_bind_methods() { -} - ProgressDialog::ProgressDialog() { main = memnew(VBoxContainer); add_child(main); diff --git a/editor/progress_dialog.h b/editor/progress_dialog.h index c75c8fac10..74196a28df 100644 --- a/editor/progress_dialog.h +++ b/editor/progress_dialog.h @@ -56,8 +56,6 @@ protected: void _task_step(const String &p_task, int p_step = -1); void _end_task(const String &p_task); - static void _bind_methods(); - public: void add_task(const String &p_task, const String &p_label, int p_steps); void task_step(const String &p_task, int p_step = -1); @@ -89,9 +87,6 @@ class ProgressDialog : public PopupPanel { void _cancel_pressed(); bool canceled = false; -protected: - static void _bind_methods(); - public: static ProgressDialog *get_singleton() { return singleton; } void add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel = false); diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index bea865af13..f8161272f6 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -68,10 +68,10 @@ public: RegEx reg_json_parse = RegEx("([\t ]{0,})([^\n]+)parse_json\\(([^\n]+)"); RegEx reg_json_non_new = RegEx("([\t ]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)"); RegEx reg_json_print = RegEx("\\bJSON\\b\\.print\\("); - RegEx reg_export_simple = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)"); - RegEx reg_export_typed = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)[ ]*:[ ]*[a-zA-Z0-9_]+"); - RegEx reg_export_inferred_type = RegEx("export\\([a-zA-Z0-9_]+\\)[ ]+var[ ]+([a-zA-Z0-9_]+)[ ]*:[ ]*="); - RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)"); + RegEx reg_export_simple = RegEx("export[ ]*\\(([a-zA-Z0-9_]+)\\)[ ]*var[ ]+([a-zA-Z0-9_]+)"); + RegEx reg_export_typed = RegEx("export[ ]*\\(([a-zA-Z0-9_]+)\\)[ ]*var[ ]+([a-zA-Z0-9_]+)[ ]*:[ ]*[a-zA-Z0-9_]+"); + RegEx reg_export_inferred_type = RegEx("export[ ]*\\([a-zA-Z0-9_]+\\)[ ]*var[ ]+([a-zA-Z0-9_]+)[ ]*:[ ]*="); + RegEx reg_export_advanced = RegEx("export[ ]*\\(([^)^\n]+)\\)[ ]*var[ ]+([a-zA-Z0-9_]+)([^\n]+)"); RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)"); RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^\n]*$"); RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$"); @@ -561,7 +561,7 @@ bool ProjectConverter3To4::validate_conversion() { // Check file by file. for (int i = 0; i < collected_files.size(); i++) { - String file_name = collected_files[i]; + const String &file_name = collected_files[i]; Vector<String> lines; uint32_t ignored_lines = 0; uint64_t file_size = 0; @@ -931,6 +931,7 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { valid = valid && test_conversion_gdscript_builtin(" Transform.xform_inv(Vector3(a,b,c) + Vector3.UP) ", " (Vector3(a,b,c) + Vector3.UP) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("export (int)var spaces=1", "export var spaces: int=1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); // TODO, this is only a workaround valid = valid && test_conversion_gdscript_builtin("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("export(float) var lifetime: float = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); @@ -1044,107 +1045,108 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { // get_object_of_execution { - { String base = "var roman = kieliszek."; - String expected = "kieliszek."; - String got = get_object_of_execution(base); - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); + String base = "var roman = kieliszek."; + String expected = "kieliszek."; + String got = get_object_of_execution(base); + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); + } + { + String base = "r."; + String expected = "r."; + String got = get_object_of_execution(base); + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); + } + { + String base = "mortadela("; + String expected = ""; + String got = get_object_of_execution(base); + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); + } + { + String base = "var node = $world/ukraine/lviv."; + String expected = "$world/ukraine/lviv."; + String got = get_object_of_execution(base); + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); } - valid = valid && (got == expected); -} -{ - String base = "r."; - String expected = "r."; - String got = get_object_of_execution(base); - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); - } - valid = valid && (got == expected); -} -{ - String base = "mortadela("; - String expected = ""; - String got = get_object_of_execution(base); - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); - } - valid = valid && (got == expected); -} -{ - String base = "var node = $world/ukraine/lviv."; - String expected = "$world/ukraine/lviv."; - String got = get_object_of_execution(base); - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); - } - valid = valid && (got == expected); -} -} -// get_starting_space -{ - String base = "\t\t\t var roman = kieliszek."; - String expected = "\t\t\t"; - String got = get_starting_space(base); - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); - } - valid = valid && (got == expected); -} -// Parse Arguments -{ - String line = "( )"; - Vector<String> got_vector = parse_arguments(line); - String got = ""; - String expected = ""; - for (String &part : got_vector) { - got += part + "|||"; - } - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); - } - valid = valid && (got == expected); -} -{ - String line = "(a , b , c)"; - Vector<String> got_vector = parse_arguments(line); - String got = ""; - String expected = "a|||b|||c|||"; - for (String &part : got_vector) { - got += part + "|||"; - } - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); - } - valid = valid && (got == expected); -} -{ - String line = "(a , \"b,\" , c)"; - Vector<String> got_vector = parse_arguments(line); - String got = ""; - String expected = "a|||\"b,\"|||c|||"; - for (String &part : got_vector) { - got += part + "|||"; - } - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); - } - valid = valid && (got == expected); -} -{ - String line = "(a , \"(,),,,,\" , c)"; - Vector<String> got_vector = parse_arguments(line); - String got = ""; - String expected = "a|||\"(,),,,,\"|||c|||"; - for (String &part : got_vector) { - got += part + "|||"; - } - if (got != expected) { - ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); - } - valid = valid && (got == expected); -} -return valid; + // get_starting_space + { + String base = "\t\t\t var roman = kieliszek."; + String expected = "\t\t\t"; + String got = get_starting_space(base); + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); + } + + // Parse Arguments + { + String line = "( )"; + Vector<String> got_vector = parse_arguments(line); + String got = ""; + String expected = ""; + for (String &part : got_vector) { + got += part + "|||"; + } + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); + } + { + String line = "(a , b , c)"; + Vector<String> got_vector = parse_arguments(line); + String got = ""; + String expected = "a|||b|||c|||"; + for (String &part : got_vector) { + got += part + "|||"; + } + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); + } + { + String line = "(a , \"b,\" , c)"; + Vector<String> got_vector = parse_arguments(line); + String got = ""; + String expected = "a|||\"b,\"|||c|||"; + for (String &part : got_vector) { + got += part + "|||"; + } + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); + } + { + String line = "(a , \"(,),,,,\" , c)"; + Vector<String> got_vector = parse_arguments(line); + String got = ""; + String expected = "a|||\"(,),,,,\"|||c|||"; + for (String &part : got_vector) { + got += part + "|||"; + } + if (got != expected) { + ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); + } + valid = valid && (got == expected); + } + + return valid; } // Validate in all arrays if names don't do cyclic renames "Node" -> "Node2D" | "Node2D" -> "2DNode" @@ -2348,7 +2350,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai line = line.replace("OS.is_window_focused", "get_window().has_focus"); } if (line.contains("OS.move_window_to_foreground")) { - line = line.replace("OS.move_window_to_foreground", "get_window().move_to_foreground"); + line = line.replace("OS.move_window_to_foreground", "get_window().grab_focus"); } if (line.contains("OS.request_attention")) { line = line.replace("OS.request_attention", "get_window().request_attention"); @@ -2732,7 +2734,7 @@ void ProjectConverter3To4::rename_joypad_buttons_and_axes(Vector<SourceLine> &so for (int i = 0; i < reg_match.size(); ++i) { Ref<RegExMatch> match = reg_match[i]; PackedStringArray strings = match->get_strings(); - String button_index_entry = strings[0]; + const String &button_index_entry = strings[0]; int button_index_value = strings[1].to_int(); if (button_index_value == 6) { // L2 and R2 are mapped to joypad axes in Godot 4. line = line.replace("InputEventJoypadButton", "InputEventJoypadMotion"); @@ -2741,7 +2743,7 @@ void ProjectConverter3To4::rename_joypad_buttons_and_axes(Vector<SourceLine> &so line = line.replace("InputEventJoypadButton", "InputEventJoypadMotion"); line = line.replace(button_index_entry, ",\"axis\":5,\"axis_value\":1.0"); } else if (button_index_value < 22) { // There are no mappings for indexes greater than 22 in both Godot 3 & 4. - String pressure_and_pressed_properties = strings[2]; + const String &pressure_and_pressed_properties = strings[2]; line = line.replace(button_index_entry, ",\"button_index\":" + String::num_int64(reg_container.joypad_button_mappings[button_index_value]) + "," + pressure_and_pressed_properties); } } @@ -2750,7 +2752,7 @@ void ProjectConverter3To4::rename_joypad_buttons_and_axes(Vector<SourceLine> &so for (int i = 0; i < reg_match.size(); ++i) { Ref<RegExMatch> match = reg_match[i]; PackedStringArray strings = match->get_strings(); - String axis_entry = strings[0]; + const String &axis_entry = strings[0]; int axis_value = strings[1].to_int(); if (axis_value == 6) { line = line.replace(axis_entry, ",\"axis\":4"); @@ -2772,7 +2774,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_joypad_buttons_and_axes(Ve for (int i = 0; i < reg_match.size(); ++i) { Ref<RegExMatch> match = reg_match[i]; PackedStringArray strings = match->get_strings(); - String button_index_entry = strings[0]; + const String &button_index_entry = strings[0]; int button_index_value = strings[1].to_int(); if (button_index_value == 6) { // L2 and R2 are mapped to joypad axes in Godot 4. found_renames.append(line_formatter(current_line, "InputEventJoypadButton", "InputEventJoypadMotion", line)); @@ -2789,7 +2791,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_joypad_buttons_and_axes(Ve for (int i = 0; i < reg_match.size(); ++i) { Ref<RegExMatch> match = reg_match[i]; PackedStringArray strings = match->get_strings(); - String axis_entry = strings[0]; + const String &axis_entry = strings[0]; int axis_value = strings[1].to_int(); if (axis_value == 6) { found_renames.append(line_formatter(current_line, axis_entry, ",\"axis\":4", line)); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index f74458e89b..e7277bad6a 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -42,13 +42,14 @@ #include "core/string/translation.h" #include "core/version.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" -#include "editor/editor_themes.h" #include "editor/editor_vcs_interface.h" #include "editor/gui/editor_file_dialog.h" #include "editor/plugins/asset_library_editor_plugin.h" +#include "editor/themes/editor_icons.h" +#include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme_manager.h" #include "main/main.h" #include "scene/gui/center_container.h" #include "scene/gui/check_box.h" @@ -103,21 +104,25 @@ void ProjectDialog::_set_message(const String &p_msg, MessageType p_type, InputT } } +static bool is_zip_file(Ref<DirAccess> p_d, const String &p_path) { + return p_path.ends_with(".zip") && p_d->file_exists(p_path); +} + String ProjectDialog::_test_path() { Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + const String base_path = project_path->get_text(); String valid_path, valid_install_path; - if (d->change_dir(project_path->get_text()) == OK) { - valid_path = project_path->get_text(); - } else if (d->change_dir(project_path->get_text().strip_edges()) == OK) { - valid_path = project_path->get_text().strip_edges(); - } else if (project_path->get_text().ends_with(".zip")) { - if (d->file_exists(project_path->get_text())) { - valid_path = project_path->get_text(); - } - } else if (project_path->get_text().strip_edges().ends_with(".zip")) { - if (d->file_exists(project_path->get_text().strip_edges())) { - valid_path = project_path->get_text().strip_edges(); - } + bool is_zip = false; + if (d->change_dir(base_path) == OK) { + valid_path = base_path; + } else if (is_zip_file(d, base_path)) { + valid_path = base_path; + is_zip = true; + } else if (d->change_dir(base_path.strip_edges()) == OK) { + valid_path = base_path.strip_edges(); + } else if (is_zip_file(d, base_path.strip_edges())) { + valid_path = base_path.strip_edges(); + is_zip = true; } if (valid_path.is_empty()) { @@ -126,7 +131,7 @@ String ProjectDialog::_test_path() { return ""; } - if (mode == MODE_IMPORT && valid_path.ends_with(".zip")) { + if (mode == MODE_IMPORT && is_zip) { if (d->change_dir(install_path->get_text()) == OK) { valid_install_path = install_path->get_text(); } else if (d->change_dir(install_path->get_text().strip_edges()) == OK) { @@ -134,15 +139,15 @@ String ProjectDialog::_test_path() { } if (valid_install_path.is_empty()) { - _set_message(TTR("The path specified doesn't exist."), MESSAGE_ERROR, INSTALL_PATH); + _set_message(TTR("The install path specified doesn't exist."), MESSAGE_ERROR, INSTALL_PATH); get_ok_button()->set_disabled(true); return ""; } } if (mode == MODE_IMPORT || mode == MODE_RENAME) { - if (!valid_path.is_empty() && !d->file_exists("project.godot")) { - if (valid_path.ends_with(".zip")) { + if (!d->file_exists("project.godot")) { + if (is_zip) { Ref<FileAccess> io_fa; zlib_filefunc_def io = zipio_create_io(&io_fa); @@ -197,7 +202,7 @@ String ProjectDialog::_test_path() { d->list_dir_end(); if (!is_folder_empty) { - _set_message(TTR("Please choose an empty folder."), MESSAGE_WARNING, INSTALL_PATH); + _set_message(TTR("Please choose an empty install folder."), MESSAGE_WARNING, INSTALL_PATH); get_ok_button()->set_disabled(true); return ""; } @@ -209,8 +214,8 @@ String ProjectDialog::_test_path() { return ""; } - } else if (valid_path.ends_with("zip")) { - _set_message(TTR("This directory already contains a Godot project."), MESSAGE_ERROR, INSTALL_PATH); + } else if (is_zip) { + _set_message(TTR("The install directory already contains a Godot project."), MESSAGE_ERROR, INSTALL_PATH); get_ok_button()->set_disabled(true); return ""; } @@ -252,7 +257,7 @@ String ProjectDialog::_test_path() { return valid_path; } -void ProjectDialog::_path_text_changed(const String &p_path) { +void ProjectDialog::_update_path(const String &p_path) { String sp = _test_path(); if (!sp.is_empty()) { // If the project name is empty or default, infer the project name from the selected folder name @@ -277,6 +282,21 @@ void ProjectDialog::_path_text_changed(const String &p_path) { } } +void ProjectDialog::_path_text_changed(const String &p_path) { + Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + if (mode == MODE_IMPORT && is_zip_file(d, p_path)) { + install_path->set_text(p_path.get_base_dir()); + install_path_container->show(); + } else if (mode == MODE_IMPORT && is_zip_file(d, p_path.strip_edges())) { + install_path->set_text(p_path.strip_edges().get_base_dir()); + install_path_container->show(); + } else { + install_path_container->hide(); + } + + _update_path(p_path.simplify_path()); +} + void ProjectDialog::_file_selected(const String &p_path) { // If not already shown. show_dialog(); @@ -300,11 +320,11 @@ void ProjectDialog::_file_selected(const String &p_path) { String sp = p.simplify_path(); project_path->set_text(sp); - _path_text_changed(sp); + _update_path(sp); if (p.ends_with(".zip")) { - install_path->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)install_path, &Control::grab_focus).call_deferred(); } else { - get_ok_button()->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)get_ok_button(), &Control::grab_focus).call_deferred(); } } @@ -314,15 +334,15 @@ void ProjectDialog::_path_selected(const String &p_path) { String sp = p_path.simplify_path(); project_path->set_text(sp); - _path_text_changed(sp); - get_ok_button()->call_deferred(SNAME("grab_focus")); + _update_path(sp); + callable_mp((Control *)get_ok_button(), &Control::grab_focus).call_deferred(); } void ProjectDialog::_install_path_selected(const String &p_path) { String sp = p_path.simplify_path(); install_path->set_text(sp); - _path_text_changed(sp); - get_ok_button()->call_deferred(SNAME("grab_focus")); + _update_path(sp); + callable_mp((Control *)get_ok_button(), &Control::grab_focus).call_deferred(); } void ProjectDialog::_browse_path() { @@ -359,7 +379,7 @@ void ProjectDialog::_create_folder() { d->change_dir(project_name_no_edges); String dir_str = d->get_current_dir(); project_path->set_text(dir_str); - _path_text_changed(dir_str); + _update_path(dir_str); created_folder_path = d->get_current_dir(); create_dir->set_disabled(true); } else { @@ -638,7 +658,7 @@ void ProjectDialog::cancel_pressed() { _remove_created_folder(); project_path->clear(); - _path_text_changed(""); + _update_path(""); project_name->clear(); _text_changed(""); @@ -707,7 +727,7 @@ void ProjectDialog::show_dialog() { _text_changed(cur_name); } - project_name->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)project_name, &Control::grab_focus).call_deferred(); create_dir->hide(); @@ -754,8 +774,8 @@ void ProjectDialog::show_dialog() { install_path_container->hide(); renderer_container->show(); default_files_container->show(); - project_name->call_deferred(SNAME("grab_focus")); - project_name->call_deferred(SNAME("select_all")); + callable_mp((Control *)project_name, &Control::grab_focus).call_deferred(); + callable_mp(project_name, &LineEdit::select_all).call_deferred(); } else if (mode == MODE_INSTALL) { set_title(TTR("Install Project:") + " " + zip_title); @@ -968,7 +988,7 @@ ProjectDialog::ProjectDialog() { project_name->connect("text_changed", callable_mp(this, &ProjectDialog::_text_changed)); project_path->connect("text_changed", callable_mp(this, &ProjectDialog::_path_text_changed)); - install_path->connect("text_changed", callable_mp(this, &ProjectDialog::_path_text_changed)); + install_path->connect("text_changed", callable_mp(this, &ProjectDialog::_update_path)); fdialog->connect("dir_selected", callable_mp(this, &ProjectDialog::_path_selected)); fdialog->connect("file_selected", callable_mp(this, &ProjectDialog::_file_selected)); fdialog_install->connect("dir_selected", callable_mp(this, &ProjectDialog::_install_path_selected)); @@ -2860,9 +2880,8 @@ ProjectManager::ProjectManager() { Control::set_root_layout_direction(pm_root_dir); Window::set_root_layout_direction(pm_root_dir); - EditorColorMap::create(); - EditorTheme::initialize(); - Ref<Theme> theme = create_custom_theme(); + EditorThemeManager::initialize(); + Ref<Theme> theme = EditorThemeManager::generate_theme(); DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor))); set_theme(theme); @@ -3074,7 +3093,7 @@ ProjectManager::ProjectManager() { language_btn->set_text(current_lang); for (int i = 0; i < editor_languages.size(); i++) { - String lang = editor_languages[i]; + const String &lang = editor_languages[i]; String lang_name = TranslationServer::get_singleton()->get_locale_name(lang); language_btn->add_item(vformat("[%s] %s", lang, lang_name), i); language_btn->set_item_metadata(i, lang); @@ -3298,8 +3317,7 @@ ProjectManager::~ProjectManager() { EditorSettings::destroy(); } - EditorColorMap::finish(); - EditorTheme::finalize(); + EditorThemeManager::finalize(); } void ProjectTag::_notification(int p_what) { diff --git a/editor/project_manager.h b/editor/project_manager.h index 8a8b2ff99d..7b091050bd 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -104,6 +104,7 @@ private: void _set_message(const String &p_msg, MessageType p_type = MESSAGE_SUCCESS, InputType input_type = PROJECT_PATH); String _test_path(); + void _update_path(const String &p_path); void _path_text_changed(const String &p_path); void _path_selected(const String &p_path); void _file_selected(const String &p_path); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index d587737ed4..e59bb76ff4 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -33,11 +33,11 @@ #include "core/config/project_settings.h" #include "editor/editor_log.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/export/editor_export.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/check_button.h" #include "servers/movie_writer/movie_writer.h" @@ -70,6 +70,8 @@ void ProjectSettingsEditor::popup_project_settings(bool p_clear_filter) { if (p_clear_filter) { search_box->clear(); } + + _focus_current_search_box(); } void ProjectSettingsEditor::queue_save() { @@ -173,7 +175,7 @@ void ProjectSettingsEditor::_feature_selected(int p_index) { void ProjectSettingsEditor::_update_property_box() { const String setting = _get_setting_name(); const Vector<String> t = setting.split(".", true, 1); - const String name = t[0]; + const String &name = t[0]; const String feature = (t.size() == 2) ? t[1] : ""; bool feature_invalid = (t.size() == 2) && (t[1].is_empty()); @@ -255,8 +257,7 @@ void ProjectSettingsEditor::shortcut_input(const Ref<InputEvent> &p_event) { } if (k->is_match(InputEventKey::create_reference(KeyModifierMask::CMD_OR_CTRL | Key::F))) { - search_box->grab_focus(); - search_box->select_all(); + _focus_current_search_box(); handled = true; } @@ -328,6 +329,25 @@ void ProjectSettingsEditor::_add_feature_overrides() { } } +void ProjectSettingsEditor::_tabs_tab_changed(int p_tab) { + _focus_current_search_box(); +} + +void ProjectSettingsEditor::_focus_current_search_box() { + Control *tab = tab_container->get_current_tab_control(); + LineEdit *current_search_box = nullptr; + if (tab == general_editor) { + current_search_box = search_box; + } else if (tab == action_map_editor) { + current_search_box = action_map_editor->get_search_box(); + } + + if (current_search_box) { + current_search_box->grab_focus(); + current_search_box->select_all(); + } +} + void ProjectSettingsEditor::_editor_restart() { ProjectSettings::get_singleton()->save(); EditorNode::get_singleton()->save_all_scenes(); @@ -536,6 +556,8 @@ void ProjectSettingsEditor::_update_action_map_editor() { } void ProjectSettingsEditor::_update_theme() { + add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); + del_button->set_icon(get_editor_theme_icon(SNAME("Remove"))); search_box->set_right_icon(get_editor_theme_icon(SNAME("Search"))); restart_close_button->set_icon(get_editor_theme_icon(SNAME("Close"))); restart_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); @@ -598,6 +620,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { tab_container = memnew(TabContainer); tab_container->set_use_hidden_tabs_for_min_size(true); tab_container->set_theme_type_variation("TabContainerOdd"); + tab_container->connect("tab_changed", callable_mp(this, &ProjectSettingsEditor::_tabs_tab_changed)); add_child(tab_container); general_editor = memnew(VBoxContainer); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 1f18c68acc..7771bdda61 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -95,6 +95,9 @@ class ProjectSettingsEditor : public AcceptDialog { void _add_setting(); void _delete_setting(); + void _tabs_tab_changed(int p_tab); + void _focus_current_search_box(); + void _editor_restart_request(); void _editor_restart(); void _editor_restart_close(); diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index 87dbbd599d..be5f309704 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -34,7 +34,7 @@ #include "editor/doc_tools.h" #include "editor/editor_help.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/line_edit.h" #include "scene/gui/rich_text_label.h" #include "scene/gui/tree.h" diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp index 075c856c1c..04a06ff732 100644 --- a/editor/register_editor_types.cpp +++ b/editor/register_editor_types.cpp @@ -50,6 +50,8 @@ #include "editor/filesystem_dock.h" #include "editor/gui/editor_file_dialog.h" #include "editor/gui/editor_spin_slider.h" +#include "editor/import/3d/resource_importer_obj.h" +#include "editor/import/3d/resource_importer_scene.h" #include "editor/import/editor_import_plugin.h" #include "editor/import/resource_importer_bitmask.h" #include "editor/import/resource_importer_bmfont.h" @@ -58,8 +60,6 @@ #include "editor/import/resource_importer_image.h" #include "editor/import/resource_importer_imagefont.h" #include "editor/import/resource_importer_layered_texture.h" -#include "editor/import/resource_importer_obj.h" -#include "editor/import/resource_importer_scene.h" #include "editor/import/resource_importer_shader_file.h" #include "editor/import/resource_importer_texture.h" #include "editor/import/resource_importer_texture_atlas.h" diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index a3a16dccd8..07cb96b9bc 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -35,12 +35,11 @@ #include "core/string/print_string.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" -#include "editor/editor_themes.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "modules/regex/regex.h" #include "scene/gui/check_box.h" #include "scene/gui/check_button.h" diff --git a/editor/renames_map_3_to_4.cpp b/editor/renames_map_3_to_4.cpp index 6323aecfda..ba6095db47 100644 --- a/editor/renames_map_3_to_4.cpp +++ b/editor/renames_map_3_to_4.cpp @@ -163,6 +163,7 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = { // { "_set_name", "get_tracker_name" }, // XRPositionalTracker -- CameraFeed uses this. // { "_unhandled_input", "_unhandled_key_input" }, // BaseButton, ViewportContainer -- Breaks Node, FileDialog, SubViewportContainer. + // { "add_animation", "add_animation_library" }, // AnimationPlayer -- Breaks SpriteFrames (and isn't a correct conversion). // { "create_gizmo", "_create_gizmo" }, // EditorNode3DGizmoPlugin -- May be used. // { "get_dependencies", "_get_dependencies" }, // ResourceFormatLoader -- Breaks ResourceLoader. // { "get_extents", "get_size" }, // BoxShape, RectangleShape -- Breaks Decal, VoxelGI, GPUParticlesCollisionBox, GPUParticlesCollisionSDF, GPUParticlesCollisionHeightField, GPUParticlesAttractorBox, GPUParticlesAttractorVectorField, FogVolume @@ -214,8 +215,6 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = { { "_set_current", "set_current" }, // Camera2D { "_set_editor_description", "set_editor_description" }, // Node { "_toplevel_raise_self", "_top_level_raise_self" }, // CanvasItem - { "_update_wrap_at", "_update_wrap_at_column" }, // TextEdit - { "add_animation", "add_animation_library" }, // AnimationPlayer { "add_cancel", "add_cancel_button" }, // AcceptDialog { "add_central_force", "apply_central_force" }, //RigidBody2D { "add_child_below_node", "add_sibling" }, // Node @@ -644,7 +643,6 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = { { "_SetPlaying", "SetPlaying" }, // AnimatedSprite3D { "_ToplevelRaiseSelf", "_TopLevelRaiseSelf" }, // CanvasItem { "_UpdateWrapAt", "_UpdateWrapAtColumn" }, // TextEdit - { "AddAnimation", "AddAnimationLibrary" }, // AnimationPlayer { "AddCancel", "AddCancelButton" }, // AcceptDialog { "AddCentralForce", "AddConstantCentralForce" }, //RigidBody2D { "AddChildBelowNode", "AddSibling" }, // Node diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp index 60ad7e5968..ef700d8352 100644 --- a/editor/scene_create_dialog.cpp +++ b/editor/scene_create_dialog.cpp @@ -33,9 +33,9 @@ #include "core/io/dir_access.h" #include "editor/create_dialog.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_validation_panel.h" +#include "editor/themes/editor_scale.h" #include "scene/2d/node_2d.h" #include "scene/3d/node_3d.h" #include "scene/gui/box_container.h" @@ -65,7 +65,7 @@ void SceneCreateDialog::config(const String &p_dir) { directory = p_dir; root_name_edit->set_text(""); scene_name_edit->set_text(""); - scene_name_edit->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)scene_name_edit, &Control::grab_focus).call_deferred(); validation_panel->update(); } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 6553a592d0..9c7ba827b7 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -29,20 +29,17 @@ /**************************************************************************/ #include "scene_tree_dock.h" -#include "node_dock.h" #include "core/config/project_settings.h" #include "core/input/input.h" #include "core/io/resource_saver.h" #include "core/object/class_db.h" -#include "core/object/message_queue.h" #include "core/os/keyboard.h" #include "editor/debugger/editor_debugger_node.h" #include "editor/editor_feature_profile.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_quick_open.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" @@ -50,12 +47,14 @@ #include "editor/gui/editor_file_dialog.h" #include "editor/inspector_dock.h" #include "editor/multi_node_edit.h" +#include "editor/node_dock.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/reparent_dialog.h" #include "editor/shader_create_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/animation/animation_tree.h" #include "scene/gui/check_box.h" #include "scene/main/window.h" @@ -713,7 +712,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { selection.sort_custom<Node::Comparator>(); - Node *add_below_node = selection.back()->get(); + HashMap<const Node *, Node *> add_below_map; + + for (List<Node *>::Element *E = selection.back(); E; E = E->prev()) { + Node *node = E->get(); + if (!add_below_map.has(node->get_parent())) { + add_below_map.insert(node->get_parent(), node); + } + } for (Node *node : selection) { Node *parent = node->get_parent(); @@ -740,7 +746,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { dup->set_name(parent->validate_child_name(dup)); - undo_redo->add_do_method(add_below_node, "add_sibling", dup, true); + undo_redo->add_do_method(add_below_map[parent], "add_sibling", dup, true); for (Node *F : owned) { if (!duplimap.has(F)) { @@ -759,7 +765,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { undo_redo->add_do_method(ed, "live_debug_duplicate_node", edited_scene->get_path_to(node), dup->get_name()); undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).path_join(dup->get_name()))); - add_below_node = dup; + add_below_map[parent] = dup; } undo_redo->commit_action(); @@ -1236,7 +1242,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (cant_be_set_unique_names.size()) { String popup_text = TTR("Unique names already used by another node in the scene:"); popup_text += "\n"; - for (StringName name : cant_be_set_unique_names) { + for (const StringName &name : cant_be_set_unique_names) { popup_text += "\n" + String(name); } accept->set_text(popup_text); @@ -1386,7 +1392,7 @@ void SceneTreeDock::_notification(int p_what) { node_shortcuts_toggle->set_flat(true); node_shortcuts_toggle->set_icon(get_editor_theme_icon(SNAME("Favorites"))); node_shortcuts_toggle->set_toggle_mode(true); - node_shortcuts_toggle->set_tooltip_text(TTR("Switch to Favorite Nodes")); + node_shortcuts_toggle->set_tooltip_text(TTR("Toggle the display of favorite nodes.")); node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection")); node_shortcuts_toggle->set_anchors_and_offsets_preset(Control::PRESET_CENTER_RIGHT); node_shortcuts_toggle->connect("pressed", callable_mp(this, &SceneTreeDock::_update_create_root_dialog)); @@ -1558,7 +1564,9 @@ void SceneTreeDock::_load_request(const String &p_path) { } void SceneTreeDock::_script_open_request(const Ref<Script> &p_script) { - EditorNode::get_singleton()->edit_resource(p_script); + if (ScriptEditor::get_singleton()->edit(p_script, true)) { + EditorNode::get_singleton()->editor_select(EditorNode::EDITOR_SCRIPT); + } } void SceneTreeDock::_push_item(Object *p_object) { @@ -2311,18 +2319,121 @@ void SceneTreeDock::_toggle_placeholder_from_selection() { } } -void SceneTreeDock::_toggle_editable_children(Node *p_node) { - if (p_node) { - bool editable = !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); - EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(p_node, editable); - if (editable) { - p_node->set_scene_instance_load_placeholder(false); +void SceneTreeDock::_reparent_nodes_to_root(Node *p_root, const Array &p_nodes, Node *p_owner) { + List<Node *> nodes; + for (int i = 0; i < p_nodes.size(); i++) { + Node *node = Object::cast_to<Node>(p_nodes[i]); + ERR_FAIL_NULL(node); + nodes.push_back(node); + } + + for (Node *node : nodes) { + node->set_owner(p_owner); + List<Node *> owned; + node->get_owned_by(p_owner, &owned); + String original_name = node->get_name(); + node->reparent(p_root); + node->set_name(original_name); + + for (Node *F : owned) { + F->set_owner(p_owner); } + } +} + +void SceneTreeDock::_reparent_nodes_to_paths_with_transform_and_name(Node *p_root, const Array &p_nodes, const Array &p_paths, const Array &p_transforms, const Array &p_names, Node *p_owner) { + ERR_FAIL_COND(p_nodes.size() != p_paths.size()); + ERR_FAIL_COND(p_nodes.size() != p_transforms.size()); + ERR_FAIL_COND(p_nodes.size() != p_names.size()); + + for (int i = 0; i < p_nodes.size(); i++) { + Node *node = Object::cast_to<Node>(p_nodes[i]); + ERR_FAIL_NULL(node); + const NodePath &np = p_paths[i]; + Node *parent_node = p_root->get_node_or_null(np); + ERR_FAIL_NULL(parent_node); + + List<Node *> owned; + node->get_owned_by(p_owner, &owned); + node->reparent(parent_node); + node->set_name(p_names[i]); + Node3D *node_3d = Object::cast_to<Node3D>(node); + if (node_3d) { + node_3d->set_transform(p_transforms[i]); + } else { + Node2D *node_2d = Object::cast_to<Node2D>(node); + if (node_2d) { + node_2d->set_transform(p_transforms[i]); + } + } + + for (Node *F : owned) { + F->set_owner(p_owner); + } + } +} + +void SceneTreeDock::_toggle_editable_children(Node *p_node) { + if (!p_node) { + return; + } + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + + undo_redo->create_action(TTR("Toggle Editable Children")); - Node3DEditor::get_singleton()->update_all_gizmos(p_node); + bool editable = !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); - scene_tree->update_tree(); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_editable_instance", p_node, !editable); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_editable_instance", p_node, editable); + + if (editable) { + bool original_scene_instance_load_placeholder = p_node->get_scene_instance_load_placeholder(); + + undo_redo->add_undo_method(p_node, "set_scene_instance_load_placeholder", original_scene_instance_load_placeholder); + undo_redo->add_do_method(p_node, "set_scene_instance_load_placeholder", false); + } else { + List<Node *> owned; + p_node->get_owned_by(edited_scene, &owned); + + // Get the original paths, transforms, and names for undo. + Array owned_nodes_array; + Array paths_array; + Array transform_array; + Array name_array; + + for (Node *owned_node : owned) { + if (owned_node != p_node && owned_node != edited_scene && owned_node->get_owner() == edited_scene && owned_node->get_parent()->get_owner() != edited_scene) { + owned_nodes_array.push_back(owned_node); + paths_array.push_back(p_node->get_path_to(owned_node->get_parent())); + name_array.push_back(owned_node->get_name()); + Node3D *node_3d = Object::cast_to<Node3D>(owned_node); + if (node_3d) { + transform_array.push_back(node_3d->get_transform()); + } else { + Node2D *node_2d = Object::cast_to<Node2D>(owned_node); + if (node_2d) { + transform_array.push_back(node_2d->get_transform()); + } else { + transform_array.push_back(Variant()); + } + } + } + } + + if (!owned_nodes_array.is_empty()) { + undo_redo->add_undo_method(this, "_reparent_nodes_to_paths_with_transform_and_name", p_node, owned_nodes_array, paths_array, transform_array, name_array, edited_scene); + undo_redo->add_do_method(this, "_reparent_nodes_to_root", p_node, owned_nodes_array, edited_scene); + } } + + undo_redo->add_undo_method(Node3DEditor::get_singleton(), "update_all_gizmos", p_node); + undo_redo->add_do_method(Node3DEditor::get_singleton(), "update_all_gizmos", p_node); + + undo_redo->add_undo_method(scene_tree, "update_tree"); + undo_redo->add_do_method(scene_tree, "update_tree"); + + undo_redo->commit_action(); } void SceneTreeDock::_delete_confirm(bool p_cut) { @@ -2802,12 +2913,17 @@ void SceneTreeDock::_new_scene_from(String p_file) { Node *base = selection.front()->get(); HashMap<const Node *, Node *> duplimap; + HashMap<const Node *, Node *> inverse_duplimap; Node *copy = base->duplicate_from_editor(duplimap); + for (const KeyValue<const Node *, Node *> &item : duplimap) { + inverse_duplimap[item.value] = const_cast<Node *>(item.key); + } + if (copy) { // Handle Unique Nodes. for (int i = 0; i < copy->get_child_count(false); i++) { - _set_node_owner_recursive(copy->get_child(i, false), copy); + _set_node_owner_recursive(copy->get_child(i, false), copy, inverse_duplimap); } // Root node cannot ever be unique name in its own Scene! copy->set_unique_name_in_owner(false); @@ -2841,13 +2957,18 @@ void SceneTreeDock::_new_scene_from(String p_file) { } } -void SceneTreeDock::_set_node_owner_recursive(Node *p_node, Node *p_owner) { - if (!p_node->get_owner()) { - p_node->set_owner(p_owner); +void SceneTreeDock::_set_node_owner_recursive(Node *p_node, Node *p_owner, const HashMap<const Node *, Node *> &p_inverse_duplimap) { + HashMap<const Node *, Node *>::ConstIterator E = p_inverse_duplimap.find(p_node); + + if (E) { + const Node *original = E->value; + if (original->get_owner()) { + p_node->set_owner(p_owner); + } } for (int i = 0; i < p_node->get_child_count(false); i++) { - _set_node_owner_recursive(p_node->get_child(i, false), p_owner); + _set_node_owner_recursive(p_node->get_child(i, false), p_owner, p_inverse_duplimap); } } @@ -2932,7 +3053,7 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_ _normalize_drop(node, to_pos, p_type); _perform_instantiate_scenes(p_files, node, to_pos); } else { - String res_path = p_files[0]; + const String &res_path = p_files[0]; StringName res_type = EditorFileSystem::get_singleton()->get_file_type(res_path); List<String> valid_properties; @@ -3048,6 +3169,9 @@ void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) { _normalize_drop(to_node, to_pos, p_type); _do_reparent(to_node, to_pos, nodes, !Input::get_singleton()->is_key_pressed(Key::SHIFT)); + for (Node *E : nodes) { + editor_selection->add_node(E); + } } void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) { @@ -3874,6 +3998,7 @@ void SceneTreeDock::_list_all_subresources(PopupMenu *p_menu) { } p_menu->add_item(display_text); + p_menu->set_item_tooltip(-1, pair.first->get_path()); p_menu->set_item_metadata(-1, pair.first->get_instance_id()); } } @@ -3935,6 +4060,8 @@ void SceneTreeDock::_edit_subresource(int p_idx, const PopupMenu *p_from_menu) { void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_owners"), &SceneTreeDock::_set_owners); + ClassDB::bind_method(D_METHOD("_reparent_nodes_to_root"), &SceneTreeDock::_reparent_nodes_to_root); + ClassDB::bind_method(D_METHOD("_reparent_nodes_to_paths_with_transform_and_name"), &SceneTreeDock::_reparent_nodes_to_paths_with_transform_and_name); ClassDB::bind_method(D_METHOD("_update_script_button"), &SceneTreeDock::_update_script_button); @@ -3951,7 +4078,7 @@ SceneTreeDock *SceneTreeDock::singleton = nullptr; void SceneTreeDock::_update_configuration_warning() { if (singleton) { - MessageQueue::get_singleton()->push_callable(callable_mp(singleton->scene_tree, &SceneTreeEditor::update_warning)); + callable_mp(singleton->scene_tree, &SceneTreeEditor::update_warning).call_deferred(); } } diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index fc9c271526..e765ef2a6b 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -223,6 +223,9 @@ class SceneTreeDock : public VBoxContainer { void _delete_dialog_closed(); void _toggle_editable_children_from_selection(); + + void _reparent_nodes_to_root(Node *p_root, const Array &p_nodes, Node *p_owner); + void _reparent_nodes_to_paths_with_transform_and_name(Node *p_root, const Array &p_nodes, const Array &p_paths, const Array &p_transforms, const Array &p_names, Node *p_owner); void _toggle_editable_children(Node *p_node); void _toggle_placeholder_from_selection(); @@ -234,7 +237,7 @@ class SceneTreeDock : public VBoxContainer { virtual void shortcut_input(const Ref<InputEvent> &p_event) override; void _new_scene_from(String p_file); - void _set_node_owner_recursive(Node *p_node, Node *p_owner); + void _set_node_owner_recursive(Node *p_node, Node *p_owner, const HashMap<const Node *, Node *> &p_inverse_duplimap); bool _validate_no_foreign(); bool _validate_no_instance(); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 25e17ccd2a..1da8fa49b4 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -38,11 +38,11 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" #include "editor/gui/editor_validation_panel.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/grid_container.h" #include "scene/gui/line_edit.h" diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp index fb91d139a7..8d77b14ab0 100644 --- a/editor/shader_create_dialog.cpp +++ b/editor/shader_create_dialog.cpp @@ -31,9 +31,9 @@ #include "shader_create_dialog.h" #include "core/config/project_settings.h" -#include "editor/editor_scale.h" #include "editor/gui/editor_file_dialog.h" #include "editor/gui/editor_validation_panel.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/shader_include.h" #include "scene/resources/visual_shader.h" #include "servers/rendering/shader_types.h" diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp index ead0eeeae3..46f520df45 100644 --- a/editor/shader_globals_editor.cpp +++ b/editor/shader_globals_editor.cpp @@ -105,7 +105,6 @@ class ShaderGlobalsEditorInterface : public Object { protected: static void _bind_methods() { - ClassDB::bind_method("_set_var", &ShaderGlobalsEditorInterface::_set_var); ClassDB::bind_method("_var_changed", &ShaderGlobalsEditorInterface::_var_changed); ADD_SIGNAL(MethodInfo("var_changed")); } @@ -117,7 +116,7 @@ protected: return false; } - call_deferred("_set_var", p_name, p_value, existing); + callable_mp(this, &ShaderGlobalsEditorInterface::_set_var).call_deferred(p_name, p_value, existing); return true; } @@ -345,15 +344,29 @@ static Variant create_var(RS::GlobalShaderParameterType p_type) { } } +String ShaderGlobalsEditor::_check_new_variable_name(const String &p_variable_name) { + if (p_variable_name.is_empty()) { + return TTR("Name cannot be empty."); + } + + if (!p_variable_name.is_valid_identifier()) { + return TTR("Name must be a valid identifier."); + } + + return ""; +} + +void ShaderGlobalsEditor::_variable_name_text_changed(const String &p_variable_name) { + const String &warning = _check_new_variable_name(p_variable_name.strip_edges()); + variable_add->set_tooltip_text(warning); + variable_add->set_disabled(!warning.is_empty()); +} + void ShaderGlobalsEditor::_variable_added() { String var = variable_name->get_text().strip_edges(); - if (var.is_empty() || !var.is_valid_identifier()) { - EditorNode::get_singleton()->show_warning(TTR("Please specify a valid shader uniform identifier name.")); - return; - } if (RenderingServer::get_singleton()->global_shader_parameter_get(var).get_type() != Variant::NIL) { - EditorNode::get_singleton()->show_warning(vformat(TTR("Global shader parameter '%s' already exists'"), var)); + EditorNode::get_singleton()->show_warning(vformat(TTR("Global shader parameter '%s' already exists."), var)); return; } @@ -417,6 +430,10 @@ void ShaderGlobalsEditor::_notification(int p_what) { } } break; + case NOTIFICATION_THEME_CHANGED: { + variable_add->set_icon(get_editor_theme_icon(SNAME("Add"))); + } break; + case NOTIFICATION_PREDELETE: { inspector->edit(nullptr); } break; @@ -432,6 +449,9 @@ ShaderGlobalsEditor::ShaderGlobalsEditor() { add_menu_hb->add_child(memnew(Label(TTR("Name:")))); variable_name = memnew(LineEdit); variable_name->set_h_size_flags(SIZE_EXPAND_FILL); + variable_name->set_clear_button_enabled(true); + variable_name->connect("text_changed", callable_mp(this, &ShaderGlobalsEditor::_variable_name_text_changed)); + add_menu_hb->add_child(variable_name); add_menu_hb->add_child(memnew(Label(TTR("Type:")))); @@ -444,6 +464,7 @@ ShaderGlobalsEditor::ShaderGlobalsEditor() { } variable_add = memnew(Button(TTR("Add"))); + variable_add->set_disabled(true); add_menu_hb->add_child(variable_add); variable_add->connect("pressed", callable_mp(this, &ShaderGlobalsEditor::_variable_added)); diff --git a/editor/shader_globals_editor.h b/editor/shader_globals_editor.h index 590da342d4..fc50564aae 100644 --- a/editor/shader_globals_editor.h +++ b/editor/shader_globals_editor.h @@ -49,6 +49,9 @@ class ShaderGlobalsEditor : public VBoxContainer { OptionButton *variable_type = nullptr; Button *variable_add = nullptr; + String _check_new_variable_name(const String &p_variable_name); + + void _variable_name_text_changed(const String &p_variable_name); void _variable_added(); void _variable_deleted(const String &p_variable); void _changed(); diff --git a/editor/surface_upgrade_tool.cpp b/editor/surface_upgrade_tool.cpp index 78ebe43c96..4edfb92b01 100644 --- a/editor/surface_upgrade_tool.cpp +++ b/editor/surface_upgrade_tool.cpp @@ -33,9 +33,9 @@ #include "editor/editor_file_system.h" #include "editor/editor_log.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/gui/editor_toaster.h" +#include "editor/themes/editor_scale.h" #include "scene/scene_string_names.h" #include "servers/rendering_server.h" @@ -106,7 +106,7 @@ void SurfaceUpgradeTool::prepare_upgrade() { EditorSettings::get_singleton()->set_project_metadata("surface_upgrade_tool", "resave_paths", resave_paths); // Delay to avoid deadlocks, since this dialog can be triggered by loading a scene. - MessageQueue::get_singleton()->push_callable(callable_mp(EditorNode::get_singleton(), &EditorNode::restart_editor)); + callable_mp(EditorNode::get_singleton(), &EditorNode::restart_editor).call_deferred(); } // Ensure that the warnings and popups are skipped. diff --git a/editor/themes/SCsub b/editor/themes/SCsub new file mode 100644 index 0000000000..41b20f8a78 --- /dev/null +++ b/editor/themes/SCsub @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +Import("env") + +import glob +import editor_theme_builders + + +# Fonts +flist = glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.ttf") +flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.otf")) +flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff")) +flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff2")) +flist.sort() +env.Depends("#editor/themes/builtin_fonts.gen.h", flist) +env.CommandNoCache( + "#editor/themes/builtin_fonts.gen.h", + flist, + env.Run(editor_theme_builders.make_fonts_header, "Generating builtin fonts header."), +) + +env.add_source_files(env.editor_sources, "*.cpp") diff --git a/editor/themes/editor_color_map.cpp b/editor/themes/editor_color_map.cpp new file mode 100644 index 0000000000..0b3a237244 --- /dev/null +++ b/editor/themes/editor_color_map.cpp @@ -0,0 +1,204 @@ +/**************************************************************************/ +/* editor_color_map.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "editor_color_map.h" + +HashMap<Color, Color> EditorColorMap::color_conversion_map; +HashSet<StringName> EditorColorMap::color_conversion_exceptions; + +void EditorColorMap::add_conversion_color_pair(const String p_from_color, const String p_to_color) { + color_conversion_map[Color::html(p_from_color)] = Color::html(p_to_color); +} + +void EditorColorMap::add_conversion_exception(const StringName &p_icon_name) { + color_conversion_exceptions.insert(p_icon_name); +} + +void EditorColorMap::create() { + // Some of the colors below are listed for completeness sake. + // This can be a basis for proper palette validation later. + + // Convert: FROM TO + add_conversion_color_pair("#478cbf", "#478cbf"); // Godot Blue + add_conversion_color_pair("#414042", "#414042"); // Godot Gray + + add_conversion_color_pair("#ffffff", "#414141"); // Pure white + add_conversion_color_pair("#fefefe", "#fefefe"); // Forced light color + add_conversion_color_pair("#000000", "#bfbfbf"); // Pure black + add_conversion_color_pair("#010101", "#010101"); // Forced dark color + + // Keep pure RGB colors as is, but list them for explicitness. + add_conversion_color_pair("#ff0000", "#ff0000"); // Pure red + add_conversion_color_pair("#00ff00", "#00ff00"); // Pure green + add_conversion_color_pair("#0000ff", "#0000ff"); // Pure blue + + // GUI Colors + add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Common icon color + add_conversion_color_pair("#808080", "#808080"); // GUI disabled color + add_conversion_color_pair("#b3b3b3", "#363636"); // GUI disabled light color + add_conversion_color_pair("#699ce8", "#699ce8"); // GUI highlight color + add_conversion_color_pair("#f9f9f9", "#606060"); // Scrollbar grabber highlight color + + add_conversion_color_pair("#c38ef1", "#a85de9"); // Animation + add_conversion_color_pair("#8da5f3", "#3d64dd"); // 2D + add_conversion_color_pair("#7582a8", "#6d83c8"); // 2D Abstract + add_conversion_color_pair("#fc7f7f", "#cd3838"); // 3D + add_conversion_color_pair("#b56d6d", "#be6a6a"); // 3D Abstract + add_conversion_color_pair("#8eef97", "#2fa139"); // GUI Control + add_conversion_color_pair("#76ad7b", "#64a66a"); // GUI Control Abstract + + add_conversion_color_pair("#5fb2ff", "#0079f0"); // Selection (blue) + add_conversion_color_pair("#003e7a", "#2b74bb"); // Selection (darker blue) + add_conversion_color_pair("#f7f5cf", "#615f3a"); // Gizmo (yellow) + + // Rainbow + add_conversion_color_pair("#ff4545", "#ff2929"); // Red + add_conversion_color_pair("#ffe345", "#ffe337"); // Yellow + add_conversion_color_pair("#80ff45", "#74ff34"); // Green + add_conversion_color_pair("#45ffa2", "#2cff98"); // Aqua + add_conversion_color_pair("#45d7ff", "#22ccff"); // Blue + add_conversion_color_pair("#8045ff", "#702aff"); // Purple + add_conversion_color_pair("#ff4596", "#ff2781"); // Pink + + // Audio gradients + add_conversion_color_pair("#e1da5b", "#d6cf4b"); // Yellow + + add_conversion_color_pair("#62aeff", "#1678e0"); // Frozen gradient top + add_conversion_color_pair("#75d1e6", "#41acc5"); // Frozen gradient middle + add_conversion_color_pair("#84ffee", "#49ccba"); // Frozen gradient bottom + + add_conversion_color_pair("#f70000", "#c91616"); // Color track red + add_conversion_color_pair("#eec315", "#d58c0b"); // Color track orange + add_conversion_color_pair("#dbee15", "#b7d10a"); // Color track yellow + add_conversion_color_pair("#288027", "#218309"); // Color track green + + // Other objects + add_conversion_color_pair("#ffca5f", "#fea900"); // Mesh resource (orange) + add_conversion_color_pair("#2998ff", "#68b6ff"); // Shape resource (blue) + add_conversion_color_pair("#a2d2ff", "#4998e3"); // Shape resource (light blue) + add_conversion_color_pair("#69c4d4", "#29a3cc"); // Input event highlight (light blue) + + // Animation editor tracks + // The property track icon color is set by the common icon color. + add_conversion_color_pair("#ea7940", "#bd5e2c"); // 3D Position track + add_conversion_color_pair("#ff2b88", "#bd165f"); // 3D Rotation track + add_conversion_color_pair("#eac840", "#bd9d1f"); // 3D Scale track + add_conversion_color_pair("#3cf34e", "#16a827"); // Call Method track + add_conversion_color_pair("#2877f6", "#236be6"); // Bezier Curve track + add_conversion_color_pair("#eae440", "#9f9722"); // Audio Playback track + add_conversion_color_pair("#a448f0", "#9853ce"); // Animation Playback track + add_conversion_color_pair("#5ad5c4", "#0a9c88"); // Blend Shape track + + // Control layouts + add_conversion_color_pair("#d6d6d6", "#474747"); // Highlighted part + add_conversion_color_pair("#474747", "#d6d6d6"); // Background part + add_conversion_color_pair("#919191", "#6e6e6e"); // Border part + + // TileSet editor icons + add_conversion_color_pair("#fce00e", "#aa8d24"); // New Single Tile + add_conversion_color_pair("#0e71fc", "#0350bd"); // New Autotile + add_conversion_color_pair("#c6ced4", "#828f9b"); // New Atlas + + // Variant types + add_conversion_color_pair("#41ecad", "#25e3a0"); // Variant + add_conversion_color_pair("#6f91f0", "#6d8eeb"); // bool + add_conversion_color_pair("#5abbef", "#4fb2e9"); // int/uint + add_conversion_color_pair("#35d4f4", "#27ccf0"); // float + add_conversion_color_pair("#4593ec", "#4690e7"); // String + add_conversion_color_pair("#ee5677", "#ee7991"); // AABB + add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Array + add_conversion_color_pair("#e1ec41", "#b2bb19"); // Basis + add_conversion_color_pair("#54ed9e", "#57e99f"); // Dictionary + add_conversion_color_pair("#417aec", "#6993ec"); // NodePath + add_conversion_color_pair("#55f3e3", "#12d5c3"); // Object + add_conversion_color_pair("#f74949", "#f77070"); // Plane + add_conversion_color_pair("#44bd44", "#46b946"); // Projection + add_conversion_color_pair("#ec418e", "#ec69a3"); // Quaternion + add_conversion_color_pair("#f1738f", "#ee758e"); // Rect2 + add_conversion_color_pair("#41ec80", "#2ce573"); // RID + add_conversion_color_pair("#b9ec41", "#96ce1a"); // Transform2D + add_conversion_color_pair("#f68f45", "#f49047"); // Transform3D + add_conversion_color_pair("#ac73f1", "#ad76ee"); // Vector2 + add_conversion_color_pair("#de66f0", "#dc6aed"); // Vector3 + add_conversion_color_pair("#f066bd", "#ed6abd"); // Vector4 + + // Visual shaders + add_conversion_color_pair("#77ce57", "#67c046"); // Vector funcs + add_conversion_color_pair("#ea686c", "#d95256"); // Vector transforms + add_conversion_color_pair("#eac968", "#d9b64f"); // Textures and cubemaps + add_conversion_color_pair("#cf68ea", "#c050dd"); // Functions and expressions + + // These icons should not be converted. + add_conversion_exception("EditorPivot"); + add_conversion_exception("EditorHandle"); + add_conversion_exception("Editor3DHandle"); + add_conversion_exception("EditorBoneHandle"); + add_conversion_exception("Godot"); + add_conversion_exception("Sky"); + add_conversion_exception("EditorControlAnchor"); + add_conversion_exception("DefaultProjectIcon"); + add_conversion_exception("ZoomMore"); + add_conversion_exception("ZoomLess"); + add_conversion_exception("ZoomReset"); + add_conversion_exception("LockViewport"); + add_conversion_exception("GroupViewport"); + add_conversion_exception("StatusError"); + add_conversion_exception("StatusSuccess"); + add_conversion_exception("StatusWarning"); + add_conversion_exception("OverbrightIndicator"); + add_conversion_exception("MaterialPreviewCube"); + add_conversion_exception("MaterialPreviewSphere"); + add_conversion_exception("MaterialPreviewLight1"); + add_conversion_exception("MaterialPreviewLight2"); + + // GUI + add_conversion_exception("GuiChecked"); + add_conversion_exception("GuiRadioChecked"); + add_conversion_exception("GuiIndeterminate"); + add_conversion_exception("GuiCloseCustomizable"); + add_conversion_exception("GuiGraphNodePort"); + add_conversion_exception("GuiResizer"); + add_conversion_exception("GuiMiniCheckerboard"); + + /// Code Editor. + add_conversion_exception("GuiTab"); + add_conversion_exception("GuiSpace"); + add_conversion_exception("CodeFoldedRightArrow"); + add_conversion_exception("CodeFoldDownArrow"); + add_conversion_exception("CodeRegionFoldedRightArrow"); + add_conversion_exception("CodeRegionFoldDownArrow"); + add_conversion_exception("TextEditorPlay"); + add_conversion_exception("Breakpoint"); +} + +void EditorColorMap::finish() { + color_conversion_map.clear(); + color_conversion_exceptions.clear(); +} diff --git a/editor/editor_themes.h b/editor/themes/editor_color_map.h index 7d913ccc40..4debd37faf 100644 --- a/editor/editor_themes.h +++ b/editor/themes/editor_color_map.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* editor_themes.h */ +/* editor_color_map.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef EDITOR_THEMES_H -#define EDITOR_THEMES_H +#ifndef EDITOR_COLOR_MAP_H +#define EDITOR_COLOR_MAP_H -#include "scene/resources/texture.h" -#include "scene/resources/theme.h" +#include "core/math/color.h" +#include "core/string/string_name.h" +#include "core/templates/hash_map.h" +#include "core/templates/hash_set.h" // The default icon theme is designed to be used for a dark theme. This map stores // Color values to convert to other colors for better readability on a light theme. @@ -55,27 +57,4 @@ public: static void finish(); }; -class EditorTheme : public Theme { - GDCLASS(EditorTheme, Theme); - - static Vector<StringName> editor_theme_types; - -public: - virtual Color get_color(const StringName &p_name, const StringName &p_theme_type) const override; - virtual int get_constant(const StringName &p_name, const StringName &p_theme_type) const override; - virtual Ref<Font> get_font(const StringName &p_name, const StringName &p_theme_type) const override; - virtual int get_font_size(const StringName &p_name, const StringName &p_theme_type) const override; - virtual Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_theme_type) const override; - virtual Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_theme_type) const override; - - static void initialize(); - static void finalize(); -}; - -Ref<Theme> create_editor_theme(Ref<Theme> p_theme = nullptr); - -Ref<Theme> create_custom_theme(Ref<Theme> p_theme = nullptr); - -String get_default_project_icon(); - -#endif // EDITOR_THEMES_H +#endif // EDITOR_COLOR_MAP_H diff --git a/editor/editor_fonts.cpp b/editor/themes/editor_fonts.cpp index 1e1dff61b9..fc3631653c 100644 --- a/editor/editor_fonts.cpp +++ b/editor/themes/editor_fonts.cpp @@ -30,11 +30,11 @@ #include "editor_fonts.h" -#include "builtin_fonts.gen.h" #include "core/io/dir_access.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/builtin_fonts.gen.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/font.h" Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { @@ -106,7 +106,7 @@ Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, Ty return font_var; } -void editor_register_fonts(Ref<Theme> p_theme) { +void editor_register_fonts(const Ref<Theme> &p_theme) { OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Register Fonts"); Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); diff --git a/editor/editor_fonts.h b/editor/themes/editor_fonts.h index 1705879f59..b612797df1 100644 --- a/editor/editor_fonts.h +++ b/editor/themes/editor_fonts.h @@ -33,6 +33,6 @@ #include "scene/resources/theme.h" -void editor_register_fonts(Ref<Theme> p_theme); +void editor_register_fonts(const Ref<Theme> &p_theme); #endif // EDITOR_FONTS_H diff --git a/editor/themes/editor_icons.cpp b/editor/themes/editor_icons.cpp new file mode 100644 index 0000000000..bb767747f3 --- /dev/null +++ b/editor/themes/editor_icons.cpp @@ -0,0 +1,252 @@ +/**************************************************************************/ +/* editor_icons.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "editor_icons.h" + +#include "editor/editor_settings.h" +#include "editor/editor_string_names.h" +#include "editor/themes/editor_color_map.h" +#include "editor/themes/editor_icons.gen.h" +#include "editor/themes/editor_scale.h" +#include "scene/resources/image_texture.h" +#include "scene/resources/texture.h" + +#include "modules/modules_enabled.gen.h" // For svg. +#ifdef MODULE_SVG_ENABLED +#include "modules/svg/image_loader_svg.h" +#endif + +void editor_configure_icons(bool p_dark_theme) { +#ifdef MODULE_SVG_ENABLED + if (p_dark_theme) { + ImageLoaderSVG::set_forced_color_map(HashMap<Color, Color>()); + } else { + ImageLoaderSVG::set_forced_color_map(EditorColorMap::get_color_conversion_map()); + } +#else + WARN_PRINT("SVG support disabled, editor icons won't be rendered."); +#endif +} + +// See also `generate_icon()` in `scene/theme/default_theme.cpp`. +Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float p_saturation, const HashMap<Color, Color> &p_convert_colors = HashMap<Color, Color>()) { + Ref<Image> img = memnew(Image); + +#ifdef MODULE_SVG_ENABLED + // Upsample icon generation only if the editor scale isn't an integer multiplier. + // Generating upsampled icons is slower, and the benefit is hardly visible + // with integer editor scales. + const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale); + Error err = ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors); + ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in editor theme."); + if (p_saturation != 1.0) { + img->adjust_bcs(1.0, 1.0, p_saturation); + } +#else + // If the SVG module is disabled, we can't really display the UI well, but at least we won't crash. + // 16 pixels is used as it's the most common base size for Godot icons. + img = Image::create_empty(16 * p_scale, 16 * p_scale, false, Image::FORMAT_RGBA8); +#endif + + return ImageTexture::create_from_image(img); +} + +float get_gizmo_handle_scale(const String &gizmo_handle_name = "") { + const float scale_gizmo_handles_for_touch = EDITOR_GET("interface/touchscreen/scale_gizmo_handles"); + if (scale_gizmo_handles_for_touch > 1.0f) { + // The names of the icons that require additional scaling. + static HashSet<StringName> gizmo_to_scale; + if (gizmo_to_scale.is_empty()) { + gizmo_to_scale.insert("EditorHandle"); + gizmo_to_scale.insert("EditorHandleAdd"); + gizmo_to_scale.insert("EditorHandleDisabled"); + gizmo_to_scale.insert("EditorCurveHandle"); + gizmo_to_scale.insert("EditorPathSharpHandle"); + gizmo_to_scale.insert("EditorPathSmoothHandle"); + } + + if (gizmo_to_scale.has(gizmo_handle_name)) { + return EDSCALE * scale_gizmo_handles_for_touch; + } + } + + return EDSCALE; +} + +void editor_register_icons(const Ref<Theme> &p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs) { + const String benchmark_key = vformat("Generate Icons (%s)", (p_only_thumbs ? "Only Thumbs" : "All")); + OS::get_singleton()->benchmark_begin_measure("EditorTheme", benchmark_key); + + // Before we register the icons, we adjust their colors and saturation. + // Most icons follow the standard rules for color conversion to follow the editor + // theme's polarity (dark/light). We also adjust the saturation for most icons, + // following the editor setting. + // Some icons are excluded from this conversion, and instead use the configured + // accent color to replace their innate accent color to match the editor theme. + // And then some icons are completely excluded from the conversion. + + // Standard color conversion map. + HashMap<Color, Color> color_conversion_map; + // Icons by default are set up for the dark theme, so if the theme is light, + // we apply the dark-to-light color conversion map. + if (!p_dark_theme) { + for (KeyValue<Color, Color> &E : EditorColorMap::get_color_conversion_map()) { + color_conversion_map[E.key] = E.value; + } + } + // These colors should be converted even if we are using a dark theme. + const Color error_color = p_theme->get_color(SNAME("error_color"), EditorStringName(Editor)); + const Color success_color = p_theme->get_color(SNAME("success_color"), EditorStringName(Editor)); + const Color warning_color = p_theme->get_color(SNAME("warning_color"), EditorStringName(Editor)); + color_conversion_map[Color::html("#ff5f5f")] = error_color; + color_conversion_map[Color::html("#5fff97")] = success_color; + color_conversion_map[Color::html("#ffdd65")] = warning_color; + + // The names of the icons to exclude from the standard color conversion. + HashSet<StringName> conversion_exceptions = EditorColorMap::get_color_conversion_exceptions(); + + // The names of the icons to exclude when adjusting for saturation. + HashSet<StringName> saturation_exceptions; + saturation_exceptions.insert("DefaultProjectIcon"); + saturation_exceptions.insert("Godot"); + saturation_exceptions.insert("Logo"); + + // Accent color conversion map. + // It is used on some icons (checkbox, radio, toggle, etc.), regardless of the dark + // or light mode. + HashMap<Color, Color> accent_color_map; + HashSet<StringName> accent_color_icons; + + const Color accent_color = p_theme->get_color(SNAME("accent_color"), EditorStringName(Editor)); + accent_color_map[Color::html("699ce8")] = accent_color; + if (accent_color.get_luminance() > 0.75) { + accent_color_map[Color::html("ffffff")] = Color(0.2, 0.2, 0.2); + } + + accent_color_icons.insert("GuiChecked"); + accent_color_icons.insert("GuiRadioChecked"); + accent_color_icons.insert("GuiIndeterminate"); + accent_color_icons.insert("GuiToggleOn"); + accent_color_icons.insert("GuiToggleOnMirrored"); + accent_color_icons.insert("PlayOverlay"); + + // Generate icons. + if (!p_only_thumbs) { + for (int i = 0; i < editor_icons_count; i++) { + Ref<ImageTexture> icon; + + const String &editor_icon_name = editor_icons_names[i]; + if (accent_color_icons.has(editor_icon_name)) { + icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), 1.0, accent_color_map); + } else { + float saturation = p_icon_saturation; + if (saturation_exceptions.has(editor_icon_name)) { + saturation = 1.0; + } + + if (conversion_exceptions.has(editor_icon_name)) { + icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation); + } else { + icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation, color_conversion_map); + } + } + + p_theme->set_icon(editor_icon_name, EditorStringName(EditorIcons), icon); + } + } + + // Generate thumbnail icons with the given thumbnail size. + // See editor\icons\editor_icons_builders.py for the code that determines which icons are thumbnails. + if (p_thumb_size >= 64) { + const float scale = (float)p_thumb_size / 64.0 * EDSCALE; + for (int i = 0; i < editor_bg_thumbs_count; i++) { + const int index = editor_bg_thumbs_indices[i]; + Ref<ImageTexture> icon; + + if (accent_color_icons.has(editor_icons_names[index])) { + icon = editor_generate_icon(index, scale, 1.0, accent_color_map); + } else { + float saturation = p_icon_saturation; + if (saturation_exceptions.has(editor_icons_names[index])) { + saturation = 1.0; + } + + if (conversion_exceptions.has(editor_icons_names[index])) { + icon = editor_generate_icon(index, scale, saturation); + } else { + icon = editor_generate_icon(index, scale, saturation, color_conversion_map); + } + } + + p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon); + } + } else { + const float scale = (float)p_thumb_size / 32.0 * EDSCALE; + for (int i = 0; i < editor_md_thumbs_count; i++) { + const int index = editor_md_thumbs_indices[i]; + Ref<ImageTexture> icon; + + if (accent_color_icons.has(editor_icons_names[index])) { + icon = editor_generate_icon(index, scale, 1.0, accent_color_map); + } else { + float saturation = p_icon_saturation; + if (saturation_exceptions.has(editor_icons_names[index])) { + saturation = 1.0; + } + + if (conversion_exceptions.has(editor_icons_names[index])) { + icon = editor_generate_icon(index, scale, saturation); + } else { + icon = editor_generate_icon(index, scale, saturation, color_conversion_map); + } + } + + p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon); + } + } + OS::get_singleton()->benchmark_end_measure("EditorTheme", benchmark_key); +} + +void editor_copy_icons(const Ref<Theme> &p_theme, const Ref<Theme> &p_old_theme) { + for (int i = 0; i < editor_icons_count; i++) { + p_theme->set_icon(editor_icons_names[i], EditorStringName(EditorIcons), p_old_theme->get_icon(editor_icons_names[i], EditorStringName(EditorIcons))); + } +} + +// Returns the SVG code for the default project icon. +String get_default_project_icon() { + // FIXME: This icon can probably be predefined in editor_icons.gen.h so we don't have to look up. + for (int i = 0; i < editor_icons_count; i++) { + if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) { + return String(editor_icons_sources[i]); + } + } + return String(); +} diff --git a/editor/themes/editor_icons.h b/editor/themes/editor_icons.h new file mode 100644 index 0000000000..2094ebf27c --- /dev/null +++ b/editor/themes/editor_icons.h @@ -0,0 +1,42 @@ +/**************************************************************************/ +/* editor_icons.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef EDITOR_ICONS_H +#define EDITOR_ICONS_H + +#include "scene/resources/theme.h" + +void editor_configure_icons(bool p_dark_theme); +void editor_register_icons(const Ref<Theme> &p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs = false); +void editor_copy_icons(const Ref<Theme> &p_theme, const Ref<Theme> &p_old_theme); + +String get_default_project_icon(); + +#endif // EDITOR_ICONS_H diff --git a/editor/editor_scale.cpp b/editor/themes/editor_scale.cpp index 0670e98e2c..0670e98e2c 100644 --- a/editor/editor_scale.cpp +++ b/editor/themes/editor_scale.cpp diff --git a/editor/editor_scale.h b/editor/themes/editor_scale.h index b3583fdcee..b3583fdcee 100644 --- a/editor/editor_scale.h +++ b/editor/themes/editor_scale.h diff --git a/editor/themes/editor_theme.cpp b/editor/themes/editor_theme.cpp new file mode 100644 index 0000000000..ab7c808303 --- /dev/null +++ b/editor/themes/editor_theme.cpp @@ -0,0 +1,131 @@ +/**************************************************************************/ +/* editor_theme.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "editor_theme.h" + +#include "editor/editor_string_names.h" +#include "scene/theme/theme_db.h" + +Vector<StringName> EditorTheme::editor_theme_types; + +// TODO: Refactor these and corresponding Theme methods to use the bool get_xxx(r_value) pattern internally. + +// Keep in sync with Theme::get_color. +Color EditorTheme::get_color(const StringName &p_name, const StringName &p_theme_type) const { + if (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)) { + return color_map[p_theme_type][p_name]; + } else { + if (editor_theme_types.has(p_theme_type)) { + WARN_PRINT(vformat("Trying to access a non-existing editor theme color '%s' in '%s'.", p_name, p_theme_type)); + } + return Color(); + } +} + +// Keep in sync with Theme::get_constant. +int EditorTheme::get_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)) { + return constant_map[p_theme_type][p_name]; + } else { + if (editor_theme_types.has(p_theme_type)) { + WARN_PRINT(vformat("Trying to access a non-existing editor theme constant '%s' in '%s'.", p_name, p_theme_type)); + } + return 0; + } +} + +// Keep in sync with Theme::get_font. +Ref<Font> EditorTheme::get_font(const StringName &p_name, const StringName &p_theme_type) const { + if (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) { + return font_map[p_theme_type][p_name]; + } else if (has_default_font()) { + if (editor_theme_types.has(p_theme_type)) { + WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type)); + } + return default_font; + } else { + if (editor_theme_types.has(p_theme_type)) { + WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type)); + } + return ThemeDB::get_singleton()->get_fallback_font(); + } +} + +// Keep in sync with Theme::get_font_size. +int EditorTheme::get_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name) && (font_size_map[p_theme_type][p_name] > 0)) { + return font_size_map[p_theme_type][p_name]; + } else if (has_default_font_size()) { + if (editor_theme_types.has(p_theme_type)) { + WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type)); + } + return default_font_size; + } else { + if (editor_theme_types.has(p_theme_type)) { + WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type)); + } + return ThemeDB::get_singleton()->get_fallback_font_size(); + } +} + +// Keep in sync with Theme::get_icon. +Ref<Texture2D> EditorTheme::get_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) { + return icon_map[p_theme_type][p_name]; + } else { + if (editor_theme_types.has(p_theme_type)) { + WARN_PRINT(vformat("Trying to access a non-existing editor theme icon '%s' in '%s'.", p_name, p_theme_type)); + } + return ThemeDB::get_singleton()->get_fallback_icon(); + } +} + +// Keep in sync with Theme::get_stylebox. +Ref<StyleBox> EditorTheme::get_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) { + return style_map[p_theme_type][p_name]; + } else { + if (editor_theme_types.has(p_theme_type)) { + WARN_PRINT(vformat("Trying to access a non-existing editor theme stylebox '%s' in '%s'.", p_name, p_theme_type)); + } + return ThemeDB::get_singleton()->get_fallback_stylebox(); + } +} + +void EditorTheme::initialize() { + editor_theme_types.append(EditorStringName(Editor)); + editor_theme_types.append(EditorStringName(EditorFonts)); + editor_theme_types.append(EditorStringName(EditorIcons)); + editor_theme_types.append(EditorStringName(EditorStyles)); +} + +void EditorTheme::finalize() { + editor_theme_types.clear(); +} diff --git a/editor/themes/editor_theme.h b/editor/themes/editor_theme.h new file mode 100644 index 0000000000..41a60fdf96 --- /dev/null +++ b/editor/themes/editor_theme.h @@ -0,0 +1,53 @@ +/**************************************************************************/ +/* editor_theme.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef EDITOR_THEME_H +#define EDITOR_THEME_H + +#include "scene/resources/theme.h" + +class EditorTheme : public Theme { + GDCLASS(EditorTheme, Theme); + + static Vector<StringName> editor_theme_types; + +public: + virtual Color get_color(const StringName &p_name, const StringName &p_theme_type) const override; + virtual int get_constant(const StringName &p_name, const StringName &p_theme_type) const override; + virtual Ref<Font> get_font(const StringName &p_name, const StringName &p_theme_type) const override; + virtual int get_font_size(const StringName &p_name, const StringName &p_theme_type) const override; + virtual Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_theme_type) const override; + virtual Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_theme_type) const override; + + static void initialize(); + static void finalize(); +}; + +#endif // EDITOR_THEME_H diff --git a/editor/themes/editor_theme_builders.py b/editor/themes/editor_theme_builders.py new file mode 100644 index 0000000000..19b346db58 --- /dev/null +++ b/editor/themes/editor_theme_builders.py @@ -0,0 +1,41 @@ +""" +Functions used to generate source files during build time + +All such functions are invoked in a subprocess on Windows to prevent build flakiness. + +""" + +import os +from platform_methods import subprocess_main + + +def make_fonts_header(target, source, env): + dst = target[0] + + g = open(dst, "w", encoding="utf-8") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _EDITOR_FONTS_H\n") + g.write("#define _EDITOR_FONTS_H\n") + + # Saving uncompressed, since FreeType will reference from memory pointer. + for i in range(len(source)): + with open(source[i], "rb") as f: + buf = f.read() + + name = os.path.splitext(os.path.basename(source[i]))[0] + + g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n") + g.write("static const unsigned char _font_" + name + "[] = {\n") + for j in range(len(buf)): + g.write("\t" + str(buf[j]) + ",\n") + + g.write("};\n") + + g.write("#endif") + + g.close() + + +if __name__ == "__main__": + subprocess_main(globals()) diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp new file mode 100644 index 0000000000..4ce323c763 --- /dev/null +++ b/editor/themes/editor_theme_manager.cpp @@ -0,0 +1,2232 @@ +/**************************************************************************/ +/* editor_theme_manager.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "editor_theme_manager.h" + +#include "core/error/error_macros.h" +#include "core/io/resource_loader.h" +#include "editor/editor_settings.h" +#include "editor/editor_string_names.h" +#include "editor/themes/editor_color_map.h" +#include "editor/themes/editor_fonts.h" +#include "editor/themes/editor_icons.h" +#include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme.h" +#include "scene/resources/image_texture.h" +#include "scene/resources/style_box_flat.h" +#include "scene/resources/style_box_line.h" +#include "scene/resources/style_box_texture.h" +#include "scene/resources/texture.h" + +// Helper methods. + +Ref<StyleBoxTexture> make_stylebox(Ref<Texture2D> p_texture, float p_left, float p_top, float p_right, float p_bottom, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, bool p_draw_center = true) { + Ref<StyleBoxTexture> style(memnew(StyleBoxTexture)); + style->set_texture(p_texture); + style->set_texture_margin_individual(p_left * EDSCALE, p_top * EDSCALE, p_right * EDSCALE, p_bottom * EDSCALE); + style->set_content_margin_individual((p_left + p_margin_left) * EDSCALE, (p_top + p_margin_top) * EDSCALE, (p_right + p_margin_right) * EDSCALE, (p_bottom + p_margin_bottom) * EDSCALE); + style->set_draw_center(p_draw_center); + return style; +} + +Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { + Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); + style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE); + return style; +} + +Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, int p_corner_width = 0) { + Ref<StyleBoxFlat> style(memnew(StyleBoxFlat)); + style->set_bg_color(p_color); + // Adjust level of detail based on the corners' effective sizes. + style->set_corner_detail(Math::ceil(0.8 * p_corner_width * EDSCALE)); + style->set_corner_radius_all(p_corner_width * EDSCALE); + style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE); + // Work around issue about antialiased edges being blurrier (GH-35279). + style->set_anti_aliased(false); + return style; +} + +Ref<StyleBoxLine> make_line_stylebox(Color p_color, int p_thickness = 1, float p_grow_begin = 1, float p_grow_end = 1, bool p_vertical = false) { + Ref<StyleBoxLine> style(memnew(StyleBoxLine)); + style->set_color(p_color); + style->set_grow_begin(p_grow_begin); + style->set_grow_end(p_grow_end); + style->set_thickness(p_thickness); + style->set_vertical(p_vertical); + return style; +} + +// Theme generation and population routines. + +Ref<Theme> EditorThemeManager::_create_base_theme(const Ref<Theme> &p_old_theme) { + OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Base Theme"); + + Ref<EditorTheme> theme = memnew(EditorTheme); + ThemeConfiguration config = _create_theme_config(theme); + _create_shared_styles(theme, config); + + // FIXME: Make the comparison more robust and fix imprecision issues by hashing affecting values. + // TODO: Refactor the icons check into their respective file, and add a similar check for fonts. + + // Register editor icons. + // If settings are comparable to the old theme, then just copy existing icons over. + // Otherwise, regenerate them. Also check if we need to regenerate "thumb" icons. + bool keep_old_icons = false; + bool regenerate_thumb_icons = true; + if (p_old_theme != nullptr) { + // We check editor scale, theme dark/light mode, icon saturation, and accent color. + + // That doesn't really work as expected, since theme constants are integers, and scales are floats. + // So this check will never work when changing between 100-199% values. + const float prev_scale = (float)p_old_theme->get_constant(SNAME("scale"), EditorStringName(Editor)); + const bool prev_dark_theme = (bool)p_old_theme->get_constant(SNAME("dark_theme"), EditorStringName(Editor)); + const Color prev_accent_color = p_old_theme->get_color(SNAME("accent_color"), EditorStringName(Editor)); + const float prev_icon_saturation = p_old_theme->get_color(SNAME("icon_saturation"), EditorStringName(Editor)).r; + const float prev_gizmo_handle_scale = (float)p_old_theme->get_constant(SNAME("gizmo_handle_scale"), EditorStringName(Editor)); + + keep_old_icons = (Math::is_equal_approx(prev_scale, EDSCALE) && + Math::is_equal_approx(prev_gizmo_handle_scale, config.gizmo_handle_scale) && + prev_dark_theme == config.dark_theme && + prev_accent_color == config.accent_color && + prev_icon_saturation == config.icon_saturation); + + const double prev_thumb_size = (double)p_old_theme->get_constant(SNAME("thumb_size"), EditorStringName(Editor)); + + regenerate_thumb_icons = !Math::is_equal_approx(prev_thumb_size, config.thumb_size); + } + + // External functions, see editor_icons.cpp. + editor_configure_icons(config.dark_theme); + if (keep_old_icons) { + editor_copy_icons(theme, p_old_theme); + } else { + editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, false); + } + if (regenerate_thumb_icons) { + editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, true); + } + + // External function, see editor_fonts.cpp. + editor_register_fonts(theme); + + _populate_standard_styles(theme, config); + _populate_editor_styles(theme, config); + _populate_text_editor_styles(theme, config); + + OS::get_singleton()->benchmark_end_measure("EditorTheme", "Create Base Theme"); + return theme; +} + +EditorThemeManager::ThemeConfiguration EditorThemeManager::_create_theme_config(const Ref<Theme> &p_theme) { + ThemeConfiguration config; + + // Basic properties. + + config.preset = EDITOR_GET("interface/theme/preset"); + config.spacing_preset = EDITOR_GET("interface/theme/spacing_preset"); + config.dark_theme = EditorSettings::get_singleton()->is_dark_theme(); + + config.base_color = EDITOR_GET("interface/theme/base_color"); + config.accent_color = EDITOR_GET("interface/theme/accent_color"); + config.contrast = EDITOR_GET("interface/theme/contrast"); + config.icon_saturation = EDITOR_GET("interface/theme/icon_saturation"); + + // Extra properties. + + config.base_spacing = EDITOR_GET("interface/theme/base_spacing"); + config.extra_spacing = EDITOR_GET("interface/theme/additional_spacing"); + // Ensure borders are visible when using an editor scale below 100%. + config.border_width = CLAMP((int)EDITOR_GET("interface/theme/border_size"), 0, 2) * MAX(1, EDSCALE); + config.corner_radius = CLAMP((int)EDITOR_GET("interface/theme/corner_radius"), 0, 6); + + config.draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders"); + config.relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity"); + config.thumb_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size"); + config.class_icon_size = 16 * EDSCALE; + config.increase_scrollbar_touch_area = EDITOR_GET("interface/touchscreen/increase_scrollbar_touch_area"); + config.gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles"); + config.color_picker_button_height = 28 * EDSCALE; + + config.default_contrast = 0.3; // Make sure to keep this in sync with the editor settings definition. + + // Handle main theme preset. + { + if (config.preset != "Custom") { + Color preset_accent_color; + Color preset_base_color; + float preset_contrast = 0; + bool preset_draw_extra_borders = false; + + // Please use alphabetical order if you're adding a new theme here. + if (config.preset == "Breeze Dark") { + preset_accent_color = Color(0.26, 0.76, 1.00); + preset_base_color = Color(0.24, 0.26, 0.28); + preset_contrast = config.default_contrast; + } else if (config.preset == "Godot 2") { + preset_accent_color = Color(0.53, 0.67, 0.89); + preset_base_color = Color(0.24, 0.23, 0.27); + preset_contrast = config.default_contrast; + } else if (config.preset == "Gray") { + preset_accent_color = Color(0.44, 0.73, 0.98); + preset_base_color = Color(0.24, 0.24, 0.24); + preset_contrast = config.default_contrast; + } else if (config.preset == "Light") { + preset_accent_color = Color(0.18, 0.50, 1.00); + preset_base_color = Color(0.9, 0.9, 0.9); + // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation". + preset_contrast = -0.06; + } else if (config.preset == "Solarized (Dark)") { + preset_accent_color = Color(0.15, 0.55, 0.82); + preset_base_color = Color(0.04, 0.23, 0.27); + preset_contrast = config.default_contrast; + } else if (config.preset == "Solarized (Light)") { + preset_accent_color = Color(0.15, 0.55, 0.82); + preset_base_color = Color(0.89, 0.86, 0.79); + // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation". + preset_contrast = -0.06; + } else if (config.preset == "Black (OLED)") { + preset_accent_color = Color(0.45, 0.75, 1.0); + preset_base_color = Color(0, 0, 0); + // The contrast rate value is irrelevant on a fully black theme. + preset_contrast = 0.0; + preset_draw_extra_borders = true; + } else { // Default + preset_accent_color = Color(0.44, 0.73, 0.98); + preset_base_color = Color(0.21, 0.24, 0.29); + preset_contrast = config.default_contrast; + } + + config.accent_color = preset_accent_color; + config.base_color = preset_base_color; + config.contrast = preset_contrast; + config.draw_extra_borders = preset_draw_extra_borders; + + EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", config.accent_color); + EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", config.base_color); + EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", config.contrast); + EditorSettings::get_singleton()->set_initial_value("interface/theme/draw_extra_borders", config.draw_extra_borders); + } + + // Enforce values in case they were adjusted or overridden. + EditorSettings::get_singleton()->set_manually("interface/theme/preset", config.preset); + EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", config.accent_color); + EditorSettings::get_singleton()->set_manually("interface/theme/base_color", config.base_color); + EditorSettings::get_singleton()->set_manually("interface/theme/contrast", config.contrast); + EditorSettings::get_singleton()->set_manually("interface/theme/draw_extra_borders", config.draw_extra_borders); + } + + // Handle theme spacing preset. + { + if (config.spacing_preset != "Custom") { + int preset_base_spacing = 0; + int preset_extra_spacing = 0; + + if (config.spacing_preset == "Compact") { + preset_base_spacing = 0; + preset_extra_spacing = 4; + } else if (config.spacing_preset == "Spacious") { + preset_base_spacing = 6; + preset_extra_spacing = 2; + } else { // Default + preset_base_spacing = 4; + preset_extra_spacing = 0; + } + + config.base_spacing = preset_base_spacing; + config.extra_spacing = preset_extra_spacing; + + EditorSettings::get_singleton()->set_initial_value("interface/theme/base_spacing", config.base_spacing); + EditorSettings::get_singleton()->set_initial_value("interface/theme/additional_spacing", config.extra_spacing); + } + + // Enforce values in case they were adjusted or overridden. + EditorSettings::get_singleton()->set_manually("interface/theme/spacing_preset", config.spacing_preset); + EditorSettings::get_singleton()->set_manually("interface/theme/base_spacing", config.base_spacing); + EditorSettings::get_singleton()->set_manually("interface/theme/additional_spacing", config.extra_spacing); + } + + // Generated properties. + + config.base_margin = config.base_spacing; + config.increased_margin = config.base_spacing + config.extra_spacing; + config.separation_margin = (config.base_spacing + config.extra_spacing / 2) * EDSCALE; + config.popup_margin = config.base_margin * 3 * EDSCALE; + // Make sure content doesn't stick to window decorations; this can be fixed in future with layout changes. + config.window_border_margin = MAX(1, config.base_margin * 2); + config.top_bar_separation = config.base_margin * 2 * EDSCALE; + + // Force the v_separation to be even so that the spacing on top and bottom is even. + // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided. + // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example). + const int separation_base = config.increased_margin + 6; + config.forced_even_separation = separation_base + (separation_base % 2); + + return config; +} + +void EditorThemeManager::_create_shared_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config) { + // Colors. + { + // Base colors. + + p_theme->set_color("base_color", EditorStringName(Editor), p_config.base_color); + p_theme->set_color("accent_color", EditorStringName(Editor), p_config.accent_color); + + // White (dark theme) or black (light theme), will be used to generate the rest of the colors + p_config.mono_color = p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0); + + // Ensure base colors are in the 0..1 luminance range to avoid 8-bit integer overflow or text rendering issues. + // Some places in the editor use 8-bit integer colors. + p_config.dark_color_1 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast).clamp(); + p_config.dark_color_2 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast * 1.5).clamp(); + p_config.dark_color_3 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast * 2).clamp(); + + p_config.contrast_color_1 = p_config.base_color.lerp(p_config.mono_color, MAX(p_config.contrast, p_config.default_contrast)); + p_config.contrast_color_2 = p_config.base_color.lerp(p_config.mono_color, MAX(p_config.contrast * 1.5, p_config.default_contrast * 1.5)); + + p_config.highlight_color = Color(p_config.accent_color.r, p_config.accent_color.g, p_config.accent_color.b, 0.275); + p_config.highlight_disabled_color = p_config.highlight_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5); + + p_config.success_color = Color(0.45, 0.95, 0.5); + p_config.warning_color = Color(1, 0.87, 0.4); + p_config.error_color = Color(1, 0.47, 0.42); + if (!p_config.dark_theme) { + // Darken some colors to be readable on a light background. + p_config.success_color = p_config.success_color.lerp(p_config.mono_color, 0.35); + p_config.warning_color = p_config.warning_color.lerp(p_config.mono_color, 0.35); + p_config.error_color = p_config.error_color.lerp(p_config.mono_color, 0.25); + } + + p_theme->set_color("mono_color", EditorStringName(Editor), p_config.mono_color); + p_theme->set_color("dark_color_1", EditorStringName(Editor), p_config.dark_color_1); + p_theme->set_color("dark_color_2", EditorStringName(Editor), p_config.dark_color_2); + p_theme->set_color("dark_color_3", EditorStringName(Editor), p_config.dark_color_3); + p_theme->set_color("contrast_color_1", EditorStringName(Editor), p_config.contrast_color_1); + p_theme->set_color("contrast_color_2", EditorStringName(Editor), p_config.contrast_color_2); + p_theme->set_color("highlight_color", EditorStringName(Editor), p_config.highlight_color); + p_theme->set_color("highlight_disabled_color", EditorStringName(Editor), p_config.highlight_disabled_color); + p_theme->set_color("success_color", EditorStringName(Editor), p_config.success_color); + p_theme->set_color("warning_color", EditorStringName(Editor), p_config.warning_color); + p_theme->set_color("error_color", EditorStringName(Editor), p_config.error_color); + + // Only used when the Draw Extra Borders editor setting is enabled. + p_config.extra_border_color_1 = Color(0.5, 0.5, 0.5); + p_config.extra_border_color_2 = p_config.dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7); + + p_theme->set_color("extra_border_color_1", EditorStringName(Editor), p_config.extra_border_color_1); + p_theme->set_color("extra_border_color_2", EditorStringName(Editor), p_config.extra_border_color_2); + + // Font colors. + + p_config.font_color = p_config.mono_color.lerp(p_config.base_color, 0.25); + p_config.font_focus_color = p_config.mono_color.lerp(p_config.base_color, 0.125); + p_config.font_hover_color = p_config.mono_color.lerp(p_config.base_color, 0.125); + p_config.font_pressed_color = p_config.accent_color; + p_config.font_hover_pressed_color = p_config.font_hover_color.lerp(p_config.accent_color, 0.74); + p_config.font_disabled_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.35); + p_config.font_readonly_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.65); + p_config.font_placeholder_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.6); + p_config.font_outline_color = Color(0, 0, 0, 0); + + p_theme->set_color("font_color", EditorStringName(Editor), p_config.font_color); + p_theme->set_color("font_focus_color", EditorStringName(Editor), p_config.font_focus_color); + p_theme->set_color("font_hover_color", EditorStringName(Editor), p_config.font_hover_color); + p_theme->set_color("font_pressed_color", EditorStringName(Editor), p_config.font_pressed_color); + p_theme->set_color("font_hover_pressed_color", EditorStringName(Editor), p_config.font_hover_pressed_color); + p_theme->set_color("font_disabled_color", EditorStringName(Editor), p_config.font_disabled_color); + p_theme->set_color("font_readonly_color", EditorStringName(Editor), p_config.font_readonly_color); + p_theme->set_color("font_placeholder_color", EditorStringName(Editor), p_config.font_placeholder_color); + p_theme->set_color("font_outline_color", EditorStringName(Editor), p_config.font_outline_color); + + // Icon colors. + + p_config.icon_normal_color = Color(1, 1, 1); + p_config.icon_focus_color = p_config.icon_normal_color * (p_config.dark_theme ? 1.15 : 1.45); + p_config.icon_focus_color.a = 1.0; + p_config.icon_hover_color = p_config.icon_focus_color; + // Make the pressed icon color overbright because icons are not completely white on a dark theme. + // On a light theme, icons are dark, so we need to modulate them with an even brighter color. + p_config.icon_pressed_color = p_config.accent_color * (p_config.dark_theme ? 1.15 : 3.5); + p_config.icon_pressed_color.a = 1.0; + p_config.icon_disabled_color = Color(p_config.icon_normal_color, 0.4); + + p_theme->set_color("icon_normal_color", EditorStringName(Editor), p_config.icon_normal_color); + p_theme->set_color("icon_focus_color", EditorStringName(Editor), p_config.icon_focus_color); + p_theme->set_color("icon_hover_color", EditorStringName(Editor), p_config.icon_hover_color); + p_theme->set_color("icon_pressed_color", EditorStringName(Editor), p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", EditorStringName(Editor), p_config.icon_disabled_color); + + // Additional GUI colors. + + p_config.shadow_color = Color(0, 0, 0, p_config.dark_theme ? 0.3 : 0.1); + p_config.selection_color = p_config.accent_color * Color(1, 1, 1, 0.4); + p_config.disabled_border_color = p_config.mono_color.inverted().lerp(p_config.base_color, 0.7); + p_config.disabled_bg_color = p_config.mono_color.inverted().lerp(p_config.base_color, 0.9); + p_config.separator_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.1); + + p_theme->set_color("selection_color", EditorStringName(Editor), p_config.selection_color); + p_theme->set_color("disabled_border_color", EditorStringName(Editor), p_config.disabled_border_color); + p_theme->set_color("disabled_bg_color", EditorStringName(Editor), p_config.disabled_bg_color); + p_theme->set_color("separator_color", EditorStringName(Editor), p_config.separator_color); + + // Additional editor colors. + + p_theme->set_color("box_selection_fill_color", EditorStringName(Editor), p_config.accent_color * Color(1, 1, 1, 0.3)); + p_theme->set_color("box_selection_stroke_color", EditorStringName(Editor), p_config.accent_color * Color(1, 1, 1, 0.8)); + + p_theme->set_color("axis_x_color", EditorStringName(Editor), Color(0.96, 0.20, 0.32)); + p_theme->set_color("axis_y_color", EditorStringName(Editor), Color(0.53, 0.84, 0.01)); + p_theme->set_color("axis_z_color", EditorStringName(Editor), Color(0.16, 0.55, 0.96)); + p_theme->set_color("axis_w_color", EditorStringName(Editor), Color(0.55, 0.55, 0.55)); + + const float prop_color_saturation = p_config.accent_color.get_s() * 0.75; + const float prop_color_value = p_config.accent_color.get_v(); + + p_theme->set_color("property_color_x", EditorStringName(Editor), Color().from_hsv(0.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + p_theme->set_color("property_color_y", EditorStringName(Editor), Color().from_hsv(1.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + p_theme->set_color("property_color_z", EditorStringName(Editor), Color().from_hsv(2.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + p_theme->set_color("property_color_w", EditorStringName(Editor), Color().from_hsv(1.5 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + + // Special colors for rendering methods. + + p_theme->set_color("forward_plus_color", EditorStringName(Editor), Color::hex(0x5d8c3fff)); + p_theme->set_color("mobile_color", EditorStringName(Editor), Color::hex(0xa5557dff)); + p_theme->set_color("gl_compatibility_color", EditorStringName(Editor), Color::hex(0x5586a4ff)); + + if (p_config.dark_theme) { + p_theme->set_color("highend_color", EditorStringName(Editor), Color(1.0, 0.0, 0.0)); + } else { + p_theme->set_color("highend_color", EditorStringName(Editor), Color::hex(0xad1128ff)); + } + } + + // Constants. + { + // Can't save single float in theme, so using Color. + p_theme->set_color("icon_saturation", EditorStringName(Editor), Color(p_config.icon_saturation, p_config.icon_saturation, p_config.icon_saturation)); + + // Controls may rely on the scale for their internal drawing logic. + p_theme->set_default_base_scale(EDSCALE); + p_theme->set_constant("scale", EditorStringName(Editor), EDSCALE); + + p_theme->set_constant("thumb_size", EditorStringName(Editor), p_config.thumb_size); + p_theme->set_constant("class_icon_size", EditorStringName(Editor), p_config.class_icon_size); + p_theme->set_constant("color_picker_button_height", EditorStringName(Editor), p_config.color_picker_button_height); + p_theme->set_constant("gizmo_handle_scale", EditorStringName(Editor), p_config.gizmo_handle_scale); + + p_theme->set_constant("base_margin", EditorStringName(Editor), p_config.base_margin); + p_theme->set_constant("increased_margin", EditorStringName(Editor), p_config.increased_margin); + p_theme->set_constant("window_border_margin", EditorStringName(Editor), p_config.window_border_margin); + p_theme->set_constant("top_bar_separation", EditorStringName(Editor), p_config.top_bar_separation); + + p_theme->set_constant("dark_theme", EditorStringName(Editor), p_config.dark_theme); + } + + // Styleboxes. + { + // This is the basic stylebox, used as a base for most other styleboxes (through `duplicate()`). + p_config.base_style = make_flat_stylebox(p_config.base_color, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.corner_radius); + p_config.base_style->set_border_width_all(p_config.border_width); + p_config.base_style->set_border_color(p_config.base_color); + + p_config.base_empty_style = make_empty_stylebox(p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin); + + // Button styles. + { + p_config.widget_margin = Vector2(p_config.increased_margin + 2, p_config.increased_margin + 1) * EDSCALE; + + p_config.button_style = p_config.base_style->duplicate(); + p_config.button_style->set_content_margin_individual(p_config.widget_margin.x, p_config.widget_margin.y, p_config.widget_margin.x, p_config.widget_margin.y); + p_config.button_style->set_bg_color(p_config.dark_color_1); + if (p_config.draw_extra_borders) { + p_config.button_style->set_border_width_all(Math::round(EDSCALE)); + p_config.button_style->set_border_color(p_config.extra_border_color_1); + } else { + p_config.button_style->set_border_color(p_config.dark_color_2); + } + + p_config.button_style_disabled = p_config.button_style->duplicate(); + p_config.button_style_disabled->set_bg_color(p_config.disabled_bg_color); + if (p_config.draw_extra_borders) { + p_config.button_style_disabled->set_border_color(p_config.extra_border_color_2); + } else { + p_config.button_style_disabled->set_border_color(p_config.disabled_border_color); + } + + p_config.button_style_focus = p_config.button_style->duplicate(); + p_config.button_style_focus->set_draw_center(false); + p_config.button_style_focus->set_border_width_all(Math::round(2 * MAX(1, EDSCALE))); + p_config.button_style_focus->set_border_color(p_config.accent_color); + + p_config.button_style_pressed = p_config.button_style->duplicate(); + p_config.button_style_pressed->set_bg_color(p_config.dark_color_1.darkened(0.125)); + + p_config.button_style_hover = p_config.button_style->duplicate(); + p_config.button_style_hover->set_bg_color(p_config.mono_color * Color(1, 1, 1, 0.11)); + if (p_config.draw_extra_borders) { + p_config.button_style_hover->set_border_color(p_config.extra_border_color_1); + } else { + p_config.button_style_hover->set_border_color(p_config.mono_color * Color(1, 1, 1, 0.05)); + } + } + + // Windows and popups. + { + p_config.popup_style = p_config.base_style->duplicate(); + p_config.popup_style->set_content_margin_all(p_config.popup_margin); + p_config.popup_style->set_border_color(p_config.contrast_color_1); + p_config.popup_style->set_shadow_color(p_config.shadow_color); + p_config.popup_style->set_shadow_size(4 * EDSCALE); + // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency + // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled). + p_config.popup_style->set_corner_radius_all(0); + + p_config.window_style = p_config.popup_style->duplicate(); + p_config.window_style->set_border_color(p_config.base_color); + p_config.window_style->set_border_width(SIDE_TOP, 24 * EDSCALE); + p_config.window_style->set_expand_margin(SIDE_TOP, 24 * EDSCALE); + + // Prevent corner artifacts between window title and body. + p_config.dialog_style = p_config.base_style->duplicate(); + p_config.dialog_style->set_corner_radius(CORNER_TOP_LEFT, 0); + p_config.dialog_style->set_corner_radius(CORNER_TOP_RIGHT, 0); + // Prevent visible line between window title and body. + p_config.dialog_style->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE); + } + + // Panels. + { + p_config.panel_container_style = p_config.button_style->duplicate(); + p_config.panel_container_style->set_draw_center(false); + p_config.panel_container_style->set_border_width_all(0); + + // Content panel for tabs and similar containers. + + // Compensate for the border. + const int content_panel_margin = p_config.base_margin * EDSCALE + p_config.border_width; + + p_config.content_panel_style = p_config.base_style->duplicate(); + p_config.content_panel_style->set_border_color(p_config.dark_color_3); + p_config.content_panel_style->set_border_width_all(p_config.border_width); + p_config.content_panel_style->set_border_width(Side::SIDE_TOP, 0); + p_config.content_panel_style->set_corner_radius(CORNER_TOP_LEFT, 0); + p_config.content_panel_style->set_corner_radius(CORNER_TOP_RIGHT, 0); + p_config.content_panel_style->set_content_margin_individual(content_panel_margin, 2 * EDSCALE + content_panel_margin, content_panel_margin, content_panel_margin); + + // Trees and similarly inset panels. + + p_config.tree_panel_style = p_config.base_style->duplicate(); + // Make Trees easier to distinguish from other controls by using a darker background color. + p_config.tree_panel_style->set_bg_color(p_config.dark_color_1.lerp(p_config.dark_color_2, 0.5)); + if (p_config.draw_extra_borders) { + p_config.tree_panel_style->set_border_width_all(Math::round(EDSCALE)); + p_config.tree_panel_style->set_border_color(p_config.extra_border_color_2); + } else { + p_config.tree_panel_style->set_border_color(p_config.dark_color_3); + } + } + } +} + +void EditorThemeManager::_populate_standard_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config) { + // Panels. + { + // Panel. + p_theme->set_stylebox("panel", "Panel", make_flat_stylebox(p_config.dark_color_1, 6, 4, 6, 4, p_config.corner_radius)); + + // PanelContainer. + p_theme->set_stylebox("panel", "PanelContainer", p_config.panel_container_style); + + // TooltipPanel & TooltipLabel. + { + // TooltipPanel is also used for custom tooltips, while TooltipLabel + // is only relevant for default tooltips. + + p_theme->set_color("font_color", "TooltipLabel", p_config.font_hover_color); + p_theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0)); + + Ref<StyleBoxFlat> style_tooltip = p_config.popup_style->duplicate(); + style_tooltip->set_shadow_size(0); + style_tooltip->set_content_margin_all(p_config.base_margin * EDSCALE * 0.5); + style_tooltip->set_bg_color(p_config.dark_color_3 * Color(0.8, 0.8, 0.8, 0.9)); + style_tooltip->set_border_width_all(0); + p_theme->set_stylebox("panel", "TooltipPanel", style_tooltip); + } + + // PopupPanel + p_theme->set_stylebox("panel", "PopupPanel", p_config.popup_style); + } + + // Buttons. + { + // Button. + + p_theme->set_stylebox("normal", "Button", p_config.button_style); + p_theme->set_stylebox("hover", "Button", p_config.button_style_hover); + p_theme->set_stylebox("pressed", "Button", p_config.button_style_pressed); + p_theme->set_stylebox("focus", "Button", p_config.button_style_focus); + p_theme->set_stylebox("disabled", "Button", p_config.button_style_disabled); + + p_theme->set_color("font_color", "Button", p_config.font_color); + p_theme->set_color("font_hover_color", "Button", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "Button", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "Button", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "Button", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "Button", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "Button", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "Button", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "Button", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "Button", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "Button", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "Button", p_config.icon_disabled_color); + + p_theme->set_constant("h_separation", "Button", 4 * EDSCALE); + p_theme->set_constant("outline_size", "Button", 0); + + // MenuButton. + + p_theme->set_stylebox("normal", "MenuButton", p_config.panel_container_style); + p_theme->set_stylebox("hover", "MenuButton", p_config.button_style_hover); + p_theme->set_stylebox("pressed", "MenuButton", p_config.panel_container_style); + p_theme->set_stylebox("focus", "MenuButton", p_config.panel_container_style); + p_theme->set_stylebox("disabled", "MenuButton", p_config.panel_container_style); + + p_theme->set_color("font_color", "MenuButton", p_config.font_color); + p_theme->set_color("font_hover_color", "MenuButton", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "MenuButton", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "MenuButton", p_config.font_focus_color); + p_theme->set_color("font_outline_color", "MenuButton", p_config.font_outline_color); + + p_theme->set_constant("outline_size", "MenuButton", 0); + + // MenuBar. + + p_theme->set_stylebox("normal", "MenuBar", p_config.button_style); + p_theme->set_stylebox("hover", "MenuBar", p_config.button_style_hover); + p_theme->set_stylebox("pressed", "MenuBar", p_config.button_style_pressed); + p_theme->set_stylebox("disabled", "MenuBar", p_config.button_style_disabled); + + p_theme->set_color("font_color", "MenuBar", p_config.font_color); + p_theme->set_color("font_hover_color", "MenuBar", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "MenuBar", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "MenuBar", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "MenuBar", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "MenuBar", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "MenuBar", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "MenuBar", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "MenuBar", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "MenuBar", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "MenuBar", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "MenuBar", p_config.icon_disabled_color); + + p_theme->set_constant("h_separation", "MenuBar", 4 * EDSCALE); + p_theme->set_constant("outline_size", "MenuBar", 0); + + // OptionButton. + { + Ref<StyleBoxFlat> option_button_focus_style = p_config.button_style_focus->duplicate(); + Ref<StyleBoxFlat> option_button_normal_style = p_config.button_style->duplicate(); + Ref<StyleBoxFlat> option_button_hover_style = p_config.button_style_hover->duplicate(); + Ref<StyleBoxFlat> option_button_pressed_style = p_config.button_style_pressed->duplicate(); + Ref<StyleBoxFlat> option_button_disabled_style = p_config.button_style_disabled->duplicate(); + + option_button_focus_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + option_button_normal_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + option_button_hover_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + option_button_pressed_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + option_button_disabled_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + + p_theme->set_stylebox("focus", "OptionButton", option_button_focus_style); + p_theme->set_stylebox("normal", "OptionButton", p_config.button_style); + p_theme->set_stylebox("hover", "OptionButton", p_config.button_style_hover); + p_theme->set_stylebox("pressed", "OptionButton", p_config.button_style_pressed); + p_theme->set_stylebox("disabled", "OptionButton", p_config.button_style_disabled); + + p_theme->set_stylebox("normal_mirrored", "OptionButton", option_button_normal_style); + p_theme->set_stylebox("hover_mirrored", "OptionButton", option_button_hover_style); + p_theme->set_stylebox("pressed_mirrored", "OptionButton", option_button_pressed_style); + p_theme->set_stylebox("disabled_mirrored", "OptionButton", option_button_disabled_style); + + p_theme->set_color("font_color", "OptionButton", p_config.font_color); + p_theme->set_color("font_hover_color", "OptionButton", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "OptionButton", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "OptionButton", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "OptionButton", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "OptionButton", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "OptionButton", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "OptionButton", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "OptionButton", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "OptionButton", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "OptionButton", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "OptionButton", p_config.icon_disabled_color); + + p_theme->set_icon("arrow", "OptionButton", p_theme->get_icon(SNAME("GuiOptionArrow"), EditorStringName(EditorIcons))); + p_theme->set_constant("arrow_margin", "OptionButton", p_config.widget_margin.x - 2 * EDSCALE); + p_theme->set_constant("modulate_arrow", "OptionButton", true); + p_theme->set_constant("h_separation", "OptionButton", 4 * EDSCALE); + p_theme->set_constant("outline_size", "OptionButton", 0); + } + + // CheckButton. + + p_theme->set_stylebox("normal", "CheckButton", p_config.panel_container_style); + p_theme->set_stylebox("pressed", "CheckButton", p_config.panel_container_style); + p_theme->set_stylebox("disabled", "CheckButton", p_config.panel_container_style); + p_theme->set_stylebox("hover", "CheckButton", p_config.panel_container_style); + p_theme->set_stylebox("hover_pressed", "CheckButton", p_config.panel_container_style); + + p_theme->set_icon("checked", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOn"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOff"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffDisabled"), EditorStringName(EditorIcons))); + + p_theme->set_icon("checked_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnMirrored"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffMirrored"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), EditorStringName(EditorIcons))); + + p_theme->set_color("font_color", "CheckButton", p_config.font_color); + p_theme->set_color("font_hover_color", "CheckButton", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "CheckButton", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "CheckButton", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "CheckButton", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "CheckButton", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "CheckButton", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "CheckButton", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "CheckButton", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "CheckButton", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "CheckButton", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "CheckButton", p_config.icon_disabled_color); + + p_theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE); + p_theme->set_constant("check_v_offset", "CheckButton", 0); + p_theme->set_constant("outline_size", "CheckButton", 0); + + // CheckBox. + { + Ref<StyleBoxFlat> checkbox_style = p_config.panel_container_style->duplicate(); + checkbox_style->set_content_margin_all(p_config.base_margin * EDSCALE); + + p_theme->set_stylebox("normal", "CheckBox", checkbox_style); + p_theme->set_stylebox("pressed", "CheckBox", checkbox_style); + p_theme->set_stylebox("disabled", "CheckBox", checkbox_style); + p_theme->set_stylebox("hover", "CheckBox", checkbox_style); + p_theme->set_stylebox("hover_pressed", "CheckBox", checkbox_style); + p_theme->set_icon("checked", "CheckBox", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked", "CheckBox", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_checked", "CheckBox", p_theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_unchecked", "CheckBox", p_theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_checked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_unchecked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons))); + + p_theme->set_color("font_color", "CheckBox", p_config.font_color); + p_theme->set_color("font_hover_color", "CheckBox", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "CheckBox", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "CheckBox", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "CheckBox", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "CheckBox", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "CheckBox", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "CheckBox", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "CheckBox", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "CheckBox", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "CheckBox", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "CheckBox", p_config.icon_disabled_color); + + p_theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE); + p_theme->set_constant("check_v_offset", "CheckBox", 0); + p_theme->set_constant("outline_size", "CheckBox", 0); + } + + // LinkButton. + + p_theme->set_stylebox("focus", "LinkButton", p_config.base_empty_style); + p_theme->set_color("font_color", "LinkButton", p_config.font_color); + p_theme->set_color("font_hover_color", "LinkButton", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "LinkButton", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "LinkButton", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "LinkButton", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "LinkButton", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "LinkButton", p_config.font_outline_color); + + p_theme->set_constant("outline_size", "LinkButton", 0); + } + + // Tree & ItemList. + { + Ref<StyleBoxFlat> style_tree_focus = p_config.base_style->duplicate(); + style_tree_focus->set_bg_color(p_config.highlight_color); + style_tree_focus->set_border_width_all(0); + + Ref<StyleBoxFlat> style_tree_selected = style_tree_focus->duplicate(); + + const Color guide_color = p_config.mono_color * Color(1, 1, 1, 0.05); + + // Tree. + { + p_theme->set_icon("checked", "Tree", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled", "Tree", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("indeterminate", "Tree", p_theme->get_icon(SNAME("GuiIndeterminate"), EditorStringName(EditorIcons))); + p_theme->set_icon("indeterminate_disabled", "Tree", p_theme->get_icon(SNAME("GuiIndeterminateDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked", "Tree", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled", "Tree", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("arrow", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons))); + p_theme->set_icon("arrow_collapsed", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons))); + p_theme->set_icon("arrow_collapsed_mirrored", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowLeft"), EditorStringName(EditorIcons))); + p_theme->set_icon("updown", "Tree", p_theme->get_icon(SNAME("GuiTreeUpdown"), EditorStringName(EditorIcons))); + p_theme->set_icon("select_arrow", "Tree", p_theme->get_icon(SNAME("GuiDropdown"), EditorStringName(EditorIcons))); + + p_theme->set_stylebox("panel", "Tree", p_config.tree_panel_style); + p_theme->set_stylebox("focus", "Tree", p_config.button_style_focus); + p_theme->set_stylebox("custom_button", "Tree", make_empty_stylebox()); + p_theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox()); + p_theme->set_stylebox("custom_button_hover", "Tree", p_config.button_style); + + p_theme->set_color("custom_button_font_highlight", "Tree", p_config.font_hover_color); + p_theme->set_color("font_color", "Tree", p_config.font_color); + p_theme->set_color("font_selected_color", "Tree", p_config.mono_color); + p_theme->set_color("font_disabled_color", "Tree", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "Tree", p_config.font_outline_color); + p_theme->set_color("title_button_color", "Tree", p_config.font_color); + p_theme->set_color("drop_position_color", "Tree", p_config.accent_color); + + p_theme->set_constant("v_separation", "Tree", p_config.separation_margin); + p_theme->set_constant("h_separation", "Tree", (p_config.increased_margin + 2) * EDSCALE); + p_theme->set_constant("guide_width", "Tree", p_config.border_width); + p_theme->set_constant("item_margin", "Tree", 3 * p_config.increased_margin * EDSCALE); + p_theme->set_constant("inner_item_margin_top", "Tree", p_config.separation_margin); + p_theme->set_constant("inner_item_margin_bottom", "Tree", p_config.separation_margin); + p_theme->set_constant("inner_item_margin_left", "Tree", p_config.increased_margin * EDSCALE); + p_theme->set_constant("inner_item_margin_right", "Tree", p_config.increased_margin * EDSCALE); + p_theme->set_constant("button_margin", "Tree", p_config.base_margin * EDSCALE); + p_theme->set_constant("scroll_border", "Tree", 40 * EDSCALE); + p_theme->set_constant("scroll_speed", "Tree", 12); + p_theme->set_constant("outline_size", "Tree", 0); + p_theme->set_constant("scrollbar_margin_left", "Tree", 0); + p_theme->set_constant("scrollbar_margin_top", "Tree", 0); + p_theme->set_constant("scrollbar_margin_right", "Tree", 0); + p_theme->set_constant("scrollbar_margin_bottom", "Tree", 0); + p_theme->set_constant("scrollbar_h_separation", "Tree", 1 * EDSCALE); + p_theme->set_constant("scrollbar_v_separation", "Tree", 1 * EDSCALE); + + Color relationship_line_color = p_config.mono_color * Color(1, 1, 1, p_config.relationship_line_opacity); + + p_theme->set_constant("draw_guides", "Tree", p_config.relationship_line_opacity < 0.01); + p_theme->set_color("guide_color", "Tree", guide_color); + + int relationship_line_width = 1; + Color parent_line_color = p_config.mono_color * Color(1, 1, 1, CLAMP(p_config.relationship_line_opacity + 0.45, 0.0, 1.0)); + Color children_line_color = p_config.mono_color * Color(1, 1, 1, CLAMP(p_config.relationship_line_opacity + 0.25, 0.0, 1.0)); + + p_theme->set_constant("draw_relationship_lines", "Tree", p_config.relationship_line_opacity >= 0.01); + p_theme->set_constant("relationship_line_width", "Tree", relationship_line_width); + p_theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2); + p_theme->set_constant("children_hl_line_width", "Tree", relationship_line_width); + p_theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3); + p_theme->set_color("relationship_line_color", "Tree", relationship_line_color); + p_theme->set_color("parent_hl_line_color", "Tree", parent_line_color); + p_theme->set_color("children_hl_line_color", "Tree", children_line_color); + p_theme->set_color("drop_position_color", "Tree", p_config.accent_color); + + Ref<StyleBoxFlat> style_tree_btn = p_config.base_style->duplicate(); + style_tree_btn->set_bg_color(p_config.highlight_color); + style_tree_btn->set_border_width_all(0); + p_theme->set_stylebox("button_pressed", "Tree", style_tree_btn); + + Ref<StyleBoxFlat> style_tree_hover = p_config.base_style->duplicate(); + style_tree_hover->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.4)); + style_tree_hover->set_border_width_all(0); + p_theme->set_stylebox("hover", "Tree", style_tree_hover); + + p_theme->set_stylebox("selected_focus", "Tree", style_tree_focus); + p_theme->set_stylebox("selected", "Tree", style_tree_selected); + + Ref<StyleBoxFlat> style_tree_cursor = p_config.base_style->duplicate(); + style_tree_cursor->set_draw_center(false); + style_tree_cursor->set_border_width_all(MAX(1, p_config.border_width)); + style_tree_cursor->set_border_color(p_config.contrast_color_1); + + Ref<StyleBoxFlat> style_tree_title = p_config.base_style->duplicate(); + style_tree_title->set_bg_color(p_config.dark_color_3); + style_tree_title->set_border_width_all(0); + p_theme->set_stylebox("cursor", "Tree", style_tree_cursor); + p_theme->set_stylebox("cursor_unfocused", "Tree", style_tree_cursor); + p_theme->set_stylebox("title_button_normal", "Tree", style_tree_title); + p_theme->set_stylebox("title_button_hover", "Tree", style_tree_title); + p_theme->set_stylebox("title_button_pressed", "Tree", style_tree_title); + } + + // ItemList. + { + Ref<StyleBoxFlat> style_itemlist_bg = p_config.base_style->duplicate(); + style_itemlist_bg->set_content_margin_all(p_config.separation_margin); + style_itemlist_bg->set_bg_color(p_config.dark_color_1); + + if (p_config.draw_extra_borders) { + style_itemlist_bg->set_border_width_all(Math::round(EDSCALE)); + style_itemlist_bg->set_border_color(p_config.extra_border_color_2); + } else { + style_itemlist_bg->set_border_width_all(p_config.border_width); + style_itemlist_bg->set_border_color(p_config.dark_color_3); + } + + Ref<StyleBoxFlat> style_itemlist_cursor = p_config.base_style->duplicate(); + style_itemlist_cursor->set_draw_center(false); + style_itemlist_cursor->set_border_width_all(p_config.border_width); + style_itemlist_cursor->set_border_color(p_config.highlight_color); + + Ref<StyleBoxFlat> style_itemlist_hover = style_tree_selected->duplicate(); + style_itemlist_hover->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.3)); + style_itemlist_hover->set_border_width_all(0); + + p_theme->set_stylebox("panel", "ItemList", style_itemlist_bg); + p_theme->set_stylebox("focus", "ItemList", p_config.button_style_focus); + p_theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor); + p_theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor); + p_theme->set_stylebox("selected_focus", "ItemList", style_tree_focus); + p_theme->set_stylebox("selected", "ItemList", style_tree_selected); + p_theme->set_stylebox("hovered", "ItemList", style_itemlist_hover); + p_theme->set_color("font_color", "ItemList", p_config.font_color); + p_theme->set_color("font_hovered_color", "ItemList", p_config.mono_color); + p_theme->set_color("font_selected_color", "ItemList", p_config.mono_color); + p_theme->set_color("font_outline_color", "ItemList", p_config.font_outline_color); + p_theme->set_color("guide_color", "ItemList", guide_color); + p_theme->set_constant("v_separation", "ItemList", p_config.forced_even_separation * 0.5 * EDSCALE); + p_theme->set_constant("h_separation", "ItemList", (p_config.increased_margin + 2) * EDSCALE); + p_theme->set_constant("icon_margin", "ItemList", (p_config.increased_margin + 2) * EDSCALE); + p_theme->set_constant("line_separation", "ItemList", p_config.separation_margin); + p_theme->set_constant("outline_size", "ItemList", 0); + } + } + + // TabBar & TabContainer. + { + Ref<StyleBoxFlat> style_tab_base = p_config.button_style->duplicate(); + + style_tab_base->set_border_width_all(0); + // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel. + // This also makes the top highlight look better. + style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + + // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel. + style_tab_base->set_expand_margin(SIDE_LEFT, -p_config.border_width); + + style_tab_base->set_content_margin(SIDE_LEFT, p_config.widget_margin.x + 5 * EDSCALE); + style_tab_base->set_content_margin(SIDE_RIGHT, p_config.widget_margin.x + 5 * EDSCALE); + style_tab_base->set_content_margin(SIDE_BOTTOM, p_config.widget_margin.y); + style_tab_base->set_content_margin(SIDE_TOP, p_config.widget_margin.y); + + Ref<StyleBoxFlat> style_tab_selected = style_tab_base->duplicate(); + + style_tab_selected->set_bg_color(p_config.base_color); + // Add a highlight line at the top of the selected tab. + style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE)); + // Make the highlight line prominent, but not too prominent as to not be distracting. + Color tab_highlight = p_config.dark_color_2.lerp(p_config.accent_color, 0.75); + style_tab_selected->set_border_color(tab_highlight); + style_tab_selected->set_corner_radius_all(0); + + Ref<StyleBoxFlat> style_tab_hovered = style_tab_base->duplicate(); + + style_tab_hovered->set_bg_color(p_config.dark_color_1.lerp(p_config.base_color, 0.4)); + // Hovered tab has a subtle highlight between normal and selected states. + style_tab_hovered->set_corner_radius_all(0); + + Ref<StyleBoxFlat> style_tab_unselected = style_tab_base->duplicate(); + style_tab_unselected->set_expand_margin(SIDE_BOTTOM, 0); + style_tab_unselected->set_bg_color(p_config.dark_color_1); + // Add some spacing between unselected tabs to make them easier to distinguish from each other + style_tab_unselected->set_border_color(Color(0, 0, 0, 0)); + + Ref<StyleBoxFlat> style_tab_disabled = style_tab_base->duplicate(); + style_tab_disabled->set_expand_margin(SIDE_BOTTOM, 0); + style_tab_disabled->set_bg_color(p_config.disabled_bg_color); + style_tab_disabled->set_border_color(p_config.disabled_bg_color); + + Ref<StyleBoxFlat> style_tab_focus = p_config.button_style_focus->duplicate(); + + Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(p_config.dark_color_1, 0, 0, 0, 0, p_config.corner_radius * EDSCALE); + style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + p_theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background); + p_theme->set_stylebox("panel", "TabContainer", p_config.content_panel_style); + + p_theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected); + p_theme->set_stylebox("tab_hovered", "TabContainer", style_tab_hovered); + p_theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected); + p_theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled); + p_theme->set_stylebox("tab_focus", "TabContainer", style_tab_focus); + p_theme->set_stylebox("tab_selected", "TabBar", style_tab_selected); + p_theme->set_stylebox("tab_hovered", "TabBar", style_tab_hovered); + p_theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected); + p_theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled); + p_theme->set_stylebox("tab_focus", "TabBar", style_tab_focus); + p_theme->set_stylebox("button_pressed", "TabBar", p_config.panel_container_style); + p_theme->set_stylebox("button_highlight", "TabBar", p_config.panel_container_style); + + p_theme->set_color("font_selected_color", "TabContainer", p_config.font_color); + p_theme->set_color("font_hovered_color", "TabContainer", p_config.font_color); + p_theme->set_color("font_unselected_color", "TabContainer", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "TabContainer", p_config.font_outline_color); + p_theme->set_color("font_selected_color", "TabBar", p_config.font_color); + p_theme->set_color("font_hovered_color", "TabBar", p_config.font_color); + p_theme->set_color("font_unselected_color", "TabBar", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "TabBar", p_config.font_outline_color); + p_theme->set_color("drop_mark_color", "TabContainer", tab_highlight); + p_theme->set_color("drop_mark_color", "TabBar", tab_highlight); + + p_theme->set_icon("menu", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons))); + p_theme->set_icon("menu_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("close", "TabBar", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); + p_theme->set_icon("increment", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons))); + p_theme->set_icon("decrement", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons))); + p_theme->set_icon("increment", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons))); + p_theme->set_icon("decrement", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons))); + p_theme->set_icon("increment_highlight", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("decrement_highlight", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("increment_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("decrement_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("drop_mark", "TabContainer", p_theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons))); + p_theme->set_icon("drop_mark", "TabBar", p_theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons))); + + p_theme->set_constant("side_margin", "TabContainer", 0); + p_theme->set_constant("outline_size", "TabContainer", 0); + p_theme->set_constant("h_separation", "TabBar", 4 * EDSCALE); + p_theme->set_constant("outline_size", "TabBar", 0); + } + + // Separators. + p_theme->set_stylebox("separator", "HSeparator", make_line_stylebox(p_config.separator_color, MAX(Math::round(EDSCALE), p_config.border_width))); + p_theme->set_stylebox("separator", "VSeparator", make_line_stylebox(p_config.separator_color, MAX(Math::round(EDSCALE), p_config.border_width), 0, 0, true)); + + // LineEdit & TextEdit. + { + Ref<StyleBoxFlat> text_editor_style = p_config.button_style->duplicate(); + // The original button_style style has an extra 1 pixel offset that makes LineEdits not align with Buttons, + // so this compensates for that. + text_editor_style->set_content_margin(SIDE_TOP, text_editor_style->get_content_margin(SIDE_TOP) - 1 * EDSCALE); + + // Don't round the bottom corners to make the line look sharper. + text_editor_style->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + text_editor_style->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + + if (p_config.draw_extra_borders) { + text_editor_style->set_border_width_all(Math::round(EDSCALE)); + text_editor_style->set_border_color(p_config.extra_border_color_1); + } else { + // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors + // such as the Project Settings. + text_editor_style->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); + text_editor_style->set_border_color(p_config.dark_color_2); + } + + Ref<StyleBoxFlat> text_editor_disabled_style = text_editor_style->duplicate(); + text_editor_disabled_style->set_border_color(p_config.disabled_border_color); + text_editor_disabled_style->set_bg_color(p_config.disabled_bg_color); + + // LineEdit. + + p_theme->set_stylebox("normal", "LineEdit", text_editor_style); + p_theme->set_stylebox("focus", "LineEdit", p_config.button_style_focus); + p_theme->set_stylebox("read_only", "LineEdit", text_editor_disabled_style); + + p_theme->set_icon("clear", "LineEdit", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); + + p_theme->set_color("font_color", "LineEdit", p_config.font_color); + p_theme->set_color("font_selected_color", "LineEdit", p_config.mono_color); + p_theme->set_color("font_uneditable_color", "LineEdit", p_config.font_readonly_color); + p_theme->set_color("font_placeholder_color", "LineEdit", p_config.font_placeholder_color); + p_theme->set_color("font_outline_color", "LineEdit", p_config.font_outline_color); + p_theme->set_color("caret_color", "LineEdit", p_config.font_color); + p_theme->set_color("selection_color", "LineEdit", p_config.selection_color); + p_theme->set_color("clear_button_color", "LineEdit", p_config.font_color); + p_theme->set_color("clear_button_color_pressed", "LineEdit", p_config.accent_color); + + p_theme->set_constant("minimum_character_width", "LineEdit", 4); + p_theme->set_constant("outline_size", "LineEdit", 0); + p_theme->set_constant("caret_width", "LineEdit", 1); + + // TextEdit. + + p_theme->set_stylebox("normal", "TextEdit", text_editor_style); + p_theme->set_stylebox("focus", "TextEdit", p_config.button_style_focus); + p_theme->set_stylebox("read_only", "TextEdit", text_editor_disabled_style); + + p_theme->set_icon("tab", "TextEdit", p_theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons))); + p_theme->set_icon("space", "TextEdit", p_theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons))); + + p_theme->set_color("font_color", "TextEdit", p_config.font_color); + p_theme->set_color("font_readonly_color", "TextEdit", p_config.font_readonly_color); + p_theme->set_color("font_placeholder_color", "TextEdit", p_config.font_placeholder_color); + p_theme->set_color("font_outline_color", "TextEdit", p_config.font_outline_color); + p_theme->set_color("caret_color", "TextEdit", p_config.font_color); + p_theme->set_color("selection_color", "TextEdit", p_config.selection_color); + p_theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); + + p_theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE); + p_theme->set_constant("outline_size", "TextEdit", 0); + p_theme->set_constant("caret_width", "TextEdit", 1); + } + + // Containers. + { + p_theme->set_constant("separation", "BoxContainer", p_config.separation_margin); + p_theme->set_constant("separation", "HBoxContainer", p_config.separation_margin); + p_theme->set_constant("separation", "VBoxContainer", p_config.separation_margin); + p_theme->set_constant("margin_left", "MarginContainer", 0); + p_theme->set_constant("margin_top", "MarginContainer", 0); + p_theme->set_constant("margin_right", "MarginContainer", 0); + p_theme->set_constant("margin_bottom", "MarginContainer", 0); + p_theme->set_constant("h_separation", "GridContainer", p_config.separation_margin); + p_theme->set_constant("v_separation", "GridContainer", p_config.separation_margin); + p_theme->set_constant("h_separation", "FlowContainer", p_config.separation_margin); + p_theme->set_constant("v_separation", "FlowContainer", p_config.separation_margin); + p_theme->set_constant("h_separation", "HFlowContainer", p_config.separation_margin); + p_theme->set_constant("v_separation", "HFlowContainer", p_config.separation_margin); + p_theme->set_constant("h_separation", "VFlowContainer", p_config.separation_margin); + p_theme->set_constant("v_separation", "VFlowContainer", p_config.separation_margin); + + // SplitContainer. + + p_theme->set_icon("h_grabber", "SplitContainer", p_theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons))); + p_theme->set_icon("v_grabber", "SplitContainer", p_theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons))); + p_theme->set_icon("grabber", "VSplitContainer", p_theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons))); + p_theme->set_icon("grabber", "HSplitContainer", p_theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons))); + + p_theme->set_constant("separation", "SplitContainer", p_config.separation_margin); + p_theme->set_constant("separation", "HSplitContainer", p_config.separation_margin); + p_theme->set_constant("separation", "VSplitContainer", p_config.separation_margin); + + p_theme->set_constant("minimum_grab_thickness", "SplitContainer", p_config.increased_margin * EDSCALE); + p_theme->set_constant("minimum_grab_thickness", "HSplitContainer", p_config.increased_margin * EDSCALE); + p_theme->set_constant("minimum_grab_thickness", "VSplitContainer", p_config.increased_margin * EDSCALE); + + // GridContainer. + p_theme->set_constant("v_separation", "GridContainer", Math::round(p_config.widget_margin.y - 2 * EDSCALE)); + } + + // Window and dialogs. + { + // Window. + + p_theme->set_stylebox("embedded_border", "Window", p_config.window_style); + p_theme->set_stylebox("embedded_unfocused_border", "Window", p_config.window_style); + + p_theme->set_color("title_color", "Window", p_config.font_color); + p_theme->set_icon("close", "Window", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); + p_theme->set_icon("close_pressed", "Window", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); + p_theme->set_constant("close_h_offset", "Window", 22 * EDSCALE); + p_theme->set_constant("close_v_offset", "Window", 20 * EDSCALE); + p_theme->set_constant("title_height", "Window", 24 * EDSCALE); + p_theme->set_constant("resize_margin", "Window", 4 * EDSCALE); + p_theme->set_font("title_font", "Window", p_theme->get_font(SNAME("title"), EditorStringName(EditorFonts))); + p_theme->set_font_size("title_font_size", "Window", p_theme->get_font_size(SNAME("title_size"), EditorStringName(EditorFonts))); + + // AcceptDialog. + p_theme->set_stylebox("panel", "AcceptDialog", p_config.dialog_style); + p_theme->set_constant("buttons_separation", "AcceptDialog", 8 * EDSCALE); + + // FileDialog. + p_theme->set_icon("folder", "FileDialog", p_theme->get_icon(SNAME("Folder"), EditorStringName(EditorIcons))); + p_theme->set_icon("parent_folder", "FileDialog", p_theme->get_icon(SNAME("ArrowUp"), EditorStringName(EditorIcons))); + p_theme->set_icon("back_folder", "FileDialog", p_theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons))); + p_theme->set_icon("forward_folder", "FileDialog", p_theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons))); + p_theme->set_icon("reload", "FileDialog", p_theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); + p_theme->set_icon("toggle_hidden", "FileDialog", p_theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons))); + // Use a different color for folder icons to make them easier to distinguish from files. + // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color. + p_theme->set_color("folder_icon_color", "FileDialog", (p_config.dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(p_config.accent_color, 0.7)); + p_theme->set_color("files_disabled", "FileDialog", p_config.font_disabled_color); + + // PopupDialog. + p_theme->set_stylebox("panel", "PopupDialog", p_config.popup_style); + + // PopupMenu. + { + Ref<StyleBoxFlat> style_popup_menu = p_config.popup_style->duplicate(); + // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn + // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted, + // and it looks weird. 1px solves this. + style_popup_menu->set_content_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE); + // Always display a border for PopupMenus so they can be distinguished from their background. + style_popup_menu->set_border_width_all(EDSCALE); + if (p_config.draw_extra_borders) { + style_popup_menu->set_border_color(p_config.extra_border_color_2); + } else { + style_popup_menu->set_border_color(p_config.dark_color_2); + } + p_theme->set_stylebox("panel", "PopupMenu", style_popup_menu); + + Ref<StyleBoxFlat> style_menu_hover = p_config.button_style_hover->duplicate(); + // Don't use rounded corners for hover highlights since the StyleBox touches the PopupMenu's edges. + style_menu_hover->set_corner_radius_all(0); + p_theme->set_stylebox("hover", "PopupMenu", style_menu_hover); + + Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine)); + style_popup_separator->set_color(p_config.separator_color); + style_popup_separator->set_grow_begin(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_separator->set_grow_end(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); + + Ref<StyleBoxLine> style_popup_labeled_separator_left(memnew(StyleBoxLine)); + style_popup_labeled_separator_left->set_grow_begin(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_labeled_separator_left->set_color(p_config.separator_color); + style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); + + Ref<StyleBoxLine> style_popup_labeled_separator_right(memnew(StyleBoxLine)); + style_popup_labeled_separator_right->set_grow_end(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_labeled_separator_right->set_color(p_config.separator_color); + style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); + + p_theme->set_stylebox("separator", "PopupMenu", style_popup_separator); + p_theme->set_stylebox("labeled_separator_left", "PopupMenu", style_popup_labeled_separator_left); + p_theme->set_stylebox("labeled_separator_right", "PopupMenu", style_popup_labeled_separator_right); + + p_theme->set_color("font_color", "PopupMenu", p_config.font_color); + p_theme->set_color("font_hover_color", "PopupMenu", p_config.font_hover_color); + p_theme->set_color("font_accelerator_color", "PopupMenu", p_config.font_disabled_color); + p_theme->set_color("font_disabled_color", "PopupMenu", p_config.font_disabled_color); + p_theme->set_color("font_separator_color", "PopupMenu", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "PopupMenu", p_config.font_outline_color); + + p_theme->set_icon("checked", "PopupMenu", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked", "PopupMenu", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_checked", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_unchecked", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_checked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_unchecked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("submenu", "PopupMenu", p_theme->get_icon(SNAME("ArrowRight"), EditorStringName(EditorIcons))); + p_theme->set_icon("submenu_mirrored", "PopupMenu", p_theme->get_icon(SNAME("ArrowLeft"), EditorStringName(EditorIcons))); + p_theme->set_icon("visibility_hidden", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityHidden"), EditorStringName(EditorIcons))); + p_theme->set_icon("visibility_visible", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons))); + p_theme->set_icon("visibility_xray", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityXray"), EditorStringName(EditorIcons))); + + p_theme->set_constant("v_separation", "PopupMenu", p_config.forced_even_separation * EDSCALE); + p_theme->set_constant("outline_size", "PopupMenu", 0); + p_theme->set_constant("item_start_padding", "PopupMenu", p_config.separation_margin); + p_theme->set_constant("item_end_padding", "PopupMenu", p_config.separation_margin); + } + } + + // Sliders and scrollbars. + { + Ref<Texture2D> empty_icon = memnew(ImageTexture); + + // HScrollBar. + + if (p_config.increase_scrollbar_touch_area) { + p_theme->set_stylebox("scroll", "HScrollBar", make_line_stylebox(p_config.separator_color, 50)); + } else { + p_theme->set_stylebox("scroll", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, -5, 1, -5, 1)); + } + p_theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); + + p_theme->set_icon("increment", "HScrollBar", empty_icon); + p_theme->set_icon("increment_highlight", "HScrollBar", empty_icon); + p_theme->set_icon("increment_pressed", "HScrollBar", empty_icon); + p_theme->set_icon("decrement", "HScrollBar", empty_icon); + p_theme->set_icon("decrement_highlight", "HScrollBar", empty_icon); + p_theme->set_icon("decrement_pressed", "HScrollBar", empty_icon); + + // VScrollBar. + + if (p_config.increase_scrollbar_touch_area) { + p_theme->set_stylebox("scroll", "VScrollBar", make_line_stylebox(p_config.separator_color, 50, 1, 1, true)); + } else { + p_theme->set_stylebox("scroll", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, -5, 1, -5)); + } + p_theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); + + p_theme->set_icon("increment", "VScrollBar", empty_icon); + p_theme->set_icon("increment_highlight", "VScrollBar", empty_icon); + p_theme->set_icon("increment_pressed", "VScrollBar", empty_icon); + p_theme->set_icon("decrement", "VScrollBar", empty_icon); + p_theme->set_icon("decrement_highlight", "VScrollBar", empty_icon); + p_theme->set_icon("decrement_pressed", "VScrollBar", empty_icon); + + // HSlider. + p_theme->set_icon("grabber_highlight", "HSlider", p_theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("grabber", "HSlider", p_theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons))); + p_theme->set_stylebox("slider", "HSlider", make_flat_stylebox(p_config.dark_color_3, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2, p_config.corner_radius)); + p_theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(p_config.contrast_color_1, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2, p_config.corner_radius)); + p_theme->set_stylebox("grabber_area_highlight", "HSlider", make_flat_stylebox(p_config.contrast_color_1, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2)); + p_theme->set_constant("center_grabber", "HSlider", 0); + p_theme->set_constant("grabber_offset", "HSlider", 0); + + // VSlider. + p_theme->set_icon("grabber", "VSlider", p_theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons))); + p_theme->set_icon("grabber_highlight", "VSlider", p_theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons))); + p_theme->set_stylebox("slider", "VSlider", make_flat_stylebox(p_config.dark_color_3, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0, p_config.corner_radius)); + p_theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(p_config.contrast_color_1, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0, p_config.corner_radius)); + p_theme->set_stylebox("grabber_area_highlight", "VSlider", make_flat_stylebox(p_config.contrast_color_1, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0)); + p_theme->set_constant("center_grabber", "VSlider", 0); + p_theme->set_constant("grabber_offset", "VSlider", 0); + } + + // Labels. + { + // RichTextLabel. + + p_theme->set_stylebox("normal", "RichTextLabel", p_config.tree_panel_style); + p_theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox()); + + p_theme->set_color("default_color", "RichTextLabel", p_config.font_color); + p_theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0)); + p_theme->set_color("font_outline_color", "RichTextLabel", p_config.font_outline_color); + p_theme->set_color("selection_color", "RichTextLabel", p_config.selection_color); + + p_theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE); + p_theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE); + p_theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE); + p_theme->set_constant("outline_size", "RichTextLabel", 0); + + // Label. + + p_theme->set_stylebox("normal", "Label", p_config.base_empty_style); + + p_theme->set_color("font_color", "Label", p_config.font_color); + p_theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0)); + p_theme->set_color("font_outline_color", "Label", p_config.font_outline_color); + + p_theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE); + p_theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE); + p_theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE); + p_theme->set_constant("line_spacing", "Label", 3 * EDSCALE); + p_theme->set_constant("outline_size", "Label", 0); + } + + // SpinBox. + p_theme->set_icon("updown", "SpinBox", p_theme->get_icon(SNAME("GuiSpinboxUpdown"), EditorStringName(EditorIcons))); + p_theme->set_icon("updown_disabled", "SpinBox", p_theme->get_icon(SNAME("GuiSpinboxUpdownDisabled"), EditorStringName(EditorIcons))); + + // ProgressBar. + p_theme->set_stylebox("background", "ProgressBar", make_stylebox(p_theme->get_icon(SNAME("GuiProgressBar"), EditorStringName(EditorIcons)), 4, 4, 4, 4, 0, 0, 0, 0)); + p_theme->set_stylebox("fill", "ProgressBar", make_stylebox(p_theme->get_icon(SNAME("GuiProgressFill"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 2, 1, 2, 1)); + p_theme->set_color("font_color", "ProgressBar", p_config.font_color); + p_theme->set_color("font_outline_color", "ProgressBar", p_config.font_outline_color); + p_theme->set_constant("outline_size", "ProgressBar", 0); + + // GraphEdit and related nodes. + { + // GraphEdit. + + p_theme->set_stylebox("panel", "GraphEdit", p_config.tree_panel_style); + p_theme->set_stylebox("menu_panel", "GraphEdit", make_flat_stylebox(p_config.dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3)); + + if (p_config.dark_theme) { + p_theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1)); + p_theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05)); + } else { + p_theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15)); + p_theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07)); + } + p_theme->set_color("selection_fill", "GraphEdit", p_theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor))); + p_theme->set_color("selection_stroke", "GraphEdit", p_theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor))); + p_theme->set_color("activity", "GraphEdit", p_config.accent_color); + + p_theme->set_icon("zoom_out", "GraphEdit", p_theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons))); + p_theme->set_icon("zoom_in", "GraphEdit", p_theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons))); + p_theme->set_icon("zoom_reset", "GraphEdit", p_theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons))); + p_theme->set_icon("grid_toggle", "GraphEdit", p_theme->get_icon(SNAME("GridToggle"), EditorStringName(EditorIcons))); + p_theme->set_icon("minimap_toggle", "GraphEdit", p_theme->get_icon(SNAME("GridMinimap"), EditorStringName(EditorIcons))); + p_theme->set_icon("snapping_toggle", "GraphEdit", p_theme->get_icon(SNAME("SnapGrid"), EditorStringName(EditorIcons))); + p_theme->set_icon("layout", "GraphEdit", p_theme->get_icon(SNAME("GridLayout"), EditorStringName(EditorIcons))); + + // GraphEditMinimap. + { + Ref<StyleBoxFlat> style_minimap_bg = make_flat_stylebox(p_config.dark_color_1, 0, 0, 0, 0); + style_minimap_bg->set_border_color(p_config.dark_color_3); + style_minimap_bg->set_border_width_all(1); + p_theme->set_stylebox("panel", "GraphEditMinimap", style_minimap_bg); + + Ref<StyleBoxFlat> style_minimap_camera; + Ref<StyleBoxFlat> style_minimap_node; + if (p_config.dark_theme) { + style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0); + style_minimap_camera->set_border_color(Color(0.65, 0.65, 0.65, 0.45)); + style_minimap_node = make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0); + } else { + style_minimap_camera = make_flat_stylebox(Color(0.38, 0.38, 0.38, 0.2), 0, 0, 0, 0); + style_minimap_camera->set_border_color(Color(0.38, 0.38, 0.38, 0.45)); + style_minimap_node = make_flat_stylebox(Color(0, 0, 0), 0, 0, 0, 0); + } + style_minimap_camera->set_border_width_all(1); + style_minimap_node->set_anti_aliased(false); + p_theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera); + p_theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node); + + const Color minimap_resizer_color = p_config.dark_theme ? Color(1, 1, 1, 0.65) : Color(0, 0, 0, 0.65); + p_theme->set_icon("resizer", "GraphEditMinimap", p_theme->get_icon(SNAME("GuiResizerTopLeft"), EditorStringName(EditorIcons))); + p_theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color); + } + + // GraphElement & GraphNode. + { + const int gn_margin_top = 2; + const int gn_margin_side = 2; + const int gn_margin_bottom = 2; + + const Color gn_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09); + const Color gn_selected_border_color = gn_bg_color.lerp(p_config.accent_color, 0.275); + const Color gn_frame_bg = gn_bg_color.lerp(p_config.tree_panel_style->get_bg_color(), 0.3); + + Ref<StyleBoxFlat> gn_panel_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius); + gn_panel_style->set_border_width_all(p_config.border_width); + gn_panel_style->set_border_color(gn_bg_color); + gn_panel_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE); + gn_panel_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE); + + Ref<StyleBoxFlat> gn_panel_selected_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius); + gn_panel_selected_style->set_border_width_all(2 * EDSCALE + p_config.border_width); + gn_panel_selected_style->set_border_color(gn_selected_border_color); + gn_panel_selected_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE); + gn_panel_selected_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE); + + const int gn_titlebar_margin_left = 12; + const int gn_titlebar_margin_right = 4; // The rest is for the close button. + + Ref<StyleBoxFlat> gn_titlebar_style = make_flat_stylebox(gn_bg_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius); + gn_titlebar_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE); + gn_titlebar_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0); + + Ref<StyleBoxFlat> gn_titlebar_selected_style = make_flat_stylebox(gn_selected_border_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius); + gn_titlebar_selected_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0); + gn_titlebar_selected_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE); + + Color gn_decoration_color = p_config.dark_color_1.inverted(); + + // GraphElement. + + p_theme->set_stylebox("panel", "GraphElement", gn_panel_style); + p_theme->set_stylebox("panel_selected", "GraphElement", gn_panel_selected_style); + p_theme->set_stylebox("titlebar", "GraphElement", gn_titlebar_style); + p_theme->set_stylebox("titlebar_selected", "GraphElement", gn_titlebar_selected_style); + + p_theme->set_color("resizer_color", "GraphElement", gn_decoration_color); + p_theme->set_icon("resizer", "GraphElement", p_theme->get_icon(SNAME("GuiResizer"), EditorStringName(EditorIcons))); + + // GraphNode. + + Ref<StyleBoxEmpty> gn_slot_style = make_empty_stylebox(12, 0, 12, 0); + + p_theme->set_stylebox("panel", "GraphNode", gn_panel_style); + p_theme->set_stylebox("panel_selected", "GraphNode", gn_panel_selected_style); + p_theme->set_stylebox("titlebar", "GraphNode", gn_titlebar_style); + p_theme->set_stylebox("titlebar_selected", "GraphNode", gn_titlebar_selected_style); + p_theme->set_stylebox("slot", "GraphNode", gn_slot_style); + + p_theme->set_color("resizer_color", "GraphNode", gn_decoration_color); + + p_theme->set_constant("port_h_offset", "GraphNode", 0); + p_theme->set_constant("separation", "GraphNode", 1 * EDSCALE); + + Ref<ImageTexture> port_icon = p_theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons)); + // The true size is 24x24 This is necessary for sharp port icons at high zoom levels in GraphEdit (up to ~200%). + port_icon->set_size_override(Size2(12, 12)); + p_theme->set_icon("port", "GraphNode", port_icon); + + // GraphNode's title Label. + p_theme->set_type_variation("GraphNodeTitleLabel", "Label"); + p_theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0)); + p_theme->set_color("font_color", "GraphNodeTitleLabel", p_config.font_color); + p_theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE); + } + } + + // ColorPicker and related nodes. + { + // ColorPicker. + + p_theme->set_constant("margin", "ColorPicker", p_config.base_margin); + p_theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE); + p_theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE); + p_theme->set_constant("h_width", "ColorPicker", 30 * EDSCALE); + p_theme->set_constant("label_width", "ColorPicker", 10 * EDSCALE); + p_theme->set_constant("center_slider_grabbers", "ColorPicker", 1); + + p_theme->set_icon("screen_picker", "ColorPicker", p_theme->get_icon(SNAME("ColorPick"), EditorStringName(EditorIcons))); + p_theme->set_icon("shape_circle", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeCircle"), EditorStringName(EditorIcons))); + p_theme->set_icon("shape_rect", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeRectangle"), EditorStringName(EditorIcons))); + p_theme->set_icon("shape_rect_wheel", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeRectangleWheel"), EditorStringName(EditorIcons))); + p_theme->set_icon("add_preset", "ColorPicker", p_theme->get_icon(SNAME("Add"), EditorStringName(EditorIcons))); + p_theme->set_icon("sample_bg", "ColorPicker", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); + p_theme->set_icon("sample_revert", "ColorPicker", p_theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); + p_theme->set_icon("overbright_indicator", "ColorPicker", p_theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons))); + p_theme->set_icon("bar_arrow", "ColorPicker", p_theme->get_icon(SNAME("ColorPickerBarArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("picker_cursor", "ColorPicker", p_theme->get_icon(SNAME("PickerCursor"), EditorStringName(EditorIcons))); + + // ColorPickerButton. + p_theme->set_icon("bg", "ColorPickerButton", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); + + // ColorPresetButton. + p_theme->set_stylebox("preset_fg", "ColorPresetButton", make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2, 2)); + p_theme->set_icon("preset_bg", "ColorPresetButton", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); + p_theme->set_icon("overbright_indicator", "ColorPresetButton", p_theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons))); + } +} + +void EditorThemeManager::_populate_editor_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config) { + // Project manager. + { + p_theme->set_stylebox("search_panel", "ProjectManager", p_config.tree_panel_style); + p_theme->set_constant("sidebar_button_icon_separation", "ProjectManager", int(6 * EDSCALE)); + + // ProjectTag. + { + p_theme->set_type_variation("ProjectTag", "Button"); + + Ref<StyleBoxFlat> tag = p_config.button_style->duplicate(); + tag->set_bg_color(p_config.dark_theme ? tag->get_bg_color().lightened(0.2) : tag->get_bg_color().darkened(0.2)); + tag->set_corner_radius(CORNER_TOP_LEFT, 0); + tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + tag->set_corner_radius(CORNER_TOP_RIGHT, 4); + tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); + p_theme->set_stylebox("normal", "ProjectTag", tag); + + tag = p_config.button_style_hover->duplicate(); + tag->set_corner_radius(CORNER_TOP_LEFT, 0); + tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + tag->set_corner_radius(CORNER_TOP_RIGHT, 4); + tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); + p_theme->set_stylebox("hover", "ProjectTag", tag); + + tag = p_config.button_style_pressed->duplicate(); + tag->set_corner_radius(CORNER_TOP_LEFT, 0); + tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + tag->set_corner_radius(CORNER_TOP_RIGHT, 4); + tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); + p_theme->set_stylebox("pressed", "ProjectTag", tag); + } + } + + // Editor and main screen. + { + // Editor background. + Color background_color_opaque = p_config.dark_color_2; + background_color_opaque.a = 1.0; + p_theme->set_color("background", EditorStringName(Editor), background_color_opaque); + p_theme->set_stylebox("Background", EditorStringName(EditorStyles), make_flat_stylebox(background_color_opaque, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin)); + + p_theme->set_stylebox("PanelForeground", EditorStringName(EditorStyles), p_config.base_style); + + // Editor focus. + p_theme->set_stylebox("Focus", EditorStringName(EditorStyles), p_config.button_style_focus); + // Use a less opaque color to be less distracting for the 2D and 3D editor viewports. + Ref<StyleBoxFlat> style_widget_focus_viewport = p_config.button_style_focus->duplicate(); + style_widget_focus_viewport->set_border_color(p_config.accent_color * Color(1, 1, 1, 0.5)); + p_theme->set_stylebox("FocusViewport", EditorStringName(EditorStyles), style_widget_focus_viewport); + + // This stylebox is used in 3d and 2d viewports (no borders). + Ref<StyleBoxFlat> style_content_panel_vp = p_config.content_panel_style->duplicate(); + style_content_panel_vp->set_content_margin_individual(p_config.border_width * 2, p_config.base_margin * EDSCALE, p_config.border_width * 2, p_config.border_width * 2); + p_theme->set_stylebox("Content", EditorStringName(EditorStyles), style_content_panel_vp); + + // 2D/CanvasItem editor + Ref<StyleBoxFlat> style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2)); + style_canvas_editor_info->set_expand_margin_all(4 * EDSCALE); + p_theme->set_stylebox("CanvasItemInfoOverlay", EditorStringName(EditorStyles), style_canvas_editor_info); + + // 3D/Spatial editor. + Ref<StyleBoxFlat> style_info_3d_viewport = p_config.base_style->duplicate(); + style_info_3d_viewport->set_bg_color(style_info_3d_viewport->get_bg_color() * Color(1, 1, 1, 0.5)); + style_info_3d_viewport->set_border_width_all(0); + p_theme->set_stylebox("Information3dViewport", EditorStringName(EditorStyles), style_info_3d_viewport); + + // 2D and 3D contextual toolbar. + // Use a custom stylebox to make contextual menu items stand out from the rest. + // This helps with editor usability as contextual menu items change when selecting nodes, + // even though it may not be immediately obvious at first. + Ref<StyleBoxFlat> toolbar_stylebox = memnew(StyleBoxFlat); + toolbar_stylebox->set_bg_color(p_config.accent_color * Color(1, 1, 1, 0.1)); + toolbar_stylebox->set_anti_aliased(false); + // Add an underline to the StyleBox, but prevent its minimum vertical size from changing. + toolbar_stylebox->set_border_color(p_config.accent_color); + toolbar_stylebox->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); + toolbar_stylebox->set_content_margin(SIDE_BOTTOM, 0); + toolbar_stylebox->set_expand_margin_individual(4 * EDSCALE, 2 * EDSCALE, 4 * EDSCALE, 4 * EDSCALE); + p_theme->set_stylebox("ContextualToolbar", EditorStringName(EditorStyles), toolbar_stylebox); + + // Script editor. + p_theme->set_stylebox("ScriptEditorPanel", EditorStringName(EditorStyles), make_empty_stylebox(p_config.base_margin, 0, p_config.base_margin, p_config.base_margin)); + p_theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + p_theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + + // Bottom panel. + Ref<StyleBoxFlat> style_bottom_panel = p_config.content_panel_style->duplicate(); + style_bottom_panel->set_corner_radius_all(p_config.corner_radius * EDSCALE); + p_theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel); + + // Main menu. + p_theme->set_stylebox("MenuHover", EditorStringName(EditorStyles), p_config.button_style_hover); + } + + // Editor GUI widgets. + { + // EditorSpinSlider. + p_theme->set_color("label_color", "EditorSpinSlider", p_config.font_color); + p_theme->set_color("read_only_label_color", "EditorSpinSlider", p_config.font_readonly_color); + + Ref<StyleBoxFlat> editor_spin_label_bg = p_config.base_style->duplicate(); + editor_spin_label_bg->set_bg_color(p_config.dark_color_3); + editor_spin_label_bg->set_border_width_all(0); + p_theme->set_stylebox("label_bg", "EditorSpinSlider", editor_spin_label_bg); + + // Launch Pad and Play buttons + Ref<StyleBoxFlat> style_launch_pad = make_flat_stylebox(p_config.dark_color_1, 2 * EDSCALE, 0, 2 * EDSCALE, 0, p_config.corner_radius); + style_launch_pad->set_corner_radius_all(p_config.corner_radius * EDSCALE); + p_theme->set_stylebox("LaunchPadNormal", EditorStringName(EditorStyles), style_launch_pad); + Ref<StyleBoxFlat> style_launch_pad_movie = style_launch_pad->duplicate(); + style_launch_pad_movie->set_bg_color(p_config.accent_color * Color(1, 1, 1, 0.1)); + style_launch_pad_movie->set_border_color(p_config.accent_color); + style_launch_pad_movie->set_border_width_all(Math::round(2 * EDSCALE)); + p_theme->set_stylebox("LaunchPadMovieMode", EditorStringName(EditorStyles), style_launch_pad_movie); + + p_theme->set_stylebox("MovieWriterButtonNormal", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + Ref<StyleBoxFlat> style_write_movie_button = p_config.button_style_pressed->duplicate(); + style_write_movie_button->set_bg_color(p_config.accent_color); + style_write_movie_button->set_corner_radius_all(p_config.corner_radius * EDSCALE); + style_write_movie_button->set_content_margin(SIDE_TOP, 0); + style_write_movie_button->set_content_margin(SIDE_BOTTOM, 0); + style_write_movie_button->set_content_margin(SIDE_LEFT, 0); + style_write_movie_button->set_content_margin(SIDE_RIGHT, 0); + style_write_movie_button->set_expand_margin(SIDE_RIGHT, 2 * EDSCALE); + p_theme->set_stylebox("MovieWriterButtonPressed", EditorStringName(EditorStyles), style_write_movie_button); + } + + // Standard GUI variations. + { + // Custom theme type for MarginContainer with 4px margins. + p_theme->set_type_variation("MarginContainer4px", "MarginContainer"); + p_theme->set_constant("margin_left", "MarginContainer4px", 4 * EDSCALE); + p_theme->set_constant("margin_top", "MarginContainer4px", 4 * EDSCALE); + p_theme->set_constant("margin_right", "MarginContainer4px", 4 * EDSCALE); + p_theme->set_constant("margin_bottom", "MarginContainer4px", 4 * EDSCALE); + + // Header LinkButton variation. + p_theme->set_type_variation("HeaderSmallLink", "LinkButton"); + p_theme->set_font("font", "HeaderSmallLink", p_theme->get_font(SNAME("font"), SNAME("HeaderSmall"))); + p_theme->set_font_size("font_size", "HeaderSmallLink", p_theme->get_font_size(SNAME("font_size"), SNAME("HeaderSmall"))); + + // Flat button variations. + { + Ref<StyleBoxEmpty> style_flat_button = make_empty_stylebox(); + for (int i = 0; i < 4; i++) { + style_flat_button->set_content_margin((Side)i, p_config.button_style->get_margin((Side)i) + p_config.button_style->get_border_width((Side)i)); + } + + Ref<StyleBoxFlat> style_flat_button_pressed = p_config.button_style_pressed->duplicate(); + Color flat_pressed_color = p_config.dark_color_1.lightened(0.24).lerp(p_config.accent_color, 0.2) * Color(0.8, 0.8, 0.8, 0.85); + if (p_config.dark_theme) { + flat_pressed_color = p_config.dark_color_1.lerp(p_config.accent_color, 0.12) * Color(0.6, 0.6, 0.6, 0.85); + } + style_flat_button_pressed->set_bg_color(flat_pressed_color); + + p_theme->set_stylebox("normal", "FlatButton", style_flat_button); + p_theme->set_stylebox("hover", "FlatButton", style_flat_button); + p_theme->set_stylebox("pressed", "FlatButton", style_flat_button_pressed); + p_theme->set_stylebox("disabled", "FlatButton", style_flat_button); + + p_theme->set_stylebox("normal", "FlatMenuButton", style_flat_button); + p_theme->set_stylebox("hover", "FlatMenuButton", style_flat_button); + p_theme->set_stylebox("pressed", "FlatMenuButton", style_flat_button_pressed); + p_theme->set_stylebox("disabled", "FlatMenuButton", style_flat_button); + + // Variation for Editor Log filter buttons. + + p_theme->set_type_variation("EditorLogFilterButton", "Button"); + // When pressed, don't tint the icons with the accent color, just leave them normal. + p_theme->set_color("icon_pressed_color", "EditorLogFilterButton", p_config.icon_normal_color); + // When unpressed, dim the icons. + p_theme->set_color("icon_normal_color", "EditorLogFilterButton", p_config.icon_disabled_color); + + // When pressed, add a small bottom border to the buttons to better show their active state, + // similar to active tabs. + Ref<StyleBoxFlat> editor_log_button_pressed = style_flat_button_pressed->duplicate(); + editor_log_button_pressed->set_border_width(SIDE_BOTTOM, 2 * EDSCALE); + editor_log_button_pressed->set_border_color(p_config.accent_color); + p_theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed); + } + + // Complex editor windows. + { + Ref<StyleBoxFlat> style_complex_window = p_config.window_style->duplicate(); + style_complex_window->set_bg_color(p_config.dark_color_2); + style_complex_window->set_border_color(p_config.dark_color_2); + p_theme->set_stylebox("panel", "EditorSettingsDialog", style_complex_window); + p_theme->set_stylebox("panel", "ProjectSettingsEditor", style_complex_window); + p_theme->set_stylebox("panel", "EditorAbout", style_complex_window); + } + + // InspectorActionButton. + { + p_theme->set_type_variation("InspectorActionButton", "Button"); + + const float action_extra_margin = 32 * EDSCALE; + p_theme->set_constant("h_separation", "InspectorActionButton", action_extra_margin); + + Color color_inspector_action = p_config.dark_color_1.lerp(p_config.mono_color, 0.12); + color_inspector_action.a = 0.5; + Ref<StyleBoxFlat> style_inspector_action = p_config.button_style->duplicate(); + style_inspector_action->set_bg_color(color_inspector_action); + style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin); + p_theme->set_stylebox("normal", "InspectorActionButton", style_inspector_action); + + style_inspector_action = p_config.button_style_hover->duplicate(); + style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin); + p_theme->set_stylebox("hover", "InspectorActionButton", style_inspector_action); + + style_inspector_action = p_config.button_style_pressed->duplicate(); + style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin); + p_theme->set_stylebox("pressed", "InspectorActionButton", style_inspector_action); + + style_inspector_action = p_config.button_style_disabled->duplicate(); + style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin); + p_theme->set_stylebox("disabled", "InspectorActionButton", style_inspector_action); + } + + // Buttons in material previews. + { + const Color dim_light_color = p_config.icon_normal_color.darkened(0.24); + const Color dim_light_highlighted_color = p_config.icon_normal_color.darkened(0.18); + Ref<StyleBox> sb_empty_borderless = make_empty_stylebox(); + + p_theme->set_type_variation("PreviewLightButton", "Button"); + // When pressed, don't use the accent color tint. When unpressed, dim the icon. + p_theme->set_color("icon_normal_color", "PreviewLightButton", dim_light_color); + p_theme->set_color("icon_focus_color", "PreviewLightButton", dim_light_color); + p_theme->set_color("icon_pressed_color", "PreviewLightButton", p_config.icon_normal_color); + p_theme->set_color("icon_hover_pressed_color", "PreviewLightButton", p_config.icon_normal_color); + // Unpressed icon is dim, so use a dim highlight. + p_theme->set_color("icon_hover_color", "PreviewLightButton", dim_light_highlighted_color); + + p_theme->set_stylebox("normal", "PreviewLightButton", sb_empty_borderless); + p_theme->set_stylebox("hover", "PreviewLightButton", sb_empty_borderless); + p_theme->set_stylebox("focus", "PreviewLightButton", sb_empty_borderless); + p_theme->set_stylebox("pressed", "PreviewLightButton", sb_empty_borderless); + } + + // TabContainerOdd variation. + { + // Can be used on tabs against the base color background (e.g. nested tabs). + p_theme->set_type_variation("TabContainerOdd", "TabContainer"); + + Ref<StyleBoxFlat> style_tab_selected_odd = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->duplicate(); + style_tab_selected_odd->set_bg_color(p_config.disabled_bg_color); + p_theme->set_stylebox("tab_selected", "TabContainerOdd", style_tab_selected_odd); + + Ref<StyleBoxFlat> style_content_panel_odd = p_config.content_panel_style->duplicate(); + style_content_panel_odd->set_bg_color(p_config.disabled_bg_color); + p_theme->set_stylebox("panel", "TabContainerOdd", style_content_panel_odd); + } + + // EditorValidationPanel. + p_theme->set_stylebox("panel", "EditorValidationPanel", p_config.tree_panel_style); + + // ControlEditor. + { + p_theme->set_type_variation("ControlEditorPopupPanel", "PopupPanel"); + + Ref<StyleBoxFlat> control_editor_popup_style = p_config.popup_style->duplicate(); + control_editor_popup_style->set_shadow_size(0); + control_editor_popup_style->set_content_margin(SIDE_LEFT, p_config.base_margin * EDSCALE); + control_editor_popup_style->set_content_margin(SIDE_TOP, p_config.base_margin * EDSCALE); + control_editor_popup_style->set_content_margin(SIDE_RIGHT, p_config.base_margin * EDSCALE); + control_editor_popup_style->set_content_margin(SIDE_BOTTOM, p_config.base_margin * EDSCALE); + control_editor_popup_style->set_border_width_all(0); + + p_theme->set_stylebox("panel", "ControlEditorPopupPanel", control_editor_popup_style); + } + } + + // Editor inspector. + { + // Sub-inspectors. + for (int i = 0; i < 16; i++) { + Color si_base_color = p_config.accent_color; + + float hue_rotate = (i * 2 % 16) / 16.0; + si_base_color.set_hsv(Math::fmod(float(si_base_color.get_h() + hue_rotate), float(1.0)), si_base_color.get_s(), si_base_color.get_v()); + si_base_color = p_config.accent_color.lerp(si_base_color, float(EDITOR_GET("docks/property_editor/subresource_hue_tint"))); + + // Sub-inspector background. + Ref<StyleBoxFlat> sub_inspector_bg = p_config.base_style->duplicate(); + sub_inspector_bg->set_bg_color(p_config.dark_color_1.lerp(si_base_color, 0.08)); + sub_inspector_bg->set_border_width_all(2 * EDSCALE); + sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8)); + sub_inspector_bg->set_content_margin_all(4 * EDSCALE); + sub_inspector_bg->set_corner_radius(CORNER_TOP_LEFT, 0); + sub_inspector_bg->set_corner_radius(CORNER_TOP_RIGHT, 0); + + p_theme->set_stylebox("sub_inspector_bg" + itos(i), EditorStringName(Editor), sub_inspector_bg); + + // EditorProperty background while it has a sub-inspector open. + Ref<StyleBoxFlat> bg_color = make_flat_stylebox(si_base_color * Color(0.7, 0.7, 0.7, 0.8), 0, 0, 0, 0, p_config.corner_radius); + bg_color->set_anti_aliased(false); + bg_color->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + bg_color->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + + p_theme->set_stylebox("sub_inspector_property_bg" + itos(i), EditorStringName(Editor), bg_color); + } + + p_theme->set_color("sub_inspector_property_color", EditorStringName(Editor), p_config.dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)); + + // EditorProperty. + + Ref<StyleBoxFlat> style_property_bg = p_config.base_style->duplicate(); + style_property_bg->set_bg_color(p_config.highlight_color); + style_property_bg->set_border_width_all(0); + + Ref<StyleBoxFlat> style_property_child_bg = p_config.base_style->duplicate(); + style_property_child_bg->set_bg_color(p_config.dark_color_2); + style_property_child_bg->set_border_width_all(0); + + p_theme->set_stylebox("bg", "EditorProperty", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + p_theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg); + p_theme->set_stylebox("child_bg", "EditorProperty", style_property_child_bg); + p_theme->set_constant("font_offset", "EditorProperty", 8 * EDSCALE); + p_theme->set_constant("v_separation", "EditorProperty", p_config.increased_margin * EDSCALE); + + const Color property_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.5); + const Color readonly_color = property_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25); + const Color readonly_warning_color = p_config.error_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25); + + p_theme->set_color("property_color", "EditorProperty", property_color); + p_theme->set_color("readonly_color", "EditorProperty", readonly_color); + p_theme->set_color("warning_color", "EditorProperty", p_config.warning_color); + p_theme->set_color("readonly_warning_color", "EditorProperty", readonly_warning_color); + + Ref<StyleBoxFlat> style_property_group_note = p_config.base_style->duplicate(); + Color property_group_note_color = p_config.accent_color; + property_group_note_color.a = 0.1; + style_property_group_note->set_bg_color(property_group_note_color); + p_theme->set_stylebox("bg_group_note", "EditorProperty", style_property_group_note); + + // EditorInspectorSection. + + Color inspector_section_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.35); + p_theme->set_color("font_color", "EditorInspectorSection", inspector_section_color); + + Color inspector_indent_color = p_config.accent_color; + inspector_indent_color.a = 0.2; + Ref<StyleBoxFlat> inspector_indent_style = make_flat_stylebox(inspector_indent_color, 2.0 * EDSCALE, 0, 2.0 * EDSCALE, 0); + p_theme->set_stylebox("indent_box", "EditorInspectorSection", inspector_indent_style); + p_theme->set_constant("indent_size", "EditorInspectorSection", 6.0 * EDSCALE); + + Color prop_category_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.12); + Color prop_section_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.09); + Color prop_subsection_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.06); + + p_theme->set_color("prop_category", EditorStringName(Editor), prop_category_color); + p_theme->set_color("prop_section", EditorStringName(Editor), prop_section_color); + p_theme->set_color("prop_subsection", EditorStringName(Editor), prop_subsection_color); + + // EditorInspectorCategory. + + Ref<StyleBoxFlat> category_bg = p_config.base_style->duplicate(); + category_bg->set_bg_color(prop_category_color); + category_bg->set_border_color(prop_category_color); + p_theme->set_stylebox("bg", "EditorInspectorCategory", category_bg); + + p_theme->set_constant("inspector_margin", EditorStringName(Editor), 12 * EDSCALE); + + // Dictionary editor. + + // Expand to the left and right by 4px to compensate for the dictionary editor margins. + Ref<StyleBoxFlat> style_dictionary_add_item = make_flat_stylebox(prop_subsection_color, 0, 4, 0, 4, p_config.corner_radius); + style_dictionary_add_item->set_expand_margin(SIDE_LEFT, 4 * EDSCALE); + style_dictionary_add_item->set_expand_margin(SIDE_RIGHT, 4 * EDSCALE); + p_theme->set_stylebox("DictionaryAddItem", EditorStringName(EditorStyles), style_dictionary_add_item); + } + + // Editor help. + { + Ref<StyleBoxFlat> style_editor_help = p_config.base_style->duplicate(); + style_editor_help->set_bg_color(p_config.dark_color_2); + style_editor_help->set_border_color(p_config.dark_color_3); + p_theme->set_stylebox("background", "EditorHelp", style_editor_help); + + const Color kbd_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.5); + + p_theme->set_color("title_color", "EditorHelp", p_config.accent_color); + p_theme->set_color("headline_color", "EditorHelp", p_config.mono_color); + p_theme->set_color("text_color", "EditorHelp", p_config.font_color); + p_theme->set_color("comment_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("symbol_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("value_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("qualifier_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.8)); + p_theme->set_color("type_color", "EditorHelp", p_config.accent_color.lerp(p_config.font_color, 0.5)); + p_theme->set_color("selection_color", "EditorHelp", p_config.selection_color); + p_theme->set_color("link_color", "EditorHelp", p_config.accent_color.lerp(p_config.mono_color, 0.8)); + p_theme->set_color("code_color", "EditorHelp", p_config.accent_color.lerp(p_config.mono_color, 0.6)); + p_theme->set_color("kbd_color", "EditorHelp", p_config.accent_color.lerp(kbd_color, 0.6)); + p_theme->set_color("code_bg_color", "EditorHelp", p_config.dark_color_3); + p_theme->set_color("kbd_bg_color", "EditorHelp", p_config.dark_color_1); + p_theme->set_color("param_bg_color", "EditorHelp", p_config.dark_color_1); + p_theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE)); + p_theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE); + p_theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE); + p_theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE); + p_theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE); + } + + // Asset Library. + p_theme->set_stylebox("bg", "AssetLib", p_config.base_empty_style); + p_theme->set_stylebox("panel", "AssetLib", p_config.content_panel_style); + p_theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5)); // FIXME: Use a defined color instead. + p_theme->set_icon("dismiss", "AssetLib", p_theme->get_icon(SNAME("Close"), EditorStringName(EditorIcons))); + + // Debugger. + { + Ref<StyleBoxFlat> debugger_panel_style = p_config.content_panel_style->duplicate(); + debugger_panel_style->set_border_width(SIDE_BOTTOM, 0); + p_theme->set_stylebox("DebuggerPanel", EditorStringName(EditorStyles), debugger_panel_style); + + // This pattern of get_font()->get_height(get_font_size()) is used quite a lot and is very verbose. + // FIXME: Introduce Theme::get_font_height() / Control::get_theme_font_height() / Window::get_theme_font_height(). + const int offset_i1 = p_theme->get_font(SNAME("tab_selected"), SNAME("TabContainer"))->get_height(p_theme->get_font_size(SNAME("tab_selected"), SNAME("TabContainer"))); + const int offset_i2 = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->get_minimum_size().height; + const int offset_i3 = p_theme->get_stylebox(SNAME("panel"), SNAME("TabContainer"))->get_content_margin(SIDE_TOP); + const int invisible_top_offset = offset_i1 + offset_i2 + offset_i3; + + Ref<StyleBoxFlat> invisible_top_panel_style = p_config.content_panel_style->duplicate(); + invisible_top_panel_style->set_expand_margin(SIDE_TOP, -invisible_top_offset); + invisible_top_panel_style->set_content_margin(SIDE_TOP, 0); + p_theme->set_stylebox("BottomPanelDebuggerOverride", EditorStringName(EditorStyles), invisible_top_panel_style); + } + + // Resource and node editors. + { + // TextureRegion editor. + Ref<StyleBoxFlat> style_texture_region_bg = p_config.tree_panel_style->duplicate(); + style_texture_region_bg->set_content_margin_all(0); + p_theme->set_stylebox("TextureRegionPreviewBG", EditorStringName(EditorStyles), style_texture_region_bg); + p_theme->set_stylebox("TextureRegionPreviewFG", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + + // Theme editor. + { + p_theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25)); + + Color theme_preview_picker_bg_color = p_config.accent_color; + theme_preview_picker_bg_color.a = 0.2; + Ref<StyleBoxFlat> theme_preview_picker_sb = make_flat_stylebox(theme_preview_picker_bg_color, 0, 0, 0, 0); + theme_preview_picker_sb->set_border_color(p_config.accent_color); + theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE); + p_theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb); + + Color theme_preview_picker_label_bg_color = p_config.accent_color; + theme_preview_picker_label_bg_color.set_v(0.5); + Ref<StyleBoxFlat> theme_preview_picker_label_sb = make_flat_stylebox(theme_preview_picker_label_bg_color, 4.0, 1.0, 4.0, 3.0); + p_theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb); + + Ref<StyleBoxFlat> style_theme_preview_tab = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainerOdd"))->duplicate(); + style_theme_preview_tab->set_expand_margin(SIDE_BOTTOM, 5 * EDSCALE); + p_theme->set_stylebox("ThemeEditorPreviewFG", EditorStringName(EditorStyles), style_theme_preview_tab); + + Ref<StyleBoxFlat> style_theme_preview_bg_tab = p_theme->get_stylebox(SNAME("tab_unselected"), SNAME("TabContainer"))->duplicate(); + style_theme_preview_bg_tab->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE); + p_theme->set_stylebox("ThemeEditorPreviewBG", EditorStringName(EditorStyles), style_theme_preview_bg_tab); + } + + // VisualShader editor. + p_theme->set_stylebox("label_style", "VShaderEditor", make_empty_stylebox(2, 1, 2, 1)); + + // StateMachine graph. + { + p_theme->set_stylebox("panel", "GraphStateMachine", p_config.tree_panel_style); + p_theme->set_stylebox("error_panel", "GraphStateMachine", p_config.tree_panel_style); + p_theme->set_color("error_color", "GraphStateMachine", p_config.error_color); + + const int sm_margin_side = 10 * EDSCALE; + const int sm_margin_bottom = 2; + const Color sm_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09); + + Ref<StyleBoxFlat> sm_node_style = make_flat_stylebox(p_config.dark_color_3 * Color(1, 1, 1, 0.7), sm_margin_side, 24 * EDSCALE, sm_margin_side, sm_margin_bottom, p_config.corner_radius); + sm_node_style->set_border_width_all(p_config.border_width); + sm_node_style->set_border_color(sm_bg_color); + + Ref<StyleBoxFlat> sm_node_selected_style = make_flat_stylebox(sm_bg_color * Color(1, 1, 1, 0.9), sm_margin_side, 24 * EDSCALE, sm_margin_side, sm_margin_bottom, p_config.corner_radius); + sm_node_selected_style->set_border_width_all(2 * EDSCALE + p_config.border_width); + sm_node_selected_style->set_border_color(p_config.accent_color * Color(1, 1, 1, 0.9)); + sm_node_selected_style->set_shadow_size(8 * EDSCALE); + sm_node_selected_style->set_shadow_color(p_config.shadow_color); + + Ref<StyleBoxFlat> sm_node_playing_style = sm_node_selected_style->duplicate(); + sm_node_playing_style->set_border_color(p_config.warning_color); + sm_node_playing_style->set_shadow_color(p_config.warning_color * Color(1, 1, 1, 0.2)); + + p_theme->set_stylebox("node_frame", "GraphStateMachine", sm_node_style); + p_theme->set_stylebox("node_frame_selected", "GraphStateMachine", sm_node_selected_style); + p_theme->set_stylebox("node_frame_playing", "GraphStateMachine", sm_node_playing_style); + + Ref<StyleBoxFlat> sm_node_start_style = sm_node_style->duplicate(); + sm_node_start_style->set_border_width_all(1 * EDSCALE); + sm_node_start_style->set_border_color(p_config.success_color.lightened(0.24)); + p_theme->set_stylebox("node_frame_start", "GraphStateMachine", sm_node_start_style); + + Ref<StyleBoxFlat> sm_node_end_style = sm_node_style->duplicate(); + sm_node_end_style->set_border_width_all(1 * EDSCALE); + sm_node_end_style->set_border_color(p_config.error_color); + p_theme->set_stylebox("node_frame_end", "GraphStateMachine", sm_node_end_style); + + p_theme->set_font("node_title_font", "GraphStateMachine", p_theme->get_font(SNAME("font"), SNAME("Label"))); + p_theme->set_font_size("node_title_font_size", "GraphStateMachine", p_theme->get_font_size(SNAME("font_size"), SNAME("Label"))); + p_theme->set_color("node_title_font_color", "GraphStateMachine", p_config.font_color); + + p_theme->set_color("transition_color", "GraphStateMachine", p_config.font_color); + p_theme->set_color("transition_disabled_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.2)); + p_theme->set_color("transition_icon_color", "GraphStateMachine", Color(1, 1, 1)); + p_theme->set_color("transition_icon_disabled_color", "GraphStateMachine", Color(1, 1, 1, 0.2)); + p_theme->set_color("highlight_color", "GraphStateMachine", p_config.accent_color); + p_theme->set_color("highlight_disabled_color", "GraphStateMachine", p_config.accent_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("guideline_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.3)); + + p_theme->set_color("playback_color", "GraphStateMachine", p_config.font_color); + p_theme->set_color("playback_background_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.3)); + } + } +} + +void EditorThemeManager::_generate_text_editor_defaults(ThemeConfiguration &p_config) { + // Adaptive colors for comments and elements with lower relevance. + const Color dim_color = Color(p_config.font_color, 0.5); + const float mono_value = p_config.mono_color.r; + const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07); + const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14); + const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27); + + /* clang-format off */ + // Syntax highlight token colors. + const Color symbol_color = p_config.dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61); + const Color keyword_color = p_config.dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51); + const Color control_flow_keyword_color = p_config.dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8); + const Color base_type_color = p_config.dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2); + const Color engine_type_color = p_config.dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4); + const Color user_type_color = p_config.dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4); + const Color comment_color = p_config.dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5); + const Color doc_comment_color = p_config.dark_theme ? Color(0.6, 0.7, 0.8, 0.8) : Color(0.15, 0.15, 0.4, 0.7); + const Color string_color = p_config.dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0); + + // Use the brightest background color on a light theme (which generally uses a negative contrast rate). + const Color te_background_color = p_config.dark_theme ? p_config.dark_color_2 : p_config.dark_color_3; + const Color completion_background_color = p_config.dark_theme ? p_config.base_color : p_config.dark_color_2; + const Color completion_selected_color = alpha1; + const Color completion_existing_color = alpha2; + // Same opacity as the scroll grabber editor icon. + const Color completion_scroll_color = Color(mono_value, mono_value, mono_value, 0.29); + const Color completion_scroll_hovered_color = Color(mono_value, mono_value, mono_value, 0.4); + const Color completion_font_color = p_config.font_color; + const Color text_color = p_config.font_color; + const Color line_number_color = dim_color; + const Color safe_line_number_color = p_config.dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75); + const Color caret_color = p_config.mono_color; + const Color caret_background_color = p_config.mono_color.inverted(); + const Color text_selected_color = Color(0, 0, 0, 0); + const Color selection_color = p_config.selection_color; + const Color brace_mismatch_color = p_config.dark_theme ? p_config.error_color : Color(1, 0.08, 0, 1); + const Color current_line_color = alpha1; + const Color line_length_guideline_color = p_config.dark_theme ? p_config.base_color : p_config.dark_color_2; + const Color word_highlighted_color = alpha1; + const Color number_color = p_config.dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1); + const Color function_color = p_config.dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1); + const Color member_variable_color = p_config.dark_theme ? Color(0.34, 0.7, 1.0).lerp(p_config.mono_color, 0.6) : Color(0, 0.4, 0.68, 1); + const Color mark_color = Color(p_config.error_color.r, p_config.error_color.g, p_config.error_color.b, 0.3); + const Color bookmark_color = Color(0.08, 0.49, 0.98); + const Color breakpoint_color = p_config.dark_theme ? p_config.error_color : Color(1, 0.27, 0.2, 1); + const Color executing_line_color = Color(0.98, 0.89, 0.27); + const Color code_folding_color = alpha3; + const Color folded_code_region_color = Color(0.68, 0.46, 0.77, 0.2); + const Color search_result_color = alpha1; + const Color search_result_border_color = p_config.dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38); + /* clang-format on */ + + EditorSettings *setting = EditorSettings::get_singleton(); + + /* clang-format off */ + setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true); + setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true); + setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true); + setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true); + setting->set_initial_value("text_editor/theme/highlighting/doc_comment_color", doc_comment_color, true); + setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true); + setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_hovered_color", completion_scroll_hovered_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true); + setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true); + setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true); + setting->set_initial_value("text_editor/theme/highlighting/safe_line_number_color", safe_line_number_color, true); + setting->set_initial_value("text_editor/theme/highlighting/caret_color", caret_color, true); + setting->set_initial_value("text_editor/theme/highlighting/caret_background_color", caret_background_color, true); + setting->set_initial_value("text_editor/theme/highlighting/text_selected_color", text_selected_color, true); + setting->set_initial_value("text_editor/theme/highlighting/selection_color", selection_color, true); + setting->set_initial_value("text_editor/theme/highlighting/brace_mismatch_color", brace_mismatch_color, true); + setting->set_initial_value("text_editor/theme/highlighting/current_line_color", current_line_color, true); + setting->set_initial_value("text_editor/theme/highlighting/line_length_guideline_color", line_length_guideline_color, true); + setting->set_initial_value("text_editor/theme/highlighting/word_highlighted_color", word_highlighted_color, true); + setting->set_initial_value("text_editor/theme/highlighting/number_color", number_color, true); + setting->set_initial_value("text_editor/theme/highlighting/function_color", function_color, true); + setting->set_initial_value("text_editor/theme/highlighting/member_variable_color", member_variable_color, true); + setting->set_initial_value("text_editor/theme/highlighting/mark_color", mark_color, true); + setting->set_initial_value("text_editor/theme/highlighting/bookmark_color", bookmark_color, true); + setting->set_initial_value("text_editor/theme/highlighting/breakpoint_color", breakpoint_color, true); + setting->set_initial_value("text_editor/theme/highlighting/executing_line_color", executing_line_color, true); + setting->set_initial_value("text_editor/theme/highlighting/code_folding_color", code_folding_color, true); + setting->set_initial_value("text_editor/theme/highlighting/folded_code_region_color", folded_code_region_color, true); + setting->set_initial_value("text_editor/theme/highlighting/search_result_color", search_result_color, true); + setting->set_initial_value("text_editor/theme/highlighting/search_result_border_color", search_result_border_color, true); + /* clang-format on */ +} + +void EditorThemeManager::_populate_text_editor_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config) { + String text_editor_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme"); + if (text_editor_color_theme == "Default") { + _generate_text_editor_defaults(p_config); + } else if (text_editor_color_theme == "Godot 2") { + EditorSettings::get_singleton()->load_text_editor_theme(); + } + + // Now theme is loaded, apply it to CodeEdit. + p_theme->set_font("font", "CodeEdit", p_theme->get_font(SNAME("source"), EditorStringName(EditorFonts))); + p_theme->set_font_size("font_size", "CodeEdit", p_theme->get_font_size(SNAME("source_size"), EditorStringName(EditorFonts))); + + /* clang-format off */ + p_theme->set_icon("tab", "CodeEdit", p_theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons))); + p_theme->set_icon("space", "CodeEdit", p_theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons))); + p_theme->set_icon("folded", "CodeEdit", p_theme->get_icon(SNAME("CodeFoldedRightArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("can_fold", "CodeEdit", p_theme->get_icon(SNAME("CodeFoldDownArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("folded_code_region", "CodeEdit", p_theme->get_icon(SNAME("CodeRegionFoldedRightArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("can_fold_code_region", "CodeEdit", p_theme->get_icon(SNAME("CodeRegionFoldDownArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("executing_line", "CodeEdit", p_theme->get_icon(SNAME("TextEditorPlay"), EditorStringName(EditorIcons))); + p_theme->set_icon("breakpoint", "CodeEdit", p_theme->get_icon(SNAME("Breakpoint"), EditorStringName(EditorIcons))); + /* clang-format on */ + + p_theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing")); + + const Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color"); + Ref<StyleBoxFlat> code_edit_stylebox = make_flat_stylebox(background_color, p_config.widget_margin.x, p_config.widget_margin.y, p_config.widget_margin.x, p_config.widget_margin.y, p_config.corner_radius); + p_theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox); + p_theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox); + p_theme->set_stylebox("focus", "CodeEdit", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); + + p_theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); // Unset any color, we use a stylebox. + + /* clang-format off */ + p_theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color")); + p_theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color")); + p_theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color")); + p_theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color")); + p_theme->set_color("completion_scroll_hovered_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_hovered_color")); + p_theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color")); + p_theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color")); + p_theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/caret_color")); + p_theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_selected_color")); + p_theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/selection_color")); + p_theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/brace_mismatch_color")); + p_theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/current_line_color")); + p_theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_length_guideline_color")); + p_theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/word_highlighted_color")); + p_theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/bookmark_color")); + p_theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/breakpoint_color")); + p_theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/executing_line_color")); + p_theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/code_folding_color")); + p_theme->set_color("folded_code_region_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/folded_code_region_color")); + p_theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_color")); + p_theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_border_color")); + /* clang-format on */ +} + +// Public interface for theme generation. + +Ref<Theme> EditorThemeManager::generate_theme(const Ref<Theme> &p_old_theme) { + OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Generate Theme"); + + Ref<Theme> theme = _create_base_theme(p_old_theme); + + const String custom_theme_path = EDITOR_GET("interface/theme/custom_theme"); + if (!custom_theme_path.is_empty()) { + Ref<Theme> custom_theme = ResourceLoader::load(custom_theme_path); + if (custom_theme.is_valid()) { + theme->merge_with(custom_theme); + } + } + + OS::get_singleton()->benchmark_end_measure("EditorTheme", "Generate Theme"); + return theme; +} + +bool EditorThemeManager::is_generated_theme_outdated() { + // This list includes settings used by files in the editor/themes folder. + // Note that the editor scale is purposefully omitted because it cannot be changed + // without a restart, so there is no point regenerating the theme. + + // TODO: We can use this information more intelligently to do partial theme updates and speed things up. + return EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") || + EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/font") || + EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/main_font") || + EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/code_font") || + EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") || + EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") || + EditorSettings::get_singleton()->check_changed_settings_in_group("filesystem/file_dialog/thumbnail_size") || + EditorSettings::get_singleton()->check_changed_settings_in_group("run/output/font_size") || + EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") || + EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles"); +} + +void EditorThemeManager::initialize() { + EditorColorMap::create(); + EditorTheme::initialize(); +} + +void EditorThemeManager::finalize() { + EditorColorMap::finish(); + EditorTheme::finalize(); +} diff --git a/editor/themes/editor_theme_manager.h b/editor/themes/editor_theme_manager.h new file mode 100644 index 0000000000..86188ec244 --- /dev/null +++ b/editor/themes/editor_theme_manager.h @@ -0,0 +1,150 @@ +/**************************************************************************/ +/* editor_theme_manager.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef EDITOR_THEME_MANAGER_H +#define EDITOR_THEME_MANAGER_H + +#include "scene/resources/style_box_flat.h" +#include "scene/resources/theme.h" + +class EditorThemeManager { + struct ThemeConfiguration { + // Basic properties. + + String preset; + String spacing_preset; + bool dark_theme = false; + + Color base_color; + Color accent_color; + float contrast = 1.0; + float icon_saturation = 1.0; + + // Extra properties. + + int base_spacing = 4; + int extra_spacing = 0; + int border_width = 0; + int corner_radius = 3; + + bool draw_extra_borders = false; + float relationship_line_opacity = 1.0; + int thumb_size = 16; + int class_icon_size = 16; + bool increase_scrollbar_touch_area = false; + float gizmo_handle_scale = 1.0; + int color_picker_button_height = 28; + + float default_contrast = 1.0; + + // Generated properties. + + int base_margin = 4; + int increased_margin = 4; + int separation_margin = 4; + int popup_margin = 12; + int window_border_margin = 8; + int top_bar_separation = 8; + int forced_even_separation = 0; + + Color mono_color; + Color dark_color_1; + Color dark_color_2; + Color dark_color_3; + Color contrast_color_1; + Color contrast_color_2; + Color highlight_color; + Color highlight_disabled_color; + Color success_color; + Color warning_color; + Color error_color; + Color extra_border_color_1; + Color extra_border_color_2; + + Color font_color; + Color font_focus_color; + Color font_hover_color; + Color font_pressed_color; + Color font_hover_pressed_color; + Color font_disabled_color; + Color font_readonly_color; + Color font_placeholder_color; + Color font_outline_color; + + Color icon_normal_color; + Color icon_focus_color; + Color icon_hover_color; + Color icon_pressed_color; + Color icon_disabled_color; + + Color shadow_color; + Color selection_color; + Color disabled_border_color; + Color disabled_bg_color; + Color separator_color; + + Ref<StyleBoxFlat> base_style; + Ref<StyleBoxEmpty> base_empty_style; + + Ref<StyleBoxFlat> button_style; + Ref<StyleBoxFlat> button_style_disabled; + Ref<StyleBoxFlat> button_style_focus; + Ref<StyleBoxFlat> button_style_pressed; + Ref<StyleBoxFlat> button_style_hover; + + Ref<StyleBoxFlat> popup_style; + Ref<StyleBoxFlat> window_style; + Ref<StyleBoxFlat> dialog_style; + Ref<StyleBoxFlat> panel_container_style; + Ref<StyleBoxFlat> content_panel_style; + Ref<StyleBoxFlat> tree_panel_style; + + Vector2 widget_margin; + }; + + static Ref<Theme> _create_base_theme(const Ref<Theme> &p_old_theme = nullptr); + static ThemeConfiguration _create_theme_config(const Ref<Theme> &p_theme); + + static void _create_shared_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config); + static void _populate_standard_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config); + static void _populate_editor_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config); + + static void _generate_text_editor_defaults(ThemeConfiguration &p_config); + static void _populate_text_editor_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config); + +public: + static Ref<Theme> generate_theme(const Ref<Theme> &p_old_theme = nullptr); + static bool is_generated_theme_outdated(); + + static void initialize(); + static void finalize(); +}; + +#endif // EDITOR_THEME_MANAGER_H diff --git a/editor/window_wrapper.cpp b/editor/window_wrapper.cpp index 2d89e4df46..a085c2e44f 100644 --- a/editor/window_wrapper.cpp +++ b/editor/window_wrapper.cpp @@ -31,10 +31,10 @@ #include "window_wrapper.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/progress_dialog.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/label.h" #include "scene/gui/panel.h" @@ -74,7 +74,7 @@ class ShortcutBin : public Node { }; Rect2 WindowWrapper::_get_default_window_rect() const { - // Assume that the control rect is the desidered one for the window. + // Assume that the control rect is the desired one for the window. return wrapped_control->get_screen_rect(); } diff --git a/main/main.cpp b/main/main.cpp index 9bd2578eba..dbe186d63a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -475,7 +475,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n"); OS::get_singleton()->print(" --gpu-profile Show a GPU profile of the tasks that took the most time during frame rendering.\n"); OS::get_singleton()->print(" --gpu-validation Enable graphics API validation layers for debugging.\n"); -#if DEBUG_ENABLED +#ifdef DEBUG_ENABLED OS::get_singleton()->print(" --gpu-abort Abort on graphics API usage errors (usually validation layer errors). May help see the problem if your system freezes.\n"); #endif OS::get_singleton()->print(" --generate-spirv-debug-info Generate SPIR-V debug information. This allows source-level shader debugging with RenderDoc.\n"); @@ -1616,15 +1616,17 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // Initialize WorkerThreadPool. { - int worker_threads = GLOBAL_GET("threading/worker_pool/max_threads"); - bool low_priority_use_system_threads = GLOBAL_GET("threading/worker_pool/use_system_threads_for_low_priority_tasks"); - float low_property_ratio = GLOBAL_GET("threading/worker_pool/low_priority_thread_ratio"); - +#ifdef THREADS_ENABLED if (editor || project_manager) { - WorkerThreadPool::get_singleton()->init(); + WorkerThreadPool::get_singleton()->init(-1, 0.75); } else { - WorkerThreadPool::get_singleton()->init(worker_threads, low_priority_use_system_threads, low_property_ratio); + int worker_threads = GLOBAL_GET("threading/worker_pool/max_threads"); + float low_priority_ratio = GLOBAL_GET("threading/worker_pool/low_priority_thread_ratio"); + WorkerThreadPool::get_singleton()->init(worker_threads, low_priority_ratio); } +#else + WorkerThreadPool::get_singleton()->init(0, 0); +#endif } #ifdef TOOLS_ENABLED @@ -2463,7 +2465,7 @@ Error Main::setup2() { } if (err != OK || display_server == nullptr) { - ERR_PRINT("Unable to create DisplayServer, all display drivers failed."); + ERR_PRINT("Unable to create DisplayServer, all display drivers failed.\nUse \"--headless\" command line argument to run the engine in headless mode if this is desired (e.g. for continuous integration)."); return err; } diff --git a/main/performance.cpp b/main/performance.cpp index e24a3673b9..b5f1a45b9a 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -30,7 +30,6 @@ #include "performance.h" -#include "core/object/message_queue.h" #include "core/os/os.h" #include "core/variant/typed_array.h" #include "scene/main/node.h" diff --git a/misc/dist/html/editor.html b/misc/dist/html/editor.html index 93afbf085d..e5c68c6338 100644 --- a/misc/dist/html/editor.html +++ b/misc/dist/html/editor.html @@ -23,7 +23,7 @@ <link id="-gd-engine-icon" rel="icon" type="image/png" href="favicon.png"> <link rel="apple-touch-icon" type="image/png" href="favicon.png"> <link rel="manifest" href="manifest.json"> - <title>Godot Engine Web Editor (@GODOT_VERSION@)</title> + <title>Godot Engine Web Editor (___GODOT_VERSION___)</title> <style> *:focus { /* More visible outline for better keyboard navigation. */ @@ -294,7 +294,7 @@ a:active { <br > <img src="logo.svg" alt="Godot Engine logo" width="1024" height="414" style="width: auto; height: auto; max-width: min(85%, 50vh); max-height: 250px"> <br > - @GODOT_VERSION@ + ___GODOT_VERSION___ <br > <a href="releases/">Need an old version?</a> <br > @@ -384,7 +384,9 @@ window.addEventListener('load', () => { }); } - const missing = Engine.getMissingFeatures(); + const missing = Engine.getMissingFeatures({ + threads: ___GODOT_THREADS_ENABLED___, + }); if (missing.length) { // Display error dialog as threading support is required for the editor. document.getElementById('startButton').disabled = 'disabled'; diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html index 6710cb1533..54571e27c7 100644 --- a/misc/dist/html/full-size.html +++ b/misc/dist/html/full-size.html @@ -136,6 +136,7 @@ body { <script src="$GODOT_URL"></script> <script> const GODOT_CONFIG = $GODOT_CONFIG; +const GODOT_THREADS_ENABLED = $GODOT_THREADS_ENABLED; const engine = new Engine(GODOT_CONFIG); (function () { @@ -213,7 +214,9 @@ const engine = new Engine(GODOT_CONFIG); initializing = false; } - const missing = Engine.getMissingFeatures(); + const missing = Engine.getMissingFeatures({ + threads: GODOT_THREADS_ENABLED, + }); if (missing.length !== 0) { const missingMsg = 'Error\nThe following features required to run Godot projects on the Web are missing:\n'; displayFailureNotice(missingMsg + missing.join('\n')); diff --git a/misc/dist/html/service-worker.js b/misc/dist/html/service-worker.js index 310574f21d..70e7a399e1 100644 --- a/misc/dist/html/service-worker.js +++ b/misc/dist/html/service-worker.js @@ -3,14 +3,14 @@ // that they need an Internet connection to run the project if desired. // Incrementing CACHE_VERSION will kick off the install event and force // previously cached resources to be updated from the network. -const CACHE_VERSION = "@GODOT_VERSION@"; -const CACHE_PREFIX = "@GODOT_NAME@-sw-cache-"; +const CACHE_VERSION = "___GODOT_VERSION___"; +const CACHE_PREFIX = "___GODOT_NAME___-sw-cache-"; const CACHE_NAME = CACHE_PREFIX + CACHE_VERSION; -const OFFLINE_URL = "@GODOT_OFFLINE_PAGE@"; +const OFFLINE_URL = "___GODOT_OFFLINE_PAGE___"; // Files that will be cached on load. -const CACHED_FILES = @GODOT_CACHE@; +const CACHED_FILES = ___GODOT_CACHE___; // Files that we might not want the user to preload, and will only be cached on first load. -const CACHABLE_FILES = @GODOT_OPT_CACHE@; +const CACHABLE_FILES = ___GODOT_OPT_CACHE___; const FULL_CACHE = CACHED_FILES.concat(CACHABLE_FILES); self.addEventListener("install", (event) => { @@ -22,7 +22,7 @@ self.addEventListener("activate", (event) => { function (keys) { // Remove old caches. return Promise.all(keys.filter(key => key.startsWith(CACHE_PREFIX) && key != CACHE_NAME).map(key => caches.delete(key))); - }).then(function() { + }).then(function () { // Enable navigation preload if available. return ("navigationPreload" in self.registration) ? self.registration.navigationPreload.enable() : Promise.resolve(); }) diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index 27bc2844d5..bd2560c280 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -254,7 +254,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = $min_version; "LD_CLASSIC_1000" = ""; "LD_CLASSIC_1100" = ""; "LD_CLASSIC_1200" = ""; @@ -299,7 +299,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = $min_version; "LD_CLASSIC_1000" = ""; "LD_CLASSIC_1100" = ""; "LD_CLASSIC_1200" = ""; @@ -318,7 +318,6 @@ buildSettings = { ARCHS = "$godot_archs"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - $pbx_launch_image_usage_setting CODE_SIGN_ENTITLEMENTS = "$binary/$binary.entitlements"; CODE_SIGN_IDENTITY = "$code_sign_identity_debug"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug"; @@ -326,7 +325,7 @@ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; DEVELOPMENT_TEAM = $team_id; INFOPLIST_FILE = "$binary/$binary-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = $min_version; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -354,7 +353,6 @@ buildSettings = { ARCHS = "$godot_archs"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - $pbx_launch_image_usage_setting CODE_SIGN_ENTITLEMENTS = "$binary/$binary.entitlements"; CODE_SIGN_IDENTITY = "$code_sign_identity_release"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release"; @@ -362,7 +360,7 @@ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; DEVELOPMENT_TEAM = $team_id; INFOPLIST_FILE = "$binary/$binary-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = $min_version; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Contents.json b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Contents.json deleted file mode 100644 index f3ac82189f..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Contents.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "images" : [ - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "2436h", - "filename" : "Default-Portrait-X.png", - "minimum-system-version" : "11.0", - "orientation" : "portrait", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "2436h", - "filename" : "Default-Landscape-X.png", - "minimum-system-version" : "11.0", - "orientation" : "landscape", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "Default-Portrait-736h@3x.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "Default-Landscape-736h@3x.png", - "minimum-system-version" : "8.0", - "orientation" : "landscape", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "667h", - "filename" : "Default-667h@2x.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "filename" : "Default-480h@2x.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "retina4", - "filename" : "Default-568h@2x.png", - "minimum-system-version" : "7.0", - "orientation" : "portrait", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "filename" : "Default-Portrait.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "filename" : "Default-Landscape.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "filename" : "Default-Portrait@2x.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "filename" : "Default-Landscape@2x.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-480h@2x.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-480h@2x.png Binary files differdeleted file mode 100644 index 7c9cac3f0e..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-480h@2x.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png Binary files differdeleted file mode 100644 index 0226bdf7cd..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-667h@2x.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-667h@2x.png Binary files differdeleted file mode 100644 index 25904c186c..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-667h@2x.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h@3x.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h@3x.png Binary files differdeleted file mode 100644 index 649df071f9..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h@3x.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape-X.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape-X.png Binary files differdeleted file mode 100644 index f3bd86a7de..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape-X.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape.png Binary files differdeleted file mode 100644 index d5692eaffa..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png Binary files differdeleted file mode 100644 index 8c4fe87b9c..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait-736h@3x.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait-736h@3x.png Binary files differdeleted file mode 100644 index e755beb803..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait-736h@3x.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait-X.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait-X.png Binary files differdeleted file mode 100644 index f676fda263..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait-X.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait.png Binary files differdeleted file mode 100644 index 43da4f3ed6..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait.png +++ /dev/null diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png Binary files differdeleted file mode 100644 index 075a6790ce..0000000000 --- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png +++ /dev/null diff --git a/misc/dist/macos_template.app/Contents/Info.plist b/misc/dist/macos_template.app/Contents/Info.plist index 40966d2ced..78bb559c0e 100644 --- a/misc/dist/macos_template.app/Contents/Info.plist +++ b/misc/dist/macos_template.app/Contents/Info.plist @@ -58,5 +58,6 @@ $usage_descriptions </dict> <key>NSHighResolutionCapable</key> $highres +$additional_plist_content </dict> </plist> diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected index 8a31d0fbc8..25094dda77 100644 --- a/misc/extension_api_validation/4.2-stable.expected +++ b/misc/extension_api_validation/4.2-stable.expected @@ -14,3 +14,48 @@ Validate extension JSON: Error: Field 'classes/TileData/methods/get_navigation_p Validate extension JSON: Error: Field 'classes/TileData/methods/get_occluder/arguments': size changed value in new API, from 1 to 4. Added optional argument to get_navigation_polygon and get_occluder to specify a polygon transform. + + +GH-85393 +-------- +Validate extension JSON: Error: Field 'classes/PhysicsShapeQueryParameters3D/properties/motion': type changed value in new API, from "Vector2" to "Vector3". + +The type was registered wrongly, this was a bug. + + +GH-86687 +-------- +Validate extension JSON: Error: Field 'classes/AnimationMixer/methods/_post_process_key_value/arguments/3': type changed value in new API, from "Object" to "int". + +Exposing the pointer was dangerous and it must be changed to avoid crash. Compatibility methods registered. + + +GH-84976 +-------- +Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/FinalAction/values/FINAL_ACTION_CONTINUE': value changed value in new API, from 2.0 to 0. +Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/FinalAction/values/FINAL_ACTION_MAX': value changed value in new API, from 3.0 to 2. +Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_CLEAR': value changed value in new API, from 0.0 to 1. +Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_CLEAR_REGION_CONTINUE': value changed value in new API, from 2.0 to 1. +Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_CONTINUE': value changed value in new API, from 5.0 to 0. +Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_DROP': value changed value in new API, from 4.0 to 2. +Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_KEEP': value changed value in new API, from 3.0 to 0. +Validate extension JSON: Error: Field 'classes/RenderingDevice/enums/InitialAction/values/INITIAL_ACTION_MAX': value changed value in new API, from 6.0 to 3. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/buffer_clear/arguments': size changed value in new API, from 4 to 3. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/buffer_update/arguments': size changed value in new API, from 5 to 4. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments': size changed value in new API, from 10 to 9. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/texture_clear/arguments': size changed value in new API, from 7 to 6. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/texture_copy/arguments': size changed value in new API, from 10 to 9. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/texture_resolve_multisample/arguments': size changed value in new API, from 3 to 2. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/texture_update/arguments': size changed value in new API, from 4 to 3. + +Barrier arguments have been removed from all relevant functions as they're no longer required. +Draw and compute list overlap no longer needs to be specified. +Initial and final actions have been simplified into fewer options. + + +GH-87115 +-------- +Validate extension JSON: Error: Field 'classes/TileMap/methods/get_collision_visibility_mode': is_const changed value in new API, from false to true. +Validate extension JSON: Error: Field 'classes/TileMap/methods/get_navigation_visibility_mode': is_const changed value in new API, from false to true. + +Two TileMap getters were made const. No adjustments should be necessary. diff --git a/misc/hooks/README.md b/misc/hooks/README.md index 0aaeff8ae3..573f8fe350 100644 --- a/misc/hooks/README.md +++ b/misc/hooks/README.md @@ -29,7 +29,7 @@ so they should work out of the box on Linux/macOS. ##### clang-format - Download LLVM for Windows (version 13 or later) from - <https://releases.llvm.org/download.html> + <https://github.com/llvm/llvm-project/releases> - Make sure LLVM is added to the `PATH` during installation ##### black diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format index fd0213c175..e5cf0c4aa2 100755 --- a/misc/hooks/pre-commit-clang-format +++ b/misc/hooks/pre-commit-clang-format @@ -80,7 +80,7 @@ fi # To get consistent formatting, we recommend contributors to use the same # clang-format version as CI. RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="13" -RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="15" +RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="16" if [ ! -x "$CLANG_FORMAT" ] ; then message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX." diff --git a/modules/SCsub b/modules/SCsub index fcc01e2c1b..7c9946170f 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -7,6 +7,9 @@ Import("env") env_modules = env.Clone() +# Allow modules to detect if they are being built as a module. +env_modules.Append(CPPDEFINES=["GODOT_MODULE"]) + Export("env_modules") # Header with MODULE_*_ENABLED defines. diff --git a/modules/basis_universal/register_types.cpp b/modules/basis_universal/register_types.cpp index 7c0bc4ac82..f538fc6676 100644 --- a/modules/basis_universal/register_types.cpp +++ b/modules/basis_universal/register_types.cpp @@ -221,7 +221,7 @@ static Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size imgfmt = Image::FORMAT_DXT5_RA_AS_RG; } else if (RS::get_singleton()->has_os_feature("etc2")) { format = basist::transcoder_texture_format::cTFETC2; // get this from renderer - imgfmt = Image::FORMAT_ETC2_RGBA8; + imgfmt = Image::FORMAT_ETC2_RA_AS_RG; } else { //opengl most likely, bad for normal maps, nothing to do about this. format = basist::transcoder_texture_format::cTFRGBA32; diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 6082b468f7..1de76c60b5 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -150,13 +150,13 @@ float CSGShape3D::get_snap() const { void CSGShape3D::_make_dirty(bool p_parent_removing) { if ((p_parent_removing || is_root_shape()) && !dirty) { - call_deferred(SNAME("_update_shape")); // Must be deferred; otherwise, is_root_shape() will use the previous parent + callable_mp(this, &CSGShape3D::_update_shape).call_deferred(); // Must be deferred; otherwise, is_root_shape() will use the previous parent. } if (!is_root_shape()) { parent_shape->_make_dirty(); } else if (!dirty) { - call_deferred(SNAME("_update_shape")); + callable_mp(this, &CSGShape3D::_update_shape).call_deferred(); } dirty = true; diff --git a/modules/gdscript/README.md b/modules/gdscript/README.md new file mode 100644 index 0000000000..30685e672c --- /dev/null +++ b/modules/gdscript/README.md @@ -0,0 +1,139 @@ +# Basic GDScript module architecture +This provides some basic information in how GDScript is implemented and integrates with the rest of the engine. You can learn more about GDScript in the [documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/index.html). It describes the syntax and user facing systems and concepts, and can be used as a reference for what user expectations are. + + +## General design + +GDScript is: + +1. A [gradually typed](https://en.wikipedia.org/wiki/Gradual_typing) language. Type hints are optional and help with static analysis and performance. However, typed code must easily interoperate with untyped code. +2. A tightly designed language. Features are added because they are _needed_, and not because they can be added or are interesting to develop. +3. Primarily an interpreted scripting language: it is compiled to GDScript byte code and interpreted in a GDScript virtual machine. It is meant to be easy to use and develop gameplay in. It is not meant for CPU-intensive algorithms or data processing, and is not optimized for it. For that, [C#](https://docs.godotengine.org/en/stable/tutorials/scripting/c_sharp/c_sharp_basics.html) or [GDExtension](https://docs.godotengine.org/en/stable/tutorials/scripting/gdextension/what_is_gdextension.html) may be used. + + +## Integration into Godot + +GDScript is integrated into Godot as a module. Since modules are optional, this means that Godot may be built without GDScript and work perfectly fine without it! + +The GDScript module interfaces with Godot's codebase by inheriting from the engine's scripting-related classes. New languages inherit from [`ScriptLanguage`](/core/object/script_language.h), and are registered in Godot's [`ScriptServer`](/core/object/script_language.h). Scripts, referring to a file containing code, are represented in the engine by the `Script` class. Instances of that script, which are used at runtime when actually executing the code, inherit from [`ScriptInstance`](/core/object/script_instance.h). + +To access Godot's internal classes, GDScript uses [`ClassDB`](/core/object/class_db.h). `ClassDB` is where Godot registers classes, methods and properties that it wants exposed to its scripting system. This is how GDScript understands that `Node2D` is a class it can use, and that it has a `get_parent()` method. + +[Built-in GDScript methods](https://docs.godotengine.org/en/latest/classes/class_@gdscript.html#methods) are defined and exported by [`GDScriptUtilityFunctions`](gdscript_utility_functions.h), whereas [global scope methods](https://docs.godotengine.org/en/latest/classes/class_%2540globalscope.html) are registered in [`Variant::_register_variant_utility_functions()`](/core/variant/variant_utility.cpp). + + +## Compilation + +Scripts can be at different stages of compilation. The process isn't entirely linear, but consists of this general order: tokenizing, parsing, analyzing, and finally compiling. This process is the same for scripts in the editor and scripts in an exported game. Scripts are stored as text files in both cases, and the compilation process must happen in full before the bytecode can be passed to the virtual machine and run. + +The main class of the GDScript module is the [`GDScript`](gdscript.h) class, which represents a class defined in GDScript. Each `.gd` file is called a _class file_ because it implicitly defines a class in GDScript, and thus results in an associated `GDScript` object. However, GDScript classes may define [_inner classes_](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#inner-classes), and those are also represented by further `GDScript` objects, even though they are not in files of their own. + +The `GDScript` class contains all the information related to the corresponding GDScript class: its name and path, its members like variables, functions, symbols, signals, implicit methods like initializers, etc. This is the main class that the compilation step deals with. + +A secondary class is `GDScriptInstance`, defined in the same file, containing _runtime_ information for an instance of a `GDScript`, and is more related to the execution of a script by the virtual machine. + + +### Loading source code + +This mostly happens by calling `GDScript::load_source_code()` on a `GDScript` object. Parsing only requires a `String`, so it is entirely possible to parse a script without a `GDScript` object! + + +### Tokenizing (see [`GDScriptTokenizer`](gdscript_tokenizer.h)) + +Tokenizing is the process of converting the source code `String` into a sequence of tokens, which represent language constructs (such as `for` or `if`), identifiers, literals, etc. This happens almost exclusively during the parsing process, which asks for the next token in order to make sense of the source code. The tokenizer is only used outside of the parsing process in very rare exceptions. + + +### Parsing (see [`GDScriptParser`](gdscript_parser.h)) + +The parser takes a sequence of tokens and builds [the abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of the GDScript program. The AST is used in the analyzing and compilation steps, and the source code `String` and sequence of tokens are discarded. The AST-building process finds syntax errors in a GDScript program and reports them to the user. + +The parser class also defines all the possible nodes of the AST as subtypes of `GDScriptParser::Node`, not to be confused with Godot's scene tree `Node`. For example, `GDScriptParser::IfNode` has two children nodes, one for the code in the `if` block, and one for the code in the `else` block. A `GDScriptParser::FunctionNode` contains children nodes for its name, parameters, return type, body, etc. The parser also defines typechecking data structures like `GDScriptParser::Datatype`. + +The parser was [intentionally designed](https://godotengine.org/article/gdscript-progress-report-writing-new-parser/#less-lookahead) with a look-ahead of a single token. This means that the parser only has access to the current token and the previous token (or, if you prefer, the current token and the next token). This parsing limitation ensures that GDScript will remain syntactically simple and accessible, and that the parsing process cannot become overly complex. + + +### Analysis and typechecking (see [`GDScriptAnalyzer`](gdscript_analyzer.h)) + +The analyzer takes in the AST of a program and verifies that "everything checks out". For example, when analyzing a method call with three parameters, it will check whether the function definition also contains three parameters. If the code is typed, it will check that argument and parameter types are compatible. + +There are two types of functions in the analyzer: `reduce` functions and `resolve` functions. Their parameters always include the AST node that they are attempting to reduce or resolve. +- The `reduce` functions work on GDScript expressions, which return values, and thus their main goal is to populate the `GDScriptParser::Datatype` of the underlying AST node. The datatype is then used to typecheck code that depends on this expression, and gives the compiler necessary information to generate appropriate, safe, and optimized bytecode. +For example, function calls are handled with `reduce_call()`, which must figure out what function is being called and check that the passed arguments match the function's parameters. The type of the underlying `CallNode` will be the return type of the function. +Another example is `reduce_identifier()`, which does _a lot_ of work: given the string of its `IdentifierNode`, it must figure out what that identifier refers to. It could be a local variable, class name, global or class function, function parameter, class or superclass member, or any number of other things. It has to check many different places to find this information! +A secondary goal of the `reduce` functions is to perform [constant folding](https://en.wikipedia.org/wiki/Constant_folding): to determine whether an expression is constant, and if it is, compute its _reduced value_ at this time so it does not need to be computed over and over at runtime! +- The resolve functions work on AST nodes that represent statements, and don't necessarily have values. Their goal is to do work related to program control flow, resolve their child AST nodes, deal with scoping, etc. One of the simplest examples is `resolve_if()`, which reduces the `if` condition, then resolves the `if` body and `else` body if it exists. +The `resolve_for()` function does more work than simply resolving its code block. With `for i in range(10)`, for example, it must also declare and type the new variable `i` within the scope of its code block, as well as make sure `range(10)` is iterable, among other things. +To understand classes and inheritance without introducing cyclic dependency problems that would come from immediate full class code analysis, the analyzer often asks only for class _interfaces_: it needs to know what member variables and methods exist as well as their types, but no more. +This is done through `resolve_class_interface()`, which populates `ClassNode`'s `Datatype` with that information. It first checks for superclass information with `resolve_class_inheritance()`, then populates its member information by calling `resolve_class_member()` on each member. Since this step is only about the class _interface_, methods are resolved with `resolve_function_signature()`, which gets all relevant typing information without resolving the function body! +The remaining steps of resolution, including member variable initialization code, method code, etc, can happen at a later time. + +In fully untyped code, very little static analysis is possible. For example, the analyzer cannot know whether `my_var.some_member` exists when it does not know the type of `my_var`. Therefore, it cannot emit a warning or error because `some_member` _could_ exist - or it could not. The analyzer must trust the programmer. If an error does occur, it will be at runtime. +However, GDScript is gradually typed, so all of these analyses must work when parts of the code are typed and others untyped. Static analysis in a gradually typed language is a best-effort situation: suppose there is a typed variable `var x : int`, and an untyped `var y = "some string"`. We can obviously tell this isn't going to work, but the analyzer will accept the assignment `x = y` without warnings or errors: it only knows that `y` is untyped and can therefore be anything, including the `int` that `x` expects. It must once again trust the programmer to have written code that works. In this instance, the code will error at runtime. +In both these cases, the analyzer handles the uncertainty of untyped code by calling `mark_node_unsafe()` on the respective AST node. This means it didn't have enough information to know whether the code was fully safe or necessarily wrong. Lines with unsafe AST nodes are represented by grey line numbers in the GDScript editor. Green line numbers indicate a line of code without any unsafe nodes. + +This analysis step is also where dependencies are introduced and that information stored for use later. If class `A` extends class `B` or contains a member with type `B` from some other script file, then the analyzer will attempt to load that second script. If `B` contains references to `A`, then a _cyclic_ dependency is introduced. This is OK in many cases, but impossible to resolve in others. + +Clearly, the analyzer is where a lot of the "magic" happens! It determines what constitutes proper code that can actually be compiled, and provides as many safety guarantees as possible with the typing information it is provided with. The more typed the code, the safer and more optimized it will be! + + +#### Cyclic dependencies and member resolution + +Cyclic dependencies from inheritance (`A extends B, B extends A`) are not supported in any programming language. Other cyclic dependencies are supported, such as `A extends B` and `B` uses, contains, or preloads, members of type `A`. + +To see why cyclic dependencies are complicated, suppose there is one between classes `A <-> B`. Partially through the analysis of `A`, we will need information about `B`, and therefore trigger its analysis. However, the analysis of `B` will eventually need information from `A`, which is incomplete because we never finished analyzing it. This would result in members not being found when they actually exist! + +GDScript supports cyclic dependencies due to a few features of the analyzer: + +1. Class interface resolution: when analyzing code of class `A` that depends on some other class `B`, we don't need to resolve the _code_ of `B` (its member initializers, function code, etc). We only need to know what members and methods the class has, as well as their types. These are the only things one class can use to work with, or _interface_ with, another. Because of inheritance, a class's interface depends on its superclass as well, so recursive interface resolution is needed. More details can be found in `GDScriptAnalyzer::resolve_class_interface()`. +2. Out of order member resolution: the analyzer may not even need an entire class interface to be resolved in order to figure out a specific type! For example, if class `A` contains code that references `B.is_alive`, then the analyzer doesn't need to immediately resolve `B`'s entire interface. It may simply check whether `is_alive` exists in `B`, and reduce it for its type information, on-demand. +A fundamental cyclic dependency problem occurs when the types of two different member variables are mutually dependent. This is commonly checked by a pattern that declares a temporary datatype with `GDScriptParser::DataType resolving_datatype;`, followed by `resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;`. If the analyzer attempts to resolve a member on-demand that is already tagged as resolving, then a cyclic dependency problem has been found and can be reported. + + +### Compiling (see [`GDScriptCompiler`](gdscript_compiler.h)) + +Compiling is the final step in making a GDScript executable in the [virtual machine](gdscript_vm.h) (VM). The compiler takes a `GDScript` object and an AST, and uses another class, [`GDScriptByteCodeGenerator`](gdscript_byte_codegen.h), to generate bytecode corresponding to the class. In doing this, it creates the objects that the VM understands how to run, like [`GDScriptFunction`](gdscript_function.h), and completes a few extra tasks needed for compilation, such as populating runtime class member information. + +Importantly, the compilation process of a class, specifically the `GDScriptCompiler::_compile_class()` method, _cannot_ depend on information obtained by calling `GDScriptCompiler::_compile_class()` on another class, for the same cyclic dependency reasons explained in the previous section. +Any information that can only be obtained or populated during the compilation step, when `GDScript` objects become available, must be handled before `GDScriptCompiler::_compile_class()` is called. This process is centralized in `GDScriptCompiler::_prepare_compilation()` which works as the compile-time equivalent of `GDScriptAnalyzer::resolve_class_interface()`: it populates a `GDScript`'s "interface" exclusively with information from the analysis step, and without processing other external classes. This information may then be referenced by other classes without introducing problematic cycles. + +The more typing information a GDScript has, the more optimized the compiled bytecode can be. For example, if `my_var` is untyped, the bytecode for `my_var.some_member` will need to go through several layers of indirection to figure out the type of `my_var` at runtime, and from there determine how to obtain `some_member`. This varies depending on whether `my_var` is a dictionary, a script, or a native class. If the type of `my_var` was known at compile time, the bytecode can directly call the type-specific method for obtaining a member. +Similar optimizations are possible for `my_var.some_func()`. With untyped GDScript, the VM will need to resolve `my_var`'s type at runtime, then, depending on the type, use different methods to resolve the function and call it. When the function is fully resolved during static analysis, native function pointers or GDScript function objects can be compiled into the bytecode and directly called by the VM, removing several layers of indirection. + +Typed code is safer code and faster code! + + +## Loading scripts + +GDScripts can be loaded in a couple of different ways. The main method, used almost everywhere in the engine, is to load scripts through the `ResourceLoader` singleton. In this way, GDScripts are resources like any others: `ResourceLoader::load()` will simply reroute to `ResourceFormatLoaderGDScript::load()`, found in `gdscript.h/cpp`(gdscript.h). This generates a GDScript object which is compiled and ready to use. + +The other method is to manually load the source code, then pass it to a parser, then to an analyzer and then to a compiler. The previous approach does this behind the scenes, alongside some smart caching of scripts and other functionalities. It is used in the [GDScript test runner infrastructure](tests/gdscript_test_runner.h). + + +### Full and shallow scripts + +The `ResourceFormatLoaderGDScript::load()` method simply calls `GDScriptCache::get_full_script()`. The [`GDScriptCache`](gdscript_cache.h) is, as it sounds, a cache for GDScripts. Its two main methods, `get_shallow_script()` and `get_full_script()`, get and cache, respectively, scripts that have been merely parsed, and scripts which have been statically analyzed and fully compiled. Another internal class, `GDScriptParserRef`, found in the same file, provides even more granularity over the different steps of the parsing process, and is used extensively in the analyzer. + +Shallow, or "just parsed" scripts, provide information such as defined classes, class members, and so forth. This is sufficient for many purposes, like obtaining a class interface or checking whether a member exists on a specific class. Full scripts, on the other hand, have been analyzed and compiled and are ready to use. + +The distinction between full and shallow scripts is very important, as shallow scripts cannot create cyclic dependency problems, whereas full scripts can. The analyzer, for example, never asks for full scripts. Choosing when to request a shallow vs a full script is an important but subtle decision. + +In practice, full scripts are simply scripts where `GDScript::reload()` has been called. This critical function is the primary way in which scripts get compiled in Godot, and essentially does all the compilation steps covered so far in order. Whenever a script is loaded, or updated and reloaded in Godot, it will end up going through `GDScript::reload()`, except in very rare circumstances like the test runner. It is an excellent place to start reading and understanding the GDScript module! + + +## Special types of scripts + +Certain types of GDScripts behave slightly differently. For example, autoloads are loaded with `ResourceLoader::load()` during `Main::start()`, very soon after Godot is launched. Many systems aren't initialized at that time, so error reporting is often significantly reduced and may not even show up in the editor. + +Tool scripts, declared with the `@tool` annotation on a GDScript file, run in the editor itself as opposed to just when the game is launched. This leads to a significant increase in complexity, as many things that can be changed in the editor may affect a currently executing tool script. + + +## Other + +There are many other classes in the GDScript module. Here is a brief overview of some of them: + +- Declaration of GDScript warnings in [`GDScriptWarning`](gdscript_warning.h). +- [`GDScriptFunction`](gdscript_function.h), which represents an executable GDScript function. The relevant file contains both static as well as runtime information. +- The [virtual machine](gdscript_vm.cpp) is essentially defined as calling `GDScriptFunction::call()`. +- Editor-related functions can be found in parts of `GDScriptLanguage`, originally declared in [`gdscript.h`](gdscript.h) but defined in [`gdscript_editor.cpp`](gdscript_editor.cpp). Code highlighting can be found in [`GDScriptSyntaxHighlighter`](editor/gdscript_highlighter.h). +- GDScript decompilation is found in [`gdscript_disassembler.cpp`](gdscript_disassembler.h), defined as `GDScriptFunction::disassemble()`. +- Documentation generation from GDScript comments in [`GDScriptDocGen`](editor/gdscript_docgen.h)
\ No newline at end of file diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index fcb7a11a14..933bfba5ba 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -148,7 +148,7 @@ <return type="int" /> <param index="0" name="var" type="Variant" /> <description> - Returns the length of the given Variant [param var]. The length can be the character count of a [String], the element count of any array type or the size of a [Dictionary]. For every other Variant type, a run-time error is generated and execution is stopped. + Returns the length of the given Variant [param var]. The length can be the character count of a [String] or [StringName], the element count of any array type, or the size of a [Dictionary]. For every other Variant type, a run-time error is generated and execution is stopped. [codeblock] a = [1, 2, 3, 4] len(a) # Returns 4 diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index a999acd1bd..920aa63fbe 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1381,51 +1381,43 @@ String GDScript::debug_get_script_name(const Ref<Script> &p_script) { } #endif -GDScript::UpdatableFuncPtr GDScript::func_ptrs_to_update_main_thread; -thread_local GDScript::UpdatableFuncPtr *GDScript::func_ptrs_to_update_thread_local = nullptr; - -GDScript::UpdatableFuncPtrElement GDScript::_add_func_ptr_to_update(GDScriptFunction **p_func_ptr_ptr) { - UpdatableFuncPtrElement result = {}; - - { - MutexLock lock(func_ptrs_to_update_thread_local->mutex); - result.element = func_ptrs_to_update_thread_local->ptrs.push_back(p_func_ptr_ptr); - result.func_ptr = func_ptrs_to_update_thread_local; - - if (likely(func_ptrs_to_update_thread_local->initialized)) { - return result; - } - - func_ptrs_to_update_thread_local->initialized = true; +GDScript::UpdatableFuncPtr::UpdatableFuncPtr(GDScriptFunction *p_function) { + if (p_function == nullptr) { + return; } - MutexLock lock(func_ptrs_to_update_mutex); - func_ptrs_to_update.push_back(func_ptrs_to_update_thread_local); - func_ptrs_to_update_thread_local->rc++; + ptr = p_function; + script = ptr->get_script(); + ERR_FAIL_NULL(script); - return result; -} - -void GDScript::_remove_func_ptr_to_update(const UpdatableFuncPtrElement &p_func_ptr_element) { - ERR_FAIL_NULL(p_func_ptr_element.element); - ERR_FAIL_NULL(p_func_ptr_element.func_ptr); - MutexLock lock(p_func_ptr_element.func_ptr->mutex); - p_func_ptr_element.element->erase(); + MutexLock script_lock(script->func_ptrs_to_update_mutex); + list_element = script->func_ptrs_to_update.push_back(this); } -void GDScript::_fixup_thread_function_bookkeeping() { - // Transfer the ownership of these update items to the main thread, - // because the current one is dying, leaving theirs orphan, dangling. +GDScript::UpdatableFuncPtr::~UpdatableFuncPtr() { + ERR_FAIL_NULL(script); - DEV_ASSERT(!Thread::is_main_thread()); + if (list_element) { + MutexLock script_lock(script->func_ptrs_to_update_mutex); + list_element->erase(); + list_element = nullptr; + } +} - MutexLock lock(func_ptrs_to_update_main_thread.mutex); - MutexLock lock2(func_ptrs_to_update_thread_local->mutex); +void GDScript::_recurse_replace_function_ptrs(const HashMap<GDScriptFunction *, GDScriptFunction *> &p_replacements) const { + MutexLock lock(func_ptrs_to_update_mutex); + for (UpdatableFuncPtr *updatable : func_ptrs_to_update) { + HashMap<GDScriptFunction *, GDScriptFunction *>::ConstIterator replacement = p_replacements.find(updatable->ptr); + if (replacement) { + updatable->ptr = replacement->value; + } else { + // Probably a lambda from another reload, ignore. + updatable->ptr = nullptr; + } + } - while (!func_ptrs_to_update_thread_local->ptrs.is_empty()) { - List<GDScriptFunction **>::Element *E = func_ptrs_to_update_thread_local->ptrs.front(); - E->transfer_to_back(&func_ptrs_to_update_main_thread.ptrs); - func_ptrs_to_update_thread_local->transferred = true; + for (HashMap<StringName, Ref<GDScript>>::ConstIterator subscript = subclasses.begin(); subscript; ++subscript) { + subscript->value->_recurse_replace_function_ptrs(p_replacements); } } @@ -1447,30 +1439,9 @@ void GDScript::clear(ClearData *p_clear_data) { } { - MutexLock outer_lock(func_ptrs_to_update_mutex); + MutexLock lock(func_ptrs_to_update_mutex); for (UpdatableFuncPtr *updatable : func_ptrs_to_update) { - bool destroy = false; - { - MutexLock inner_lock(updatable->mutex); - if (updatable->transferred) { - func_ptrs_to_update_main_thread.mutex.lock(); - } - for (GDScriptFunction **func_ptr_ptr : updatable->ptrs) { - *func_ptr_ptr = nullptr; - } - DEV_ASSERT(updatable->rc != 0); - updatable->rc--; - if (updatable->rc == 0) { - destroy = true; - } - if (updatable->transferred) { - func_ptrs_to_update_main_thread.mutex.unlock(); - } - } - if (destroy) { - DEV_ASSERT(updatable != &func_ptrs_to_update_main_thread); - memdelete(updatable); - } + updatable->ptr = nullptr; } } @@ -1543,6 +1514,13 @@ GDScript::~GDScript() { } destructing = true; + if (is_print_verbose_enabled()) { + MutexLock lock(func_ptrs_to_update_mutex); + if (!func_ptrs_to_update.is_empty()) { + print_line(vformat("GDScript: %d orphaned lambdas becoming invalid at destruction of script '%s'.", func_ptrs_to_update.size(), fully_qualified_name)); + } + } + clear(); { @@ -2091,33 +2069,6 @@ void GDScriptLanguage::remove_named_global_constant(const StringName &p_name) { named_globals.erase(p_name); } -void GDScriptLanguage::thread_enter() { - GDScript::func_ptrs_to_update_thread_local = memnew(GDScript::UpdatableFuncPtr); -} - -void GDScriptLanguage::thread_exit() { - // This thread may have been created before GDScript was up - // (which also means it can't have run any GDScript code at all). - if (!GDScript::func_ptrs_to_update_thread_local) { - return; - } - - GDScript::_fixup_thread_function_bookkeeping(); - - bool destroy = false; - { - MutexLock lock(GDScript::func_ptrs_to_update_thread_local->mutex); - DEV_ASSERT(GDScript::func_ptrs_to_update_thread_local->rc != 0); - GDScript::func_ptrs_to_update_thread_local->rc--; - if (GDScript::func_ptrs_to_update_thread_local->rc == 0) { - destroy = true; - } - } - if (destroy) { - memdelete(GDScript::func_ptrs_to_update_thread_local); - } -} - void GDScriptLanguage::init() { //populate global constants int gcc = CoreConstants::get_global_constant_count(); @@ -2150,8 +2101,6 @@ void GDScriptLanguage::init() { _add_global(E.name, E.ptr); } - GDScript::func_ptrs_to_update_thread_local = &GDScript::func_ptrs_to_update_main_thread; - #ifdef TESTS_ENABLED GDScriptTests::GDScriptTestRunner::handle_cmdline(); #endif @@ -2201,8 +2150,6 @@ void GDScriptLanguage::finish() { } script_list.clear(); function_list.clear(); - - DEV_ASSERT(GDScript::func_ptrs_to_update_main_thread.rc == 1); } void GDScriptLanguage::profiling_start() { @@ -2373,14 +2320,13 @@ struct GDScriptDepSort { void GDScriptLanguage::reload_all_scripts() { #ifdef DEBUG_ENABLED print_verbose("GDScript: Reloading all scripts"); - List<Ref<GDScript>> scripts; + Array scripts; { MutexLock lock(this->mutex); SelfList<GDScript> *elem = script_list.first(); while (elem) { - // Scripts will reload all subclasses, so only reload root scripts. - if (elem->self()->is_root_script() && elem->self()->get_path().is_resource_file()) { + if (elem->self()->get_path().is_resource_file()) { print_verbose("GDScript: Found: " + elem->self()->get_path()); scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident } @@ -2401,19 +2347,11 @@ void GDScriptLanguage::reload_all_scripts() { #endif } - //as scripts are going to be reloaded, must proceed without locking here - - scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order - - for (Ref<GDScript> &scr : scripts) { - print_verbose("GDScript: Reloading: " + scr->get_path()); - scr->load_source_code(scr->get_path()); - scr->reload(true); - } + reload_scripts(scripts, true); #endif } -void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { +void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload) { #ifdef DEBUG_ENABLED List<Ref<GDScript>> scripts; @@ -2439,7 +2377,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order for (Ref<GDScript> &scr : scripts) { - bool reload = scr == p_script || to_reload.has(scr->get_base()); + bool reload = p_scripts.has(scr) || to_reload.has(scr->get_base()); if (!reload) { continue; @@ -2462,7 +2400,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so } } -//same thing for placeholders + //same thing for placeholders #ifdef TOOLS_ENABLED while (scr->placeholders.size()) { @@ -2490,6 +2428,8 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so for (KeyValue<Ref<GDScript>, HashMap<ObjectID, List<Pair<StringName, Variant>>>> &E : to_reload) { Ref<GDScript> scr = E.key; + print_verbose("GDScript: Reloading: " + scr->get_path()); + scr->load_source_code(scr->get_path()); scr->reload(p_soft_reload); //restore state if saved @@ -2537,6 +2477,12 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so #endif } +void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { + Array scripts; + scripts.push_back(p_script); + reload_scripts(scripts, p_soft_reload); +} + void GDScriptLanguage::frame() { calls = 0; diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 31811bba47..2da9b89eb9 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -117,29 +117,28 @@ class GDScript : public Script { HashMap<GDScriptFunction *, LambdaInfo> lambda_info; - // List is used here because a ptr to elements are stored, so the memory locations need to be stable - struct UpdatableFuncPtr { - List<GDScriptFunction **> ptrs; - Mutex mutex; - bool initialized : 1; - bool transferred : 1; - uint32_t rc = 1; - UpdatableFuncPtr() : - initialized(false), transferred(false) {} - }; - struct UpdatableFuncPtrElement { - List<GDScriptFunction **>::Element *element = nullptr; - UpdatableFuncPtr *func_ptr = nullptr; +public: + class UpdatableFuncPtr { + friend class GDScript; + + GDScriptFunction *ptr = nullptr; + GDScript *script = nullptr; + List<UpdatableFuncPtr *>::Element *list_element = nullptr; + + public: + GDScriptFunction *operator->() const { return ptr; } + operator GDScriptFunction *() const { return ptr; } + + UpdatableFuncPtr(GDScriptFunction *p_function); + ~UpdatableFuncPtr(); }; - static UpdatableFuncPtr func_ptrs_to_update_main_thread; - static thread_local UpdatableFuncPtr *func_ptrs_to_update_thread_local; + +private: + // List is used here because a ptr to elements are stored, so the memory locations need to be stable List<UpdatableFuncPtr *> func_ptrs_to_update; Mutex func_ptrs_to_update_mutex; - UpdatableFuncPtrElement _add_func_ptr_to_update(GDScriptFunction **p_func_ptr_ptr); - static void _remove_func_ptr_to_update(const UpdatableFuncPtrElement &p_func_ptr_element); - - static void _fixup_thread_function_bookkeeping(); + void _recurse_replace_function_ptrs(const HashMap<GDScriptFunction *, GDScriptFunction *> &p_replacements) const; #ifdef TOOLS_ENABLED // For static data storage during hot-reloading. @@ -541,7 +540,7 @@ public: virtual void get_string_delimiters(List<String> *p_delimiters) const override; virtual bool is_using_templates() override; virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override; - virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override; + virtual Vector<ScriptTemplate> get_built_in_templates(const StringName &p_object) override; virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const override; virtual Script *create_script() const override; #ifndef DISABLE_DEPRECATED @@ -562,11 +561,6 @@ public: virtual void add_named_global_constant(const StringName &p_name, const Variant &p_value) override; virtual void remove_named_global_constant(const StringName &p_name) override; - /* MULTITHREAD FUNCTIONS */ - - virtual void thread_enter() override; - virtual void thread_exit() override; - /* DEBUGGER FUNCTIONS */ virtual String debug_get_error() const override; @@ -581,6 +575,7 @@ public: virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1) override; virtual void reload_all_scripts() override; + virtual void reload_scripts(const Array &p_scripts, bool p_soft_reload) override; virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) override; virtual void frame() override; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 5478a46bbc..7026d131e3 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -845,7 +845,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type return result; } -void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, StringName p_name, const GDScriptParser::Node *p_source) { +void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, const StringName &p_name, const GDScriptParser::Node *p_source) { ERR_FAIL_COND(!p_class->has_member(p_name)); resolve_class_member(p_class, p_class->members_indices[p_name], p_source); } @@ -3636,7 +3636,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod switch (base.builtin_type) { case Variant::NIL: { if (base.is_hard_type()) { - push_error(vformat(R"(Invalid get index "%s" on base Nil)", name), p_identifier); + push_error(vformat(R"(Cannot get property "%s" on a null object.)", name), p_identifier); } return; } @@ -3658,6 +3658,10 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod return; } } + if (Variant::has_builtin_method(base.builtin_type, name)) { + p_identifier->set_datatype(make_callable_type(Variant::get_builtin_method_info(base.builtin_type, name))); + return; + } if (base.is_hard_type()) { #ifdef SUGGEST_GODOT4_RENAMES String rename_hint = String(); @@ -4904,8 +4908,19 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo } result.builtin_type = p_property.type; if (p_property.type == Variant::OBJECT) { - result.kind = GDScriptParser::DataType::NATIVE; - result.native_type = p_property.class_name == StringName() ? SNAME("Object") : p_property.class_name; + if (ScriptServer::is_global_class(p_property.class_name)) { + result.kind = GDScriptParser::DataType::SCRIPT; + result.script_path = ScriptServer::get_global_class_path(p_property.class_name); + result.native_type = ScriptServer::get_global_class_native_base(p_property.class_name); + + Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(p_property.class_name)); + if (scr.is_valid()) { + result.script_type = scr; + } + } else { + result.kind = GDScriptParser::DataType::NATIVE; + result.native_type = p_property.class_name == StringName() ? "Object" : p_property.class_name; + } } else { result.kind = GDScriptParser::DataType::BUILTIN; result.builtin_type = p_property.type; diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index ec155706df..4ed476a3df 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -62,7 +62,7 @@ class GDScriptAnalyzer { void decide_suite_type(GDScriptParser::Node *p_suite, GDScriptParser::Node *p_statement); void resolve_annotation(GDScriptParser::AnnotationNode *p_annotation); - void resolve_class_member(GDScriptParser::ClassNode *p_class, StringName p_name, const GDScriptParser::Node *p_source = nullptr); + void resolve_class_member(GDScriptParser::ClassNode *p_class, const StringName &p_name, const GDScriptParser::Node *p_source = nullptr); void resolve_class_member(GDScriptParser::ClassNode *p_class, int p_index, const GDScriptParser::Node *p_source = nullptr); void resolve_class_interface(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source = nullptr); void resolve_class_interface(GDScriptParser::ClassNode *p_class, bool p_recursive); diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index 9bface6136..f902cb10cc 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -121,7 +121,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { RBMap<MethodBind *, int> method_bind_map; RBMap<GDScriptFunction *, int> lambdas_map; -#if DEBUG_ENABLED +#ifdef DEBUG_ENABLED // Keep method and property names for pointer and validated operations. // Used when disassembling the bytecode. Vector<String> operator_names; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 9560f670e6..f6633f8bf6 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -322,9 +322,13 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code if (member.type == GDScriptParser::ClassNode::Member::FUNCTION || member.type == GDScriptParser::ClassNode::Member::SIGNAL) { // Get like it was a property. GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here. - GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF); - gen->write_get_named(temp, identifier, self); + GDScriptCodeGenerator::Address base(GDScriptCodeGenerator::Address::SELF); + if (member.type == GDScriptParser::ClassNode::Member::FUNCTION && member.function->is_static) { + base = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CLASS); + } + + gen->write_get_named(temp, identifier, base); return temp; } } @@ -1371,7 +1375,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code return GDScriptCodeGenerator::Address(); } - main_script->lambda_info.insert(function, { lambda->captures.size(), lambda->use_self }); + codegen.script->lambda_info.insert(function, { lambda->captures.size(), lambda->use_self }); gen->write_lambda(result, function, captures, lambda->use_self); for (int i = 0; i < captures.size(); i++) { @@ -3046,7 +3050,7 @@ GDScriptCompiler::FunctionLambdaInfo GDScriptCompiler::_get_function_replacement FunctionLambdaInfo info; info.function = p_func; info.parent = p_parent_func; - info.script = p_parent_func; + info.script = p_func->get_script(); info.name = p_func->get_name(); info.line = p_func->_initial_line; info.index = p_index; @@ -3057,10 +3061,14 @@ GDScriptCompiler::FunctionLambdaInfo GDScriptCompiler::_get_function_replacement info.default_arg_count = p_func->_default_arg_count; info.sublambdas = _get_function_lambda_replacement_info(p_func, p_depth, p_parent_func); - GDScript::LambdaInfo *extra_info = main_script->lambda_info.getptr(p_func); + ERR_FAIL_NULL_V(info.script, info); + GDScript::LambdaInfo *extra_info = info.script->lambda_info.getptr(p_func); if (extra_info != nullptr) { info.capture_count = extra_info->capture_count; info.use_self = extra_info->use_self; + } else { + info.capture_count = 0; + info.use_self = false; } return info; @@ -3195,22 +3203,7 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri HashMap<GDScriptFunction *, GDScriptFunction *> func_ptr_replacements; _get_function_ptr_replacements(func_ptr_replacements, old_lambda_info, &new_lambda_info); - - { - MutexLock outer_lock(main_script->func_ptrs_to_update_mutex); - for (GDScript::UpdatableFuncPtr *updatable : main_script->func_ptrs_to_update) { - MutexLock inner_lock(updatable->mutex); - for (GDScriptFunction **func_ptr_ptr : updatable->ptrs) { - GDScriptFunction **replacement = func_ptr_replacements.getptr(*func_ptr_ptr); - if (replacement != nullptr) { - *func_ptr_ptr = *replacement; - } else { - // Probably a lambda from another reload, ignore. - *func_ptr_ptr = nullptr; - } - } - } - } + main_script->_recurse_replace_function_ptrs(func_ptr_replacements); if (has_static_data && !root->annotated_static_unload) { GDScriptCache::add_static_script(p_script); diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index fd6b22f527..0adbe1ed8e 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -45,19 +45,19 @@ class GDScriptCompiler { GDScript *main_script = nullptr; struct FunctionLambdaInfo { - GDScriptFunction *function; - GDScriptFunction *parent; - Ref<GDScript> script; + GDScriptFunction *function = nullptr; + GDScriptFunction *parent = nullptr; + GDScript *script = nullptr; StringName name; - int line; - int index; - int depth; + int line = 0; + int index = 0; + int depth = 0; //uint64_t code_hash; //int code_size; - int capture_count; - int use_self; - int arg_count; - int default_arg_count; + int capture_count = 0; + bool use_self = false; + int arg_count = 0; + int default_arg_count = 0; //Vector<GDScriptDataType> argument_types; //GDScriptDataType return_type; Vector<FunctionLambdaInfo> sublambdas; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 87617cafab..210e2c3898 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -104,7 +104,7 @@ Ref<Script> GDScriptLanguage::make_template(const String &p_template, const Stri return scr; } -Vector<ScriptLanguage::ScriptTemplate> GDScriptLanguage::get_built_in_templates(StringName p_object) { +Vector<ScriptLanguage::ScriptTemplate> GDScriptLanguage::get_built_in_templates(const StringName &p_object) { Vector<ScriptLanguage::ScriptTemplate> templates; #ifdef TOOLS_ENABLED for (int i = 0; i < TEMPLATES_ARRAY_SIZE; i++) { @@ -537,7 +537,7 @@ struct GDScriptCompletionIdentifier { // appears. For example, if you are completing code in a class that inherits Node2D, a property found on Node2D // will have a "better" (lower) location "score" than a property that is found on CanvasItem. -static int _get_property_location(StringName p_class, StringName p_property) { +static int _get_property_location(const StringName &p_class, const StringName &p_property) { if (!ClassDB::has_property(p_class, p_property)) { return ScriptLanguage::LOCATION_OTHER; } @@ -552,7 +552,7 @@ static int _get_property_location(StringName p_class, StringName p_property) { return depth | ScriptLanguage::LOCATION_PARENT_MASK; } -static int _get_constant_location(StringName p_class, StringName p_constant) { +static int _get_constant_location(const StringName &p_class, const StringName &p_constant) { if (!ClassDB::has_integer_constant(p_class, p_constant)) { return ScriptLanguage::LOCATION_OTHER; } @@ -567,7 +567,7 @@ static int _get_constant_location(StringName p_class, StringName p_constant) { return depth | ScriptLanguage::LOCATION_PARENT_MASK; } -static int _get_signal_location(StringName p_class, StringName p_signal) { +static int _get_signal_location(const StringName &p_class, const StringName &p_signal) { if (!ClassDB::has_signal(p_class, p_signal)) { return ScriptLanguage::LOCATION_OTHER; } @@ -582,7 +582,7 @@ static int _get_signal_location(StringName p_class, StringName p_signal) { return depth | ScriptLanguage::LOCATION_PARENT_MASK; } -static int _get_method_location(StringName p_class, StringName p_method) { +static int _get_method_location(const StringName &p_class, const StringName &p_method) { if (!ClassDB::has_method(p_class, p_method)) { return ScriptLanguage::LOCATION_OTHER; } @@ -597,7 +597,7 @@ static int _get_method_location(StringName p_class, StringName p_method) { return depth | ScriptLanguage::LOCATION_PARENT_MASK; } -static int _get_enum_constant_location(StringName p_class, StringName p_enum_constant) { +static int _get_enum_constant_location(const StringName &p_class, const StringName &p_enum_constant) { if (!ClassDB::get_integer_constant_enum(p_class, p_enum_constant)) { return ScriptLanguage::LOCATION_OTHER; } @@ -620,9 +620,9 @@ static String _trim_parent_class(const String &p_class, const String &p_base_cla } Vector<String> names = p_class.split(".", false, 1); if (names.size() == 2) { - String first = names[0]; - String rest = names[1]; + const String &first = names[0]; if (ClassDB::class_exists(p_base_class) && ClassDB::class_exists(first) && ClassDB::is_parent_class(p_base_class, first)) { + const String &rest = names[1]; return rest; } } @@ -1210,6 +1210,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base return; } + int location = ScriptLanguage::LOCATION_OTHER; + if (!p_only_functions) { List<PropertyInfo> members; if (p_base.value.get_type() != Variant::NIL) { @@ -1223,7 +1225,11 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base continue; } if (!String(E.name).contains("/")) { - ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER); + ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location); + if (base_type.kind == GDScriptParser::DataType::ENUM) { + // Sort enum members in their declaration order. + location += 1; + } if (GDScriptParser::theme_color_names.has(E.name)) { option.theme_color_name = GDScriptParser::theme_color_names[E.name]; } @@ -1239,7 +1245,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base // Enum types are static and cannot change, therefore we skip non-const dictionary methods. continue; } - ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); + ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); if (E.arguments.size()) { option.insert_text += "("; } else { @@ -1364,7 +1370,7 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context } } -static GDScriptCompletionIdentifier _type_from_variant(const Variant &p_value) { +static GDScriptCompletionIdentifier _type_from_variant(const Variant &p_value, GDScriptParser::CompletionContext &p_context) { GDScriptCompletionIdentifier ci; ci.value = p_value; ci.type.is_constant = true; @@ -1386,8 +1392,22 @@ static GDScriptCompletionIdentifier _type_from_variant(const Variant &p_value) { scr = obj->get_script(); } if (scr.is_valid()) { - ci.type.script_type = scr; + ci.type.script_path = scr->get_path(); + + if (scr->get_path().ends_with(".gd")) { + Error err; + Ref<GDScriptParserRef> parser = GDScriptCache::get_parser(scr->get_path(), GDScriptParserRef::INTERFACE_SOLVED, err); + if (err == OK) { + ci.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; + ci.type.class_type = parser->get_parser()->get_tree(); + ci.type.kind = GDScriptParser::DataType::CLASS; + p_context.dependent_parsers.push_back(parser); + return ci; + } + } + ci.type.kind = GDScriptParser::DataType::SCRIPT; + ci.type.script_type = scr; ci.type.native_type = scr->get_instance_base_type(); } else { ci.type.kind = GDScriptParser::DataType::NATIVE; @@ -1412,8 +1432,19 @@ static GDScriptCompletionIdentifier _type_from_property(const PropertyInfo &p_pr ci.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; ci.type.builtin_type = p_property.type; if (p_property.type == Variant::OBJECT) { - ci.type.kind = GDScriptParser::DataType::NATIVE; - ci.type.native_type = p_property.class_name == StringName() ? "Object" : p_property.class_name; + if (ScriptServer::is_global_class(p_property.class_name)) { + ci.type.kind = GDScriptParser::DataType::SCRIPT; + ci.type.script_path = ScriptServer::get_global_class_path(p_property.class_name); + ci.type.native_type = ScriptServer::get_global_class_native_base(p_property.class_name); + + Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(p_property.class_name)); + if (scr.is_valid()) { + ci.type.script_type = scr; + } + } else { + ci.type.kind = GDScriptParser::DataType::NATIVE; + ci.type.native_type = p_property.class_name == StringName() ? "Object" : p_property.class_name; + } } else { ci.type.kind = GDScriptParser::DataType::BUILTIN; } @@ -1475,7 +1506,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, if (p_expression->is_constant) { // Already has a value, so just use that. - r_type = _type_from_variant(p_expression->reduced_value); + r_type = _type_from_variant(p_expression->reduced_value, p_context); switch (p_expression->get_datatype().kind) { case GDScriptParser::DataType::ENUM: case GDScriptParser::DataType::CLASS: @@ -1489,16 +1520,13 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, switch (p_expression->type) { case GDScriptParser::Node::LITERAL: { const GDScriptParser::LiteralNode *literal = static_cast<const GDScriptParser::LiteralNode *>(p_expression); - r_type = _type_from_variant(literal->value); + r_type = _type_from_variant(literal->value, p_context); found = true; } break; case GDScriptParser::Node::SELF: { if (p_context.current_class) { - if (p_context.type != GDScriptParser::COMPLETION_SUPER_METHOD) { - r_type.type = p_context.current_class->get_datatype(); - } else { - r_type.type = p_context.current_class->base_type; - } + r_type.type = p_context.current_class->get_datatype(); + r_type.type.is_meta_type = false; found = true; } } break; @@ -1673,7 +1701,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, if (!which.is_empty()) { // Try singletons first if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(which)) { - r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[which]); + r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[which], p_context); found = true; } else { for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { @@ -1724,7 +1752,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, if (ce.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) { if (ret.get_type() != Variant::OBJECT || ret.operator Object *() != nullptr) { - r_type = _type_from_variant(ret); + r_type = _type_from_variant(ret, p_context); found = true; } } @@ -1752,7 +1780,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, if (base.value.get_type() == Variant::DICTIONARY && base.value.operator Dictionary().has(String(subscript->attribute->name))) { Variant value = base.value.operator Dictionary()[String(subscript->attribute->name)]; - r_type = _type_from_variant(value); + r_type = _type_from_variant(value, p_context); found = true; break; } @@ -1804,7 +1832,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, if (base.value.in(index.value)) { Variant value = base.value.get(index.value); - r_type = _type_from_variant(value); + r_type = _type_from_variant(value, p_context); found = true; break; } @@ -1859,7 +1887,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, bool valid = false; Variant res = base_val.get(index.value, &valid); if (valid) { - r_type = _type_from_variant(res); + r_type = _type_from_variant(res, p_context); r_type.value = Variant(); r_type.type.is_constant = false; found = true; @@ -1917,7 +1945,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, found = false; break; } - r_type = _type_from_variant(res); + r_type = _type_from_variant(res, p_context); if (!v1_use_value || !v2_use_value) { r_type.value = Variant(); r_type.type.is_constant = false; @@ -2152,7 +2180,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, } else { Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(p_identifier->name)); if (scr.is_valid()) { - r_type = _type_from_variant(scr); + r_type = _type_from_variant(scr, p_context); r_type.type.is_meta_type = true; return true; } @@ -2162,7 +2190,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, // Check global variables (including autoloads). if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(p_identifier->name)) { - r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[p_identifier->name]); + r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[p_identifier->name], p_context); return true; } @@ -2215,7 +2243,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & const GDScriptParser::ExpressionNode *init = member.variable->initializer; if (init->is_constant) { r_type.value = init->reduced_value; - r_type = _type_from_variant(init->reduced_value); + r_type = _type_from_variant(init->reduced_value, p_context); return true; } else if (init->start_line == p_context.current_line) { return false; @@ -2242,7 +2270,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & r_type.enumeration = member.m_enum->identifier->name; return true; case GDScriptParser::ClassNode::Member::ENUM_VALUE: - r_type = _type_from_variant(member.enum_value.value); + r_type = _type_from_variant(member.enum_value.value, p_context); return true; case GDScriptParser::ClassNode::Member::SIGNAL: r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; @@ -2278,7 +2306,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & HashMap<StringName, Variant> constants; scr->get_constants(&constants); if (constants.has(p_identifier)) { - r_type = _type_from_variant(constants[p_identifier]); + r_type = _type_from_variant(constants[p_identifier], p_context); return true; } @@ -2342,7 +2370,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & bool valid = false; Variant res = tmp.get(p_identifier, &valid); if (valid) { - r_type = _type_from_variant(res); + r_type = _type_from_variant(res, p_context); r_type.value = Variant(); r_type.type.is_constant = false; return true; @@ -3194,6 +3222,11 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c List<String> opts; p_owner->get_argument_options("get_node", 0, &opts); + bool for_unique_name = false; + if (completion_context.node != nullptr && completion_context.node->type == GDScriptParser::Node::GET_NODE && !static_cast<GDScriptParser::GetNodeNode *>(completion_context.node)->use_dollar) { + for_unique_name = true; + } + for (const String &E : opts) { r_forced = true; String opt = E.strip_edges(); @@ -3202,6 +3235,14 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c // or handle NodePaths which are valid identifiers and don't need quotes. opt = opt.unquote(); } + + if (for_unique_name) { + if (!opt.begins_with("%")) { + continue; + } + opt = opt.substr(1); + } + // The path needs quotes if it's not a valid identifier (with an exception // for "/" as path separator, which also doesn't require quotes). if (!opt.replace("/", "_").is_valid_identifier()) { @@ -3213,11 +3254,13 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c options.insert(option.display, option); } - // Get autoloads. - for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { - String path = "/root/" + E.key; - ScriptLanguage::CodeCompletionOption option(path.quote(quote_style), ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH); - options.insert(option.display, option); + if (!for_unique_name) { + // Get autoloads. + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { + String path = "/root/" + E.key; + ScriptLanguage::CodeCompletionOption option(path.quote(quote_style), ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH); + options.insert(option.display, option); + } } } } break; @@ -3561,7 +3604,8 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co case GDScriptParser::COMPLETION_ASSIGN: case GDScriptParser::COMPLETION_CALL_ARGUMENTS: case GDScriptParser::COMPLETION_IDENTIFIER: - case GDScriptParser::COMPLETION_PROPERTY_METHOD: { + case GDScriptParser::COMPLETION_PROPERTY_METHOD: + case GDScriptParser::COMPLETION_SUBSCRIPT: { GDScriptParser::DataType base_type; if (context.current_class) { if (context.type != GDScriptParser::COMPLETION_SUPER_METHOD) { diff --git a/modules/gdscript/gdscript_lambda_callable.cpp b/modules/gdscript/gdscript_lambda_callable.cpp index 547f5607d3..f6fa17c84f 100644 --- a/modules/gdscript/gdscript_lambda_callable.cpp +++ b/modules/gdscript/gdscript_lambda_callable.cpp @@ -139,20 +139,14 @@ void GDScriptLambdaCallable::call(const Variant **p_arguments, int p_argcount, V } } -GDScriptLambdaCallable::GDScriptLambdaCallable(Ref<GDScript> p_script, GDScriptFunction *p_function, const Vector<Variant> &p_captures) { +GDScriptLambdaCallable::GDScriptLambdaCallable(Ref<GDScript> p_script, GDScriptFunction *p_function, const Vector<Variant> &p_captures) : + function(p_function) { ERR_FAIL_NULL(p_script.ptr()); ERR_FAIL_NULL(p_function); script = p_script; - function = p_function; captures = p_captures; h = (uint32_t)hash_murmur3_one_64((uint64_t)this); - - updatable_func_ptr_element = p_script->_add_func_ptr_to_update(&function); -} - -GDScriptLambdaCallable::~GDScriptLambdaCallable() { - GDScript::_remove_func_ptr_to_update(updatable_func_ptr_element); } bool GDScriptLambdaSelfCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) { @@ -264,37 +258,23 @@ void GDScriptLambdaSelfCallable::call(const Variant **p_arguments, int p_argcoun } } -GDScriptLambdaSelfCallable::GDScriptLambdaSelfCallable(Ref<RefCounted> p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures) { +GDScriptLambdaSelfCallable::GDScriptLambdaSelfCallable(Ref<RefCounted> p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures) : + function(p_function) { ERR_FAIL_NULL(p_self.ptr()); ERR_FAIL_NULL(p_function); reference = p_self; object = p_self.ptr(); - function = p_function; captures = p_captures; h = (uint32_t)hash_murmur3_one_64((uint64_t)this); - - GDScript *gds = p_function->get_script(); - if (gds != nullptr) { - updatable_func_ptr_element = gds->_add_func_ptr_to_update(&function); - } } -GDScriptLambdaSelfCallable::GDScriptLambdaSelfCallable(Object *p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures) { +GDScriptLambdaSelfCallable::GDScriptLambdaSelfCallable(Object *p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures) : + function(p_function) { ERR_FAIL_NULL(p_self); ERR_FAIL_NULL(p_function); object = p_self; - function = p_function; captures = p_captures; h = (uint32_t)hash_murmur3_one_64((uint64_t)this); - - GDScript *gds = p_function->get_script(); - if (gds != nullptr) { - updatable_func_ptr_element = gds->_add_func_ptr_to_update(&function); - } -} - -GDScriptLambdaSelfCallable::~GDScriptLambdaSelfCallable() { - GDScript::_remove_func_ptr_to_update(updatable_func_ptr_element); } diff --git a/modules/gdscript/gdscript_lambda_callable.h b/modules/gdscript/gdscript_lambda_callable.h index ee7d547544..2c5d01aa16 100644 --- a/modules/gdscript/gdscript_lambda_callable.h +++ b/modules/gdscript/gdscript_lambda_callable.h @@ -42,10 +42,9 @@ class GDScriptFunction; class GDScriptInstance; class GDScriptLambdaCallable : public CallableCustom { - GDScriptFunction *function = nullptr; + GDScript::UpdatableFuncPtr function; Ref<GDScript> script; uint32_t h; - GDScript::UpdatableFuncPtrElement updatable_func_ptr_element; Vector<Variant> captures; @@ -62,17 +61,18 @@ public: StringName get_method() const override; void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; + GDScriptLambdaCallable(GDScriptLambdaCallable &) = delete; + GDScriptLambdaCallable(const GDScriptLambdaCallable &) = delete; GDScriptLambdaCallable(Ref<GDScript> p_script, GDScriptFunction *p_function, const Vector<Variant> &p_captures); - virtual ~GDScriptLambdaCallable(); + virtual ~GDScriptLambdaCallable() = default; }; // Lambda callable that references a particular object, so it can use `self` in the body. class GDScriptLambdaSelfCallable : public CallableCustom { - GDScriptFunction *function = nullptr; + GDScript::UpdatableFuncPtr function; Ref<RefCounted> reference; // For objects that are RefCounted, keep a reference. Object *object = nullptr; // For non RefCounted objects, use a direct pointer. uint32_t h; - GDScript::UpdatableFuncPtrElement updatable_func_ptr_element; Vector<Variant> captures; @@ -88,9 +88,11 @@ public: ObjectID get_object() const override; void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; + GDScriptLambdaSelfCallable(GDScriptLambdaSelfCallable &) = delete; + GDScriptLambdaSelfCallable(const GDScriptLambdaSelfCallable &) = delete; GDScriptLambdaSelfCallable(Ref<RefCounted> p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures); GDScriptLambdaSelfCallable(Object *p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures); - virtual ~GDScriptLambdaSelfCallable(); + virtual ~GDScriptLambdaSelfCallable() = default; }; #endif // GDSCRIPT_LAMBDA_CALLABLE_H diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index f3a4f2eaa6..a4a12f8bc4 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -629,7 +629,7 @@ GDScriptParser::ClassNode *GDScriptParser::find_class(const String &p_qualified_ // Starts at index 1 because index 0 was handled above. for (int i = 1; result != nullptr && i < class_names.size(); i++) { - String current_name = class_names[i]; + const String ¤t_name = class_names[i]; GDScriptParser::ClassNode *next = nullptr; if (result->has_member(current_name)) { GDScriptParser::ClassNode::Member member = result->get_member(current_name); @@ -1120,7 +1120,12 @@ void GDScriptParser::parse_property_getter(VariableNode *p_variable) { case VariableNode::PROP_INLINE: { FunctionNode *function = alloc_node<FunctionNode>(); - consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "get".)"); + if (match(GDScriptTokenizer::Token::PARENTHESIS_OPEN)) { + consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after "get(".)*"); + consume(GDScriptTokenizer::Token::COLON, R"*(Expected ":" after "get()".)*"); + } else { + consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" or "(" after "get".)"); + } IdentifierNode *identifier = alloc_node<IdentifierNode>(); complete_extents(identifier); @@ -1268,8 +1273,7 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum(bool p_is_static) { EnumNode *enum_node = alloc_node<EnumNode>(); bool named = false; - if (check(GDScriptTokenizer::Token::IDENTIFIER)) { - advance(); + if (match(GDScriptTokenizer::Token::IDENTIFIER)) { enum_node->identifier = parse_identifier(); named = true; } diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index 40c564c36b..f8cb460e40 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -194,9 +194,9 @@ struct GDScriptUtilityFunctionsDefinitions { // Calculate how many. int count = 0; if (incr > 0) { - count = ((to - from - 1) / incr) + 1; + count = Math::division_round_up(to - from, incr); } else { - count = ((from - to - 1) / -incr) + 1; + count = Math::division_round_up(from - to, -incr); } Error err = arr.resize(count); @@ -470,7 +470,8 @@ struct GDScriptUtilityFunctionsDefinitions { static inline void len(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(1); switch (p_args[0]->get_type()) { - case Variant::STRING: { + case Variant::STRING: + case Variant::STRING_NAME: { String d = *p_args[0]; *r_ret = d.length(); } break; diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 3abfc7f8e3..7b03ac74d6 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -873,8 +873,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GET_VARIANT_PTR(value, 2); bool valid; +#ifdef DEBUG_ENABLED + Variant::VariantSetError err_code; + dst->set(*index, *value, &valid, &err_code); +#else dst->set(*index, *value, &valid); - +#endif #ifdef DEBUG_ENABLED if (!valid) { Object *obj = dst->get_validated_object(); @@ -891,7 +895,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } else { v = "of type '" + _get_var_type(index) + "'"; } - err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'"; + err_text = "Invalid assignment of property or key " + v + " with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'."; + if (err_code == Variant::VariantSetError::SET_INDEXED_ERR) { + err_text = "Invalid assignment of index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'."; + } } OPCODE_BREAK; } @@ -922,7 +929,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } else { v = "of type '" + _get_var_type(index) + "'"; } - err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'"; + err_text = "Invalid assignment of property or key " + v + " with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'."; OPCODE_BREAK; } #endif @@ -972,7 +979,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a bool valid; #ifdef DEBUG_ENABLED // Allow better error message in cases where src and dst are the same stack position. - Variant ret = src->get(*index, &valid); + Variant::VariantGetError err_code; + Variant ret = src->get(*index, &valid, &err_code); #else *dst = src->get(*index, &valid); @@ -985,7 +993,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } else { v = "of type '" + _get_var_type(index) + "'"; } - err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "')."; + err_text = "Invalid access to property or key " + v + " on a base object of type '" + _get_var_type(src) + "'."; + if (err_code == Variant::VariantGetError::GET_INDEXED_ERR) { + err_text = "Invalid access of index " + v + " on a base object of type: '" + _get_var_type(src) + "'."; + } OPCODE_BREAK; } *dst = ret; @@ -1021,7 +1032,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } else { v = "of type '" + _get_var_type(key) + "'"; } - err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "')."; + err_text = "Invalid access to property or key " + v + " on a base object of type '" + _get_var_type(src) + "'."; OPCODE_BREAK; } *dst = ret; @@ -1086,7 +1097,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (read_only_property) { err_text = vformat(R"(Cannot set value into property "%s" (on base "%s") because it is read-only.)", String(*index), _get_var_type(dst)); } else { - err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'."; + err_text = "Invalid assignment of property or key '" + String(*index) + "' with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'."; } OPCODE_BREAK; } @@ -1131,7 +1142,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif #ifdef DEBUG_ENABLED if (!valid) { - err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "')."; + err_text = "Invalid access to property or key '" + index->operator String() + "' on a base object of type '" + _get_var_type(src) + "'."; OPCODE_BREAK; } *dst = ret; @@ -2473,7 +2484,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a Variant::construct(ret_type, retvalue, const_cast<const Variant **>(&r), 1, ce); } else { #ifdef DEBUG_ENABLED - err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)", Variant::get_type_name(r->get_type()), Variant::get_type_name(ret_type)); #endif // DEBUG_ENABLED @@ -2503,9 +2514,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (r->get_type() != Variant::ARRAY) { #ifdef DEBUG_ENABLED - err_text = vformat(R"(Trying to return a value of type "%s" where expected return type is "Array[%s]".)", - _get_var_type(r), _get_element_type(builtin_type, native_type, *script_type)); -#endif // DEBUG_ENABLED + err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "Array[%s]".)", + Variant::get_type_name(r->get_type()), Variant::get_type_name(builtin_type)); +#endif OPCODE_BREAK; } @@ -2536,7 +2547,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GD_ERR_BREAK(!nc); if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) { - err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)", Variant::get_type_name(r->get_type()), nc->get_name()); OPCODE_BREAK; } @@ -2554,7 +2565,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif // DEBUG_ENABLED if (ret_obj && !ClassDB::is_parent_class(ret_obj->get_class_name(), nc->get_name())) { #ifdef DEBUG_ENABLED - err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)", ret_obj->get_class_name(), nc->get_name()); #endif // DEBUG_ENABLED OPCODE_BREAK; @@ -2577,7 +2588,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) { #ifdef DEBUG_ENABLED - err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)", Variant::get_type_name(r->get_type()), GDScript::debug_get_script_name(Ref<Script>(base_type))); #endif // DEBUG_ENABLED OPCODE_BREAK; @@ -2599,7 +2610,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a ScriptInstance *ret_inst = ret_obj->get_script_instance(); if (!ret_inst) { #ifdef DEBUG_ENABLED - err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)", ret_obj->get_class_name(), GDScript::debug_get_script_name(Ref<GDScript>(base_type))); #endif // DEBUG_ENABLED OPCODE_BREAK; @@ -2618,7 +2629,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (!valid) { #ifdef DEBUG_ENABLED - err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)", + err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)", GDScript::debug_get_script_name(ret_obj->get_script_instance()->get_script()), GDScript::debug_get_script_name(Ref<GDScript>(base_type))); #endif // DEBUG_ENABLED OPCODE_BREAK; diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index 0b1371851b..e00b92b752 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -114,7 +114,7 @@ void GDScriptTextDocument::didSave(const Variant &p_param) { scr->update_exports(); ScriptEditor::get_singleton()->reload_scripts(true); ScriptEditor::get_singleton()->update_docs_from_script(scr); - ScriptEditor::get_singleton()->trigger_live_script_reload(); + ScriptEditor::get_singleton()->trigger_live_script_reload(scr->get_path()); } } @@ -456,7 +456,7 @@ Variant GDScriptTextDocument::declaration(const Dictionary &p_params) { id = "class_global:" + symbol->native_class + ":" + symbol->name; break; } - call_deferred(SNAME("show_native_symbol_in_editor"), id); + callable_mp(this, &GDScriptTextDocument::show_native_symbol_in_editor).call_deferred(id); } else { notify_client_show_symbol(symbol); } diff --git a/modules/gdscript/tests/README.md b/modules/gdscript/tests/README.md index 361d586d32..cea251bab5 100644 --- a/modules/gdscript/tests/README.md +++ b/modules/gdscript/tests/README.md @@ -6,3 +6,44 @@ and output files. See the [Integration tests for GDScript documentation](https://docs.godotengine.org/en/latest/contributing/development/core_and_modules/unit_testing.html#integration-tests-for-gdscript) for information about creating and running GDScript integration tests. + +# GDScript Autocompletion tests + +The `script/completion` folder contains test for the GDScript autocompletion. + +Each test case consists of at least one `.gd` file, which contains the code, and one `.cfg` file, which contains expected results and configuration. Inside of the GDScript file the character `➡` represents the cursor position, at which autocompletion is invoked. + +The config file contains two section: + +`[input]` contains keys that configure the test environment. The following keys are possible: + +- `cs: boolean = false`: If `true`, the test will be skipped when running a non C# build. +- `use_single_quotes: boolean = false`: Configures the corresponding editor setting for the test. +- `scene: String`: Allows to specify a scene which is opened while autocompletion is performed. If this is not set the test runner will search for a `.tscn` file with the same basename as the GDScript file. If that isn't found either, autocompletion will behave as if no scene was opened. + +`[output]` specifies the expected results for the test. The following key are supported: + +- `include: Array`: An unordered list of suggestions that should be in the result. Each entry is one dictionary with the following keys: `display`, `insert_text`, `kind`, `location`, which correspond to the suggestion struct which is used in the code. The runner only tests against specified keys, so in most cases `display` will suffice. +- `exclude: Array`: An array of suggestions which should not be in the result. The entries take the same form as for `include`. +- `call_hint: String`: The expected call hint returned by autocompletion. +- `forced: boolean`: Whether autocompletion is expected to force opening a completion window. + +Tests will only test against entries in `[output]` that were specified. + +## Writing autocompletion tests + +To avoid failing edge cases a certain behaviour needs to be tested multiple times. Some things that tests should account for: + +- All possible types: Test with all possible types that apply to the tested behaviour. (For the last points testing against `SCRIPT` and `CLASS` should suffice. `CLASS` can be obtained through C#, `SCRIPT` through GDScript. Relying on autoloads to be of type `SCRIPT` is not good, since this might change in the future.) + + - `BUILTIN` + - `NATIVE` + - GDScripts (with `class_name` as well as `preload`ed) + - C# (as standin for all other language bindings) (with `class_name` as well as `preload`ed) + - Autoloads + +- Possible contexts: the completion might be placed in different places of the program. e.g: + - initializers of class members + - directly inside a suite + - assignments inside a suite + - as parameter to a call diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index 361ca276bb..4d93a6fc18 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -266,7 +266,7 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) { while (!next.is_empty()) { if (dir->current_is_dir()) { - if (next == "." || next == "..") { + if (next == "." || next == ".." || next == "completion" || next == "lsp") { next = dir->get_next(); continue; } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.out index 73a54d7820..a6a3973255 100644 --- a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.out +++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.out @@ -3,4 +3,4 @@ GDTEST_RUNTIME_ERROR >> on function: test() >> analyzer/errors/outer_class_constants.gd >> 8 ->> Invalid get index 'OUTER_CONST' (on base: 'GDScript'). +>> Invalid access to property or key 'OUTER_CONST' on a base object of type 'GDScript'. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.out index 92e7b9316e..70fdc5b62c 100644 --- a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.out +++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.out @@ -3,4 +3,4 @@ GDTEST_RUNTIME_ERROR >> on function: test() >> analyzer/errors/outer_class_constants_as_variant.gd >> 9 ->> Invalid get index 'OUTER_CONST' (on base: 'GDScript'). +>> Invalid access to property or key 'OUTER_CONST' on a base object of type 'GDScript'. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.out index 892f8e2c3f..6632f056bd 100644 --- a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.out +++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.out @@ -3,4 +3,4 @@ GDTEST_RUNTIME_ERROR >> on function: test() >> analyzer/errors/outer_class_instance_constants.gd >> 8 ->> Invalid get index 'OUTER_CONST' (on base: 'RefCounted (Inner)'). +>> Invalid access to property or key 'OUTER_CONST' on a base object of type 'RefCounted (Inner)'. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.out index 8257e74f57..0459b756d1 100644 --- a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.out +++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.out @@ -3,4 +3,4 @@ GDTEST_RUNTIME_ERROR >> on function: test() >> analyzer/errors/outer_class_instance_constants_as_variant.gd >> 9 ->> Invalid get index 'OUTER_CONST' (on base: 'RefCounted (Inner)'). +>> Invalid access to property or key 'OUTER_CONST' on a base object of type 'RefCounted (Inner)'. diff --git a/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.cfg b/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.cfg new file mode 100644 index 0000000000..27e695d245 --- /dev/null +++ b/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.cfg @@ -0,0 +1,4 @@ +[output] +include=[ + {"display": "autoplay"}, +] diff --git a/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.gd b/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.gd new file mode 100644 index 0000000000..d41bbb970c --- /dev/null +++ b/modules/gdscript/tests/scripts/completion/get_node/get_node_member_annotated.gd @@ -0,0 +1,6 @@ +extends Node + +var test: AnimationPlayer = $AnimationPlayer + +func _ready(): + test.➡ diff --git a/modules/gdscript/tests/scripts/lsp/class.notest.gd b/modules/gdscript/tests/scripts/lsp/class.gd index 53d0b14d72..53d0b14d72 100644 --- a/modules/gdscript/tests/scripts/lsp/class.notest.gd +++ b/modules/gdscript/tests/scripts/lsp/class.gd diff --git a/modules/gdscript/tests/scripts/lsp/enums.notest.gd b/modules/gdscript/tests/scripts/lsp/enums.gd index 38b9ec110a..38b9ec110a 100644 --- a/modules/gdscript/tests/scripts/lsp/enums.notest.gd +++ b/modules/gdscript/tests/scripts/lsp/enums.gd diff --git a/modules/gdscript/tests/scripts/lsp/indentation.notest.gd b/modules/gdscript/tests/scripts/lsp/indentation.gd index c25d73a719..c25d73a719 100644 --- a/modules/gdscript/tests/scripts/lsp/indentation.notest.gd +++ b/modules/gdscript/tests/scripts/lsp/indentation.gd diff --git a/modules/gdscript/tests/scripts/lsp/lambdas.notest.gd b/modules/gdscript/tests/scripts/lsp/lambdas.gd index 6f5d468eea..6f5d468eea 100644 --- a/modules/gdscript/tests/scripts/lsp/lambdas.notest.gd +++ b/modules/gdscript/tests/scripts/lsp/lambdas.gd diff --git a/modules/gdscript/tests/scripts/lsp/local_variables.notest.gd b/modules/gdscript/tests/scripts/lsp/local_variables.gd index b6cc46f7da..b6cc46f7da 100644 --- a/modules/gdscript/tests/scripts/lsp/local_variables.notest.gd +++ b/modules/gdscript/tests/scripts/lsp/local_variables.gd diff --git a/modules/gdscript/tests/scripts/lsp/properties.notest.gd b/modules/gdscript/tests/scripts/lsp/properties.gd index 8dfaee2e5b..8dfaee2e5b 100644 --- a/modules/gdscript/tests/scripts/lsp/properties.notest.gd +++ b/modules/gdscript/tests/scripts/lsp/properties.gd diff --git a/modules/gdscript/tests/scripts/lsp/scopes.notest.gd b/modules/gdscript/tests/scripts/lsp/scopes.gd index 20b8fb9bd7..20b8fb9bd7 100644 --- a/modules/gdscript/tests/scripts/lsp/scopes.notest.gd +++ b/modules/gdscript/tests/scripts/lsp/scopes.gd diff --git a/modules/gdscript/tests/scripts/lsp/shadowing_initializer.notest.gd b/modules/gdscript/tests/scripts/lsp/shadowing_initializer.gd index 338000fa0e..338000fa0e 100644 --- a/modules/gdscript/tests/scripts/lsp/shadowing_initializer.notest.gd +++ b/modules/gdscript/tests/scripts/lsp/shadowing_initializer.gd diff --git a/modules/gdscript/tests/scripts/parser/features/property_setter_getter.gd b/modules/gdscript/tests/scripts/parser/features/property_setter_getter.gd index 9e4b360fb2..82616ee3cf 100644 --- a/modules/gdscript/tests/scripts/parser/features/property_setter_getter.gd +++ b/modules/gdscript/tests/scripts/parser/features/property_setter_getter.gd @@ -6,6 +6,9 @@ var property: set(value): _backing = value - 1000 +var property_2: + get(): # Allow parentheses. + return 123 func test(): print("Not using self:") @@ -35,3 +38,5 @@ func test(): self.property = 5000 print(self.property) print(self._backing) + + print(property_2) diff --git a/modules/gdscript/tests/scripts/parser/features/property_setter_getter.out b/modules/gdscript/tests/scripts/parser/features/property_setter_getter.out index 560e0c3bd7..23f98f44ab 100644 --- a/modules/gdscript/tests/scripts/parser/features/property_setter_getter.out +++ b/modules/gdscript/tests/scripts/parser/features/property_setter_getter.out @@ -17,3 +17,4 @@ Using self: -50 5000 4000 +123 diff --git a/modules/gdscript/tests/scripts/project.godot b/modules/gdscript/tests/scripts/project.godot index 25b49c0abd..c500ef443d 100644 --- a/modules/gdscript/tests/scripts/project.godot +++ b/modules/gdscript/tests/scripts/project.godot @@ -3,7 +3,7 @@ ; It also helps for opening Godot to edit the scripts, but please don't ; let the editor changes be saved. -config_version=4 +config_version=5 [application] diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.out b/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.out index 2a97eaea44..c524a1ae6b 100644 --- a/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.out +++ b/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.out @@ -3,4 +3,4 @@ GDTEST_RUNTIME_ERROR >> on function: test() >> runtime/errors/constant_array_is_deep.gd >> 6 ->> Invalid set index '0' (on base: 'Dictionary') with value of type 'int' +>> Invalid assignment of property or key '0' with value of type 'int' on a base object of type 'Dictionary'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.out b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.out index c807db6b0c..cf51b0262d 100644 --- a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.out +++ b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.out @@ -3,4 +3,4 @@ GDTEST_RUNTIME_ERROR >> on function: test() >> runtime/errors/constant_dictionary_is_deep.gd >> 6 ->> Invalid set index '0' (on base: 'Array') with value of type 'int' +>> Invalid assignment of index '0' (on base: 'Array') with value of type 'int'. diff --git a/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.gd b/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.gd new file mode 100644 index 0000000000..e4016c0119 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.gd @@ -0,0 +1,6 @@ +func test(): + var array: Array = [1, 2, 3] + print(array) + var callable: Callable = array.clear + callable.call() + print(array) diff --git a/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.out b/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.out new file mode 100644 index 0000000000..c4182b38e9 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.out @@ -0,0 +1,3 @@ +GDTEST_OK +[1, 2, 3] +[] diff --git a/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd b/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd index f6aa58737f..97e9da3b26 100644 --- a/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd +++ b/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd @@ -1,12 +1,18 @@ -# GH-79521 +# GH-79521, GH-86032 class_name TestStaticMethodAsCallable static func static_func() -> String: return "Test" +static func another_static_func(): + prints("another_static_func:", static_func.call(), static_func.is_valid()) + func test(): var a: Callable = TestStaticMethodAsCallable.static_func var b: Callable = static_func prints(a.call(), a.is_valid()) prints(b.call(), b.is_valid()) + @warning_ignore("static_called_on_instance") + another_static_func() + TestStaticMethodAsCallable.another_static_func() diff --git a/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out b/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out index e6d461b8f9..2b773ce8ee 100644 --- a/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out +++ b/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out @@ -1,3 +1,5 @@ GDTEST_OK Test true Test true +another_static_func: Test true +another_static_func: Test true diff --git a/modules/gdscript/tests/test_completion.h b/modules/gdscript/tests/test_completion.h new file mode 100644 index 0000000000..fd6b5321e6 --- /dev/null +++ b/modules/gdscript/tests/test_completion.h @@ -0,0 +1,203 @@ +/**************************************************************************/ +/* test_completion.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEST_COMPLETION_H +#define TEST_COMPLETION_H + +#ifdef TOOLS_ENABLED + +#include "core/io/config_file.h" +#include "core/io/dir_access.h" +#include "core/io/file_access.h" +#include "core/object/script_language.h" +#include "core/variant/dictionary.h" +#include "core/variant/variant.h" +#include "gdscript_test_runner.h" +#include "modules/modules_enabled.gen.h" // For mono. +#include "scene/resources/packed_scene.h" + +#include "../gdscript.h" +#include "tests/test_macros.h" + +#include "editor/editor_settings.h" +#include "scene/theme/theme_db.h" + +namespace GDScriptTests { + +static bool match_option(const Dictionary p_expected, const ScriptLanguage::CodeCompletionOption p_got) { + if (p_expected.get("display", p_got.display) != p_got.display) { + return false; + } + if (p_expected.get("insert_text", p_got.insert_text) != p_got.insert_text) { + return false; + } + if (p_expected.get("kind", p_got.kind) != Variant(p_got.kind)) { + return false; + } + if (p_expected.get("location", p_got.location) != Variant(p_got.location)) { + return false; + } + return true; +} + +static void to_dict_list(Variant p_variant, List<Dictionary> &p_list) { + ERR_FAIL_COND(!p_variant.is_array()); + + Array arr = p_variant; + for (int i = 0; i < arr.size(); i++) { + if (arr[i].get_type() == Variant::DICTIONARY) { + p_list.push_back(arr[i]); + } + } +} + +static void test_directory(const String &p_dir) { + Error err = OK; + Ref<DirAccess> dir = DirAccess::open(p_dir, &err); + + if (err != OK) { + FAIL("Invalid test directory."); + return; + } + + String path = dir->get_current_dir(); + + dir->list_dir_begin(); + String next = dir->get_next(); + + while (!next.is_empty()) { + if (dir->current_is_dir()) { + if (next == "." || next == "..") { + next = dir->get_next(); + continue; + } + test_directory(path.path_join(next)); + } else if (next.ends_with(".gd") && !next.ends_with(".notest.gd")) { + Ref<FileAccess> acc = FileAccess::open(path.path_join(next), FileAccess::READ, &err); + + if (err != OK) { + next = dir->get_next(); + continue; + } + + String code = acc->get_as_utf8_string(); + // For ease of reading ➡ (0x27A1) acts as sentinel char instead of 0xFFFF in the files. + code = code.replace_first(String::chr(0x27A1), String::chr(0xFFFF)); + // Require pointer sentinel char in scripts. + CHECK(code.find_char(0xFFFF) != -1); + + ConfigFile conf; + if (conf.load(path.path_join(next.get_basename() + ".cfg")) != OK) { + FAIL("No config file found."); + } + +#ifndef MODULE_MONO_ENABLED + if (conf.get_value("input", "cs", false)) { + next = dir->get_next(); + continue; + } +#endif + + EditorSettings::get_singleton()->set_setting("text_editor/completion/use_single_quotes", conf.get_value("input", "use_single_quotes", false)); + + List<Dictionary> include; + to_dict_list(conf.get_value("output", "include", Array()), include); + + List<Dictionary> exclude; + to_dict_list(conf.get_value("output", "exclude", Array()), exclude); + + List<ScriptLanguage::CodeCompletionOption> options; + String call_hint; + bool forced; + + Node *owner = nullptr; + if (conf.has_section_key("input", "scene")) { + Ref<PackedScene> scene = ResourceLoader::load(conf.get_value("input", "scene"), "PackedScene"); + if (scene.is_valid()) { + owner = scene->instantiate(); + } + } else if (dir->file_exists(next.get_basename() + ".tscn")) { + Ref<PackedScene> scene = ResourceLoader::load(path.path_join(next.get_basename() + ".tscn"), "PackedScene"); + if (scene.is_valid()) { + owner = scene->instantiate(); + } + } + + GDScriptLanguage::get_singleton()->complete_code(code, path.path_join(next), owner, &options, forced, call_hint); + String contains_excluded; + for (ScriptLanguage::CodeCompletionOption &option : options) { + for (const Dictionary &E : exclude) { + if (match_option(E, option)) { + contains_excluded = option.display; + break; + } + } + if (!contains_excluded.is_empty()) { + break; + } + + for (const Dictionary &E : include) { + if (match_option(E, option)) { + include.erase(E); + break; + } + } + } + CHECK_MESSAGE(contains_excluded.is_empty(), "Autocompletion suggests illegal option '", contains_excluded, "' for '", path.path_join(next), "'."); + CHECK(include.is_empty()); + + String expected_call_hint = conf.get_value("output", "call_hint", call_hint); + bool expected_forced = conf.get_value("output", "forced", forced); + + CHECK(expected_call_hint == call_hint); + CHECK(expected_forced == forced); + + if (owner) { + memdelete(owner); + } + } + next = dir->get_next(); + } +} + +TEST_SUITE("[Modules][GDScript][Completion]") { + TEST_CASE("[Editor] Check suggestion list") { + // Set all editor settings that code completion relies on. + EditorSettings::get_singleton()->set_setting("text_editor/completion/use_single_quotes", false); + init_language("modules/gdscript/tests/scripts"); + + test_directory("modules/gdscript/tests/scripts/completion"); + } +} +} // namespace GDScriptTests + +#endif + +#endif // TEST_COMPLETION_H diff --git a/modules/gdscript/tests/test_lsp.h b/modules/gdscript/tests/test_lsp.h index e57df00e2d..6192272f80 100644 --- a/modules/gdscript/tests/test_lsp.h +++ b/modules/gdscript/tests/test_lsp.h @@ -76,7 +76,7 @@ namespace GDScriptTests { // LSP GDScript test scripts are located inside project of other GDScript tests: // Cannot reset `ProjectSettings` (singleton) -> Cannot load another workspace and resources in there. // -> Reuse GDScript test project. LSP specific scripts are then placed inside `lsp` folder. -// Access via `res://lsp/my_script.notest.gd`. +// Access via `res://lsp/my_script.gd`. const String root = "modules/gdscript/tests/scripts/"; /* @@ -394,7 +394,7 @@ func f(): Ref<GDScriptWorkspace> workspace = GDScriptLanguageProtocol::get_singleton()->get_workspace(); { - String path = "res://lsp/local_variables.notest.gd"; + String path = "res://lsp/local_variables.gd"; assert_no_errors_in(path); String uri = workspace->get_file_uri(path); Vector<InlineTestData> all_test_data = read_tests(path); @@ -413,7 +413,7 @@ func f(): } SUBCASE("Can get correct ranges for indented variables") { - String path = "res://lsp/indentation.notest.gd"; + String path = "res://lsp/indentation.gd"; assert_no_errors_in(path); String uri = workspace->get_file_uri(path); Vector<InlineTestData> all_test_data = read_tests(path); @@ -421,7 +421,7 @@ func f(): } SUBCASE("Can get correct ranges for scopes") { - String path = "res://lsp/scopes.notest.gd"; + String path = "res://lsp/scopes.gd"; assert_no_errors_in(path); String uri = workspace->get_file_uri(path); Vector<InlineTestData> all_test_data = read_tests(path); @@ -429,7 +429,7 @@ func f(): } SUBCASE("Can get correct ranges for lambda") { - String path = "res://lsp/lambdas.notest.gd"; + String path = "res://lsp/lambdas.gd"; assert_no_errors_in(path); String uri = workspace->get_file_uri(path); Vector<InlineTestData> all_test_data = read_tests(path); @@ -437,7 +437,7 @@ func f(): } SUBCASE("Can get correct ranges for inner class") { - String path = "res://lsp/class.notest.gd"; + String path = "res://lsp/class.gd"; assert_no_errors_in(path); String uri = workspace->get_file_uri(path); Vector<InlineTestData> all_test_data = read_tests(path); @@ -445,7 +445,7 @@ func f(): } SUBCASE("Can get correct ranges for inner class") { - String path = "res://lsp/enums.notest.gd"; + String path = "res://lsp/enums.gd"; assert_no_errors_in(path); String uri = workspace->get_file_uri(path); Vector<InlineTestData> all_test_data = read_tests(path); @@ -453,7 +453,7 @@ func f(): } SUBCASE("Can get correct ranges for shadowing & shadowed variables") { - String path = "res://lsp/shadowing_initializer.notest.gd"; + String path = "res://lsp/shadowing_initializer.gd"; assert_no_errors_in(path); String uri = workspace->get_file_uri(path); Vector<InlineTestData> all_test_data = read_tests(path); @@ -461,7 +461,7 @@ func f(): } SUBCASE("Can get correct ranges for properties and getter/setter") { - String path = "res://lsp/properties.notest.gd"; + String path = "res://lsp/properties.gd"; assert_no_errors_in(path); String uri = workspace->get_file_uri(path); Vector<InlineTestData> all_test_data = read_tests(path); diff --git a/modules/glslang/config.py b/modules/glslang/config.py index d22f9454ed..1169776a73 100644 --- a/modules/glslang/config.py +++ b/modules/glslang/config.py @@ -1,5 +1,7 @@ def can_build(env, platform): - return True + # glslang is only needed when Vulkan or Direct3D 12-based renderers are available, + # as OpenGL doesn't use glslang. + return env["vulkan"] or env["d3d12"] def configure(env): diff --git a/modules/gltf/doc_classes/GLTFAccessor.xml b/modules/gltf/doc_classes/GLTFAccessor.xml index f678a11319..ba7323b7cd 100644 --- a/modules/gltf/doc_classes/GLTFAccessor.xml +++ b/modules/gltf/doc_classes/GLTFAccessor.xml @@ -1,14 +1,19 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GLTFAccessor" inherits="Resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> + Represents a GLTF accessor. </brief_description> <description> + GLTFAccessor is a data structure representing GLTF a [code]accessor[/code] that would be found in the [code]"accessors"[/code] array. A buffer is a blob of binary data. A buffer view is a slice of a buffer. An accessor is a typed interpretation of the data in a buffer view. + Most custom data stored in GLTF does not need accessors, only buffer views (see [GLTFBufferView]). Accessors are for more advanced use cases such as interleaved mesh data encoded for the GPU. </description> <tutorials> + <link title="Buffers, BufferViews, and Accessors in Khronos glTF specification">https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md</link> <link title="Runtime file loading and saving">$DOCS_URL/tutorials/io/runtime_file_loading_and_saving.html</link> </tutorials> <members> <member name="buffer_view" type="int" setter="set_buffer_view" getter="get_buffer_view" default="-1"> + The index of the buffer view this accessor is referencing. If [code]-1[/code], this accessor is not referencing any buffer view. </member> <member name="byte_offset" type="int" setter="set_byte_offset" getter="get_byte_offset" default="0"> </member> diff --git a/modules/gltf/doc_classes/GLTFBufferView.xml b/modules/gltf/doc_classes/GLTFBufferView.xml index d0f76a9af3..11d58bda72 100644 --- a/modules/gltf/doc_classes/GLTFBufferView.xml +++ b/modules/gltf/doc_classes/GLTFBufferView.xml @@ -1,22 +1,40 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GLTFBufferView" inherits="Resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> + Represents a GLTF buffer view. </brief_description> <description> + GLTFBufferView is a data structure representing GLTF a [code]bufferView[/code] that would be found in the [code]"bufferViews"[/code] array. A buffer is a blob of binary data. A buffer view is a slice of a buffer that can be used to identify and extract data from the buffer. + Most custom uses of buffers only need to use the [member buffer], [member byte_length], and [member byte_offset]. The [member byte_stride] and [member indices] properties are for more advanced use cases such as interleaved mesh data encoded for the GPU. </description> <tutorials> + <link title="Buffers, BufferViews, and Accessors in Khronos glTF specification">https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md</link> <link title="Runtime file loading and saving">$DOCS_URL/tutorials/io/runtime_file_loading_and_saving.html</link> </tutorials> + <methods> + <method name="load_buffer_view_data" qualifiers="const"> + <return type="PackedByteArray" /> + <param index="0" name="state" type="GLTFState" /> + <description> + Loads the buffer view data from the buffer referenced by this buffer view in the given [GLTFState]. Interleaved data with a byte stride is not yet supported by this method. The data is returned as a [PackedByteArray]. + </description> + </method> + </methods> <members> <member name="buffer" type="int" setter="set_buffer" getter="get_buffer" default="-1"> + The index of the buffer this buffer view is referencing. If [code]-1[/code], this buffer view is not referencing any buffer. </member> <member name="byte_length" type="int" setter="set_byte_length" getter="get_byte_length" default="0"> + The length, in bytes, of this buffer view. If [code]0[/code], this buffer view is empty. </member> <member name="byte_offset" type="int" setter="set_byte_offset" getter="get_byte_offset" default="0"> + The offset, in bytes, from the start of the buffer to the start of this buffer view. </member> <member name="byte_stride" type="int" setter="set_byte_stride" getter="get_byte_stride" default="-1"> + The stride, in bytes, between interleaved data. If [code]-1[/code], this buffer view is not interleaved. </member> <member name="indices" type="bool" setter="set_indices" getter="get_indices" default="false"> + True if the GLTFBufferView's OpenGL GPU buffer type is an [code]ELEMENT_ARRAY_BUFFER[/code] used for vertex indices (integer constant [code]34963[/code]). False if the buffer type is [code]ARRAY_BUFFER[/code] used for vertex attributes (integer constant [code]34962[/code]) or when any other value. See [url=https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_005_BuffersBufferViewsAccessors.md]Buffers, BufferViews, and Accessors[/url] for possible values. This property is set but never used, setting this property will do nothing. </member> </members> </class> diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml index f5066ba4f1..1b52a82298 100644 --- a/modules/gltf/doc_classes/GLTFDocument.xml +++ b/modules/gltf/doc_classes/GLTFDocument.xml @@ -84,7 +84,7 @@ <param index="1" name="path" type="String" /> <description> Takes a [GLTFState] object through the [param state] parameter and writes a glTF file to the filesystem. - [b]Note:[/b] The extension of the glTF file determines if it is a .glb binary file or a .gltf file. + [b]Note:[/b] The extension of the glTF file determines if it is a .glb binary file or a .gltf text file. </description> </method> </methods> diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml index aaa55e772a..0eabcb5022 100644 --- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml +++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml @@ -30,7 +30,7 @@ <param index="3" name="node" type="Node" /> <description> Part of the export process. This method is run after [method _get_saveable_image_formats] and before [method _export_post]. If this [GLTFDocumentExtension] is used for exporting images, this runs after [method _serialize_texture_json]. - This method can be used to modify the final JSON of each node. + This method can be used to modify the final JSON of each node. Data should be primarily stored in [param gltf_node] prior to serializing the JSON, but the original Godot [param node] is also provided if available. The node may be null if not available, such as when exporting GLTF data not generated from a Godot scene. </description> </method> <method name="_export_post" qualifiers="virtual"> @@ -114,7 +114,7 @@ <param index="0" name="state" type="GLTFState" /> <description> Part of the import process. This method is run after [method _parse_node_extensions] and before [method _generate_scene_node]. - This method can be used to modify any of the data imported so far, including any scene nodes, before running the final per-node import step. + This method can be used to modify any of the data imported so far after parsing, before generating the nodes and then running the final per-node import step. </description> </method> <method name="_import_preflight" qualifiers="virtual"> diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index e256041737..100750f400 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -20,6 +20,14 @@ Appends an extension to the list of extensions used by this GLTF file during serialization. If [param required] is true, the extension will also be added to the list of required extensions. Do not run this in [method GLTFDocumentExtension._export_post], as that stage is too late to add extensions. The final list is sorted alphabetically. </description> </method> + <method name="append_data_to_buffers"> + <return type="int" /> + <param index="0" name="data" type="PackedByteArray" /> + <param index="1" name="deduplication" type="bool" /> + <description> + Appends the given byte array data to the buffers and creates a [GLTFBufferView] for it. The index of the destination [GLTFBufferView] is returned. If [param deduplication] is true, the buffers will first be searched for duplicate data, otherwise new bytes will always be appended. + </description> + </method> <method name="get_accessors"> <return type="GLTFAccessor[]" /> <description> diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp index 83c7f463df..fee8156375 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp +++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp @@ -32,12 +32,14 @@ #ifdef TOOLS_ENABLED -#include "../gltf_document.h" +#include "editor_scene_exporter_gltf_settings.h" #include "editor/editor_file_system.h" +#include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/gui/editor_file_dialog.h" -#include "scene/gui/popup_menu.h" +#include "editor/import/3d/scene_import_settings.h" +#include "editor/themes/editor_scale.h" String SceneExporterGLTFPlugin::get_name() const { return "ConvertGLTF2"; @@ -48,59 +50,72 @@ bool SceneExporterGLTFPlugin::has_main_screen() const { } SceneExporterGLTFPlugin::SceneExporterGLTFPlugin() { - file_export_lib = memnew(EditorFileDialog); - EditorNode::get_singleton()->get_gui_base()->add_child(file_export_lib); - file_export_lib->connect("file_selected", callable_mp(this, &SceneExporterGLTFPlugin::_gltf2_dialog_action)); - file_export_lib->set_title(TTR("Export Library")); - file_export_lib->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); - file_export_lib->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - file_export_lib->clear_filters(); - file_export_lib->add_filter("*.glb"); - file_export_lib->add_filter("*.gltf"); - file_export_lib->set_title(TTR("Export Scene to glTF 2.0 File")); - + _gltf_document.instantiate(); + // Set up the file dialog. + _file_dialog = memnew(EditorFileDialog); + _file_dialog->connect("file_selected", callable_mp(this, &SceneExporterGLTFPlugin::_export_scene_as_gltf)); + _file_dialog->set_title(TTR("Export Library")); + _file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + _file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); + _file_dialog->clear_filters(); + _file_dialog->add_filter("*.glb"); + _file_dialog->add_filter("*.gltf"); + _file_dialog->set_title(TTR("Export Scene to glTF 2.0 File")); + EditorNode::get_singleton()->get_gui_base()->add_child(_file_dialog); + // Set up the export settings menu. + _export_settings.instantiate(); + _export_settings->generate_property_list(_gltf_document); + _settings_inspector = memnew(EditorInspector); + _settings_inspector->set_custom_minimum_size(Size2(350, 300) * EDSCALE); + _file_dialog->add_side_menu(_settings_inspector, TTR("Export Settings:")); + // Add a button to the Scene -> Export menu to pop up the settings dialog. PopupMenu *menu = get_export_as_menu(); int idx = menu->get_item_count(); menu->add_item(TTR("glTF 2.0 Scene...")); - menu->set_item_metadata(idx, callable_mp(this, &SceneExporterGLTFPlugin::convert_scene_to_gltf2)); + menu->set_item_metadata(idx, callable_mp(this, &SceneExporterGLTFPlugin::_popup_gltf_export_dialog)); +} + +void SceneExporterGLTFPlugin::_popup_gltf_export_dialog() { + Node *root = EditorNode::get_singleton()->get_tree()->get_edited_scene_root(); + if (!root) { + EditorNode::get_singleton()->show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); + return; + } + // Set the file dialog's file name to the scene name. + String filename = String(root->get_scene_file_path().get_file().get_basename()); + if (filename.is_empty()) { + filename = root->get_name(); + } + _file_dialog->set_current_file(filename + String(".gltf")); + // Generate and refresh the export settings. + _export_settings->generate_property_list(_gltf_document); + _settings_inspector->edit(nullptr); + _settings_inspector->edit(_export_settings.ptr()); + // Show the file dialog. + _file_dialog->popup_centered_ratio(); } -void SceneExporterGLTFPlugin::_gltf2_dialog_action(String p_file) { +void SceneExporterGLTFPlugin::_export_scene_as_gltf(const String &p_file_path) { Node *root = EditorNode::get_singleton()->get_tree()->get_edited_scene_root(); if (!root) { EditorNode::get_singleton()->show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); return; } List<String> deps; - Ref<GLTFDocument> doc; - doc.instantiate(); Ref<GLTFState> state; state.instantiate(); + state->set_copyright(_export_settings->get_copyright()); int32_t flags = 0; flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; - Error err = doc->append_from_scene(root, state, flags); + Error err = _gltf_document->append_from_scene(root, state, flags); if (err != OK) { ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err))); } - err = doc->write_to_filesystem(state, p_file); + err = _gltf_document->write_to_filesystem(state, p_file_path); if (err != OK) { ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err))); } EditorFileSystem::get_singleton()->scan_changes(); } -void SceneExporterGLTFPlugin::convert_scene_to_gltf2() { - Node *root = EditorNode::get_singleton()->get_tree()->get_edited_scene_root(); - if (!root) { - EditorNode::get_singleton()->show_accept(TTR("This operation can't be done without a scene."), TTR("OK")); - return; - } - String filename = String(root->get_scene_file_path().get_file().get_basename()); - if (filename.is_empty()) { - filename = root->get_name(); - } - file_export_lib->set_current_file(filename + String(".gltf")); - file_export_lib->popup_centered_ratio(); -} - #endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h index f92b3c5180..683ff6d4f6 100644 --- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h +++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h @@ -33,18 +33,23 @@ #ifdef TOOLS_ENABLED -#include "editor_scene_importer_gltf.h" +#include "../gltf_document.h" +#include "editor_scene_exporter_gltf_settings.h" #include "editor/editor_plugin.h" class EditorFileDialog; +class EditorInspector; class SceneExporterGLTFPlugin : public EditorPlugin { GDCLASS(SceneExporterGLTFPlugin, EditorPlugin); - EditorFileDialog *file_export_lib = nullptr; - void _gltf2_dialog_action(String p_file); - void convert_scene_to_gltf2(); + Ref<GLTFDocument> _gltf_document; + Ref<EditorSceneExporterGLTFSettings> _export_settings; + EditorInspector *_settings_inspector = nullptr; + EditorFileDialog *_file_dialog = nullptr; + void _popup_gltf_export_dialog(); + void _export_scene_as_gltf(const String &p_file_path); public: virtual String get_name() const override; diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp b/modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp new file mode 100644 index 0000000000..b0283b0c55 --- /dev/null +++ b/modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* editor_scene_exporter_gltf_settings.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "editor_scene_exporter_gltf_settings.h" + +const uint32_t PROP_EDITOR_SCRIPT_VAR = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE; + +bool EditorSceneExporterGLTFSettings::_set(const StringName &p_name, const Variant &p_value) { + String name_str = String(p_name); + if (name_str.contains("/")) { + return _set_extension_setting(name_str, p_value); + } + if (p_name == StringName("image_format")) { + _document->set_image_format(p_value); + emit_signal("property_list_changed"); + return true; + } + if (p_name == StringName("lossy_quality")) { + _document->set_lossy_quality(p_value); + return true; + } + if (p_name == StringName("root_node_mode")) { + _document->set_root_node_mode((GLTFDocument::RootNodeMode)(int64_t)p_value); + return true; + } + return false; +} + +bool EditorSceneExporterGLTFSettings::_get(const StringName &p_name, Variant &r_ret) const { + String name_str = String(p_name); + if (name_str.contains("/")) { + return _get_extension_setting(name_str, r_ret); + } + if (p_name == StringName("image_format")) { + r_ret = _document->get_image_format(); + return true; + } + if (p_name == StringName("lossy_quality")) { + r_ret = _document->get_lossy_quality(); + return true; + } + if (p_name == StringName("root_node_mode")) { + r_ret = _document->get_root_node_mode(); + return true; + } + return false; +} + +void EditorSceneExporterGLTFSettings::_get_property_list(List<PropertyInfo> *p_list) const { + for (PropertyInfo prop : _property_list) { + if (prop.name == "lossy_quality") { + String image_format = get("image_format"); + bool is_image_format_lossy = image_format == "JPEG" || image_format.findn("Lossy") != -1; + prop.usage = is_image_format_lossy ? PROPERTY_USAGE_DEFAULT : PROPERTY_USAGE_STORAGE; + } + p_list->push_back(prop); + } +} + +bool EditorSceneExporterGLTFSettings::_set_extension_setting(const String &p_name_str, const Variant &p_value) { + PackedStringArray split = String(p_name_str).split("/", true, 1); + if (!_config_name_to_extension_map.has(split[0])) { + return false; + } + Ref<GLTFDocumentExtension> extension = _config_name_to_extension_map[split[0]]; + bool valid; + extension->set(split[1], p_value, &valid); + return valid; +} + +bool EditorSceneExporterGLTFSettings::_get_extension_setting(const String &p_name_str, Variant &r_ret) const { + PackedStringArray split = String(p_name_str).split("/", true, 1); + if (!_config_name_to_extension_map.has(split[0])) { + return false; + } + Ref<GLTFDocumentExtension> extension = _config_name_to_extension_map[split[0]]; + bool valid; + r_ret = extension->get(split[1], &valid); + return valid; +} + +String get_friendly_config_prefix(Ref<GLTFDocumentExtension> p_extension) { + String config_prefix = p_extension->get_name(); + if (!config_prefix.is_empty()) { + return config_prefix; + } + const String class_name = p_extension->get_class_name(); + config_prefix = class_name.trim_prefix("GLTFDocumentExtension").capitalize(); + if (!config_prefix.is_empty()) { + return config_prefix; + } + PackedStringArray supported_extensions = p_extension->get_supported_extensions(); + if (supported_extensions.size() > 0) { + return supported_extensions[0]; + } + return "Unknown GLTFDocumentExtension"; +} + +// Run this before popping up the export settings, because the extensions may have changed. +void EditorSceneExporterGLTFSettings::generate_property_list(Ref<GLTFDocument> p_document) { + _property_list.clear(); + _document = p_document; + String image_format_hint_string = "None,PNG,JPEG"; + // Add properties from all document extensions. + for (Ref<GLTFDocumentExtension> &extension : GLTFDocument::get_all_gltf_document_extensions()) { + const String config_prefix = get_friendly_config_prefix(extension); + _config_name_to_extension_map[config_prefix] = extension; + // If the extension allows saving in different image formats, add to the enum. + PackedStringArray saveable_image_formats = extension->get_saveable_image_formats(); + for (int i = 0; i < saveable_image_formats.size(); i++) { + image_format_hint_string += "," + saveable_image_formats[i]; + } + // Look through the extension's properties and find the relevant ones. + List<PropertyInfo> ext_prop_list; + extension->get_property_list(&ext_prop_list); + for (const PropertyInfo &prop : ext_prop_list) { + // We only want properties that will show up in the exporter + // settings list. Exclude Resource's properties, as they are + // not relevant to the exporter. Include any user-defined script + // variables exposed to the editor (PROP_EDITOR_SCRIPT_VAR). + if ((prop.usage & PROP_EDITOR_SCRIPT_VAR) == PROP_EDITOR_SCRIPT_VAR) { + PropertyInfo ext_prop = prop; + ext_prop.name = config_prefix + "/" + prop.name; + _property_list.push_back(ext_prop); + } + } + } + // Add top-level properties (in addition to what _bind_methods registers). + PropertyInfo image_format_prop = PropertyInfo(Variant::STRING, "image_format", PROPERTY_HINT_ENUM, image_format_hint_string); + _property_list.push_back(image_format_prop); + PropertyInfo lossy_quality_prop = PropertyInfo(Variant::FLOAT, "lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"); + _property_list.push_back(lossy_quality_prop); + PropertyInfo root_node_mode_prop = PropertyInfo(Variant::INT, "root_node_mode", PROPERTY_HINT_ENUM, "Single Root,Keep Root,Multi Root"); + _property_list.push_back(root_node_mode_prop); +} + +String EditorSceneExporterGLTFSettings::get_copyright() const { + return _copyright; +} + +void EditorSceneExporterGLTFSettings::set_copyright(const String &p_copyright) { + _copyright = p_copyright; +} + +void EditorSceneExporterGLTFSettings::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_copyright"), &EditorSceneExporterGLTFSettings::get_copyright); + ClassDB::bind_method(D_METHOD("set_copyright", "copyright"), &EditorSceneExporterGLTFSettings::set_copyright); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "copyright", PROPERTY_HINT_PLACEHOLDER_TEXT, "Example: 2014 Godette"), "set_copyright", "get_copyright"); +} diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_settings.h b/modules/gltf/editor/editor_scene_exporter_gltf_settings.h new file mode 100644 index 0000000000..6032932367 --- /dev/null +++ b/modules/gltf/editor/editor_scene_exporter_gltf_settings.h @@ -0,0 +1,64 @@ +/**************************************************************************/ +/* editor_scene_exporter_gltf_settings.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef EDITOR_SCENE_EXPORTER_GLTF_SETTINGS_H +#define EDITOR_SCENE_EXPORTER_GLTF_SETTINGS_H + +#ifdef TOOLS_ENABLED + +#include "../gltf_document.h" + +class EditorSceneExporterGLTFSettings : public RefCounted { + GDCLASS(EditorSceneExporterGLTFSettings, RefCounted); + List<PropertyInfo> _property_list; + Ref<GLTFDocument> _document; + HashMap<String, Ref<GLTFDocumentExtension>> _config_name_to_extension_map; + + String _copyright; + +protected: + static void _bind_methods(); + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + + bool _set_extension_setting(const String &p_name_str, const Variant &p_value); + bool _get_extension_setting(const String &p_name_str, Variant &r_ret) const; + +public: + void generate_property_list(Ref<GLTFDocument> p_document); + + String get_copyright() const; + void set_copyright(const String &p_copyright); +}; + +#endif // TOOLS_ENABLED + +#endif // EDITOR_SCENE_EXPORTER_GLTF_SETTINGS_H diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 9587604e56..4636782063 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -38,10 +38,10 @@ #include "core/config/project_settings.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" #include "main/main.h" #include "scene/gui/line_edit.h" @@ -134,7 +134,19 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ // Get global paths for source and sink. // Escape paths to be valid Python strings to embed in the script. - const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path).c_escape(); + String source_global = ProjectSettings::get_singleton()->globalize_path(p_path); + +#ifdef WINDOWS_ENABLED + // On Windows, when using a network share path, the above will return a path starting with "//" + // which once handed to Blender will be treated like a relative path. So we need to replace the + // first two characters with "\\" to make it absolute again. + if (source_global.is_network_share_path()) { + source_global = "\\\\" + source_global.substr(2); + } +#endif + + source_global = source_global.c_escape(); + const String blend_basename = p_path.get_file().get_basename(); const String sink = ProjectSettings::get_singleton()->get_imported_files_path().path_join( vformat("%s-%s.gltf", blend_basename, p_path.md5_text())); diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index ec467db457..c1f4280170 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -34,7 +34,7 @@ #ifdef TOOLS_ENABLED #include "editor/editor_file_system.h" -#include "editor/import/resource_importer_scene.h" +#include "editor/import/3d/resource_importer_scene.h" class Animation; class Node; diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h index cc60830eac..86ee6568c9 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.h +++ b/modules/gltf/editor/editor_scene_importer_fbx.h @@ -35,7 +35,7 @@ #include "editor/editor_file_system.h" #include "editor/fbx_importer_manager.h" -#include "editor/import/resource_importer_scene.h" +#include "editor/import/3d/resource_importer_scene.h" class Animation; class Node; diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h index 7726c845bf..ec563bf525 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.h +++ b/modules/gltf/editor/editor_scene_importer_gltf.h @@ -33,7 +33,7 @@ #ifdef TOOLS_ENABLED -#include "editor/import/resource_importer_scene.h" +#include "editor/import/3d/resource_importer_scene.h" class Animation; class Node; diff --git a/modules/gltf/extensions/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp index 582bcf466b..9fdd6034a9 100644 --- a/modules/gltf/extensions/gltf_document_extension.cpp +++ b/modules/gltf/extensions/gltf_document_extension.cpp @@ -185,7 +185,6 @@ Error GLTFDocumentExtension::serialize_texture_json(Ref<GLTFState> p_state, Dict Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER); - ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER); Error err = OK; GDVIRTUAL_CALL(_export_node, p_state, p_gltf_node, r_dict, p_node, err); return err; diff --git a/modules/gltf/extensions/gltf_document_extension.h b/modules/gltf/extensions/gltf_document_extension.h index 512b7aba91..761dff725c 100644 --- a/modules/gltf/extensions/gltf_document_extension.h +++ b/modules/gltf/extensions/gltf_document_extension.h @@ -33,6 +33,8 @@ #include "../gltf_state.h" +#include "scene/3d/node_3d.h" + class GLTFDocumentExtension : public Resource { GDCLASS(GLTFDocumentExtension, Resource); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 4060f7f626..c840889f5e 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -405,6 +405,7 @@ static Vector<real_t> _xform_to_array(const Transform3D p_transform) { Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) { Array nodes; + const int scene_node_count = p_state->scene_nodes.size(); for (int i = 0; i < p_state->nodes.size(); i++) { Dictionary node; Ref<GLTFNode> gltf_node = p_state->nodes[i]; @@ -452,10 +453,13 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) { node["children"] = children; } + Node *scene_node = nullptr; + if (i < scene_node_count) { + scene_node = p_state->scene_nodes[i]; + } for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); - ERR_CONTINUE(!p_state->scene_nodes.find(i)); - Error err = ext->export_node(p_state, gltf_node, node, p_state->scene_nodes[i]); + Error err = ext->export_node(p_state, gltf_node, node, scene_node); ERR_CONTINUE(err != OK); } @@ -3218,7 +3222,7 @@ void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const Vector< bool must_import = true; Vector<uint8_t> img_data = p_image->get_data(); Dictionary generator_parameters; - String file_path = p_state->get_base_path() + "/" + p_state->filename.get_basename() + "_" + p_image->get_name(); + String file_path = p_state->get_base_path().path_join(p_state->filename.get_basename() + "_" + p_image->get_name()); file_path += p_file_extension.is_empty() ? ".png" : p_file_extension; if (FileAccess::exists(file_path + ".import")) { Ref<ConfigFile> config; @@ -3230,6 +3234,8 @@ void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const Vector< if (!generator_parameters.has("md5")) { must_import = false; // Didn't come from a gltf document; don't overwrite. } + } + if (must_import) { String existing_md5 = generator_parameters["md5"]; unsigned char md5_hash[16]; CryptoCore::md5(img_data.ptr(), img_data.size(), md5_hash); @@ -3658,141 +3664,143 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) { mr["metallicFactor"] = base_material->get_metallic(); mr["roughnessFactor"] = base_material->get_roughness(); - bool has_roughness = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid(); - bool has_ao = base_material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid(); - bool has_metalness = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid(); - if (has_ao || has_roughness || has_metalness) { - Dictionary mrt; - Ref<Texture2D> roughness_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS); - BaseMaterial3D::TextureChannel roughness_channel = base_material->get_roughness_texture_channel(); - Ref<Texture2D> metallic_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC); - BaseMaterial3D::TextureChannel metalness_channel = base_material->get_metallic_texture_channel(); - Ref<Texture2D> ao_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION); - BaseMaterial3D::TextureChannel ao_channel = base_material->get_ao_texture_channel(); - Ref<ImageTexture> orm_texture; - orm_texture.instantiate(); - Ref<Image> orm_image; - orm_image.instantiate(); - int32_t height = 0; - int32_t width = 0; - Ref<Image> ao_image; - if (has_ao) { - height = ao_texture->get_height(); - width = ao_texture->get_width(); - ao_image = ao_texture->get_image(); - Ref<ImageTexture> img_tex = ao_image; - if (img_tex.is_valid()) { - ao_image = img_tex->get_image(); - } - if (ao_image->is_compressed()) { - ao_image->decompress(); - } - } - Ref<Image> roughness_image; - if (has_roughness) { - height = roughness_texture->get_height(); - width = roughness_texture->get_width(); - roughness_image = roughness_texture->get_image(); - Ref<ImageTexture> img_tex = roughness_image; - if (img_tex.is_valid()) { - roughness_image = img_tex->get_image(); - } - if (roughness_image->is_compressed()) { - roughness_image->decompress(); - } - } - Ref<Image> metallness_image; - if (has_metalness) { - height = metallic_texture->get_height(); - width = metallic_texture->get_width(); - metallness_image = metallic_texture->get_image(); - Ref<ImageTexture> img_tex = metallness_image; - if (img_tex.is_valid()) { - metallness_image = img_tex->get_image(); - } - if (metallness_image->is_compressed()) { - metallness_image->decompress(); + if (_image_format != "None") { + bool has_roughness = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid(); + bool has_ao = base_material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid(); + bool has_metalness = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid(); + if (has_ao || has_roughness || has_metalness) { + Dictionary mrt; + Ref<Texture2D> roughness_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS); + BaseMaterial3D::TextureChannel roughness_channel = base_material->get_roughness_texture_channel(); + Ref<Texture2D> metallic_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC); + BaseMaterial3D::TextureChannel metalness_channel = base_material->get_metallic_texture_channel(); + Ref<Texture2D> ao_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION); + BaseMaterial3D::TextureChannel ao_channel = base_material->get_ao_texture_channel(); + Ref<ImageTexture> orm_texture; + orm_texture.instantiate(); + Ref<Image> orm_image; + orm_image.instantiate(); + int32_t height = 0; + int32_t width = 0; + Ref<Image> ao_image; + if (has_ao) { + height = ao_texture->get_height(); + width = ao_texture->get_width(); + ao_image = ao_texture->get_image(); + Ref<ImageTexture> img_tex = ao_image; + if (img_tex.is_valid()) { + ao_image = img_tex->get_image(); + } + if (ao_image->is_compressed()) { + ao_image->decompress(); + } } - } - Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO); - if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { - height = albedo_texture->get_height(); - width = albedo_texture->get_width(); - } - orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8); - if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) { - ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS); - } - if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) { - roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); - } - if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) { - metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); - } - for (int32_t h = 0; h < height; h++) { - for (int32_t w = 0; w < width; w++) { - Color c = Color(1.0f, 1.0f, 1.0f); - if (has_ao) { - if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) { - c.r = ao_image->get_pixel(w, h).r; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) { - c.r = ao_image->get_pixel(w, h).g; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) { - c.r = ao_image->get_pixel(w, h).b; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) { - c.r = ao_image->get_pixel(w, h).a; - } + Ref<Image> roughness_image; + if (has_roughness) { + height = roughness_texture->get_height(); + width = roughness_texture->get_width(); + roughness_image = roughness_texture->get_image(); + Ref<ImageTexture> img_tex = roughness_image; + if (img_tex.is_valid()) { + roughness_image = img_tex->get_image(); } - if (has_roughness) { - if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) { - c.g = roughness_image->get_pixel(w, h).r; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) { - c.g = roughness_image->get_pixel(w, h).g; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) { - c.g = roughness_image->get_pixel(w, h).b; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) { - c.g = roughness_image->get_pixel(w, h).a; - } + if (roughness_image->is_compressed()) { + roughness_image->decompress(); + } + } + Ref<Image> metallness_image; + if (has_metalness) { + height = metallic_texture->get_height(); + width = metallic_texture->get_width(); + metallness_image = metallic_texture->get_image(); + Ref<ImageTexture> img_tex = metallness_image; + if (img_tex.is_valid()) { + metallness_image = img_tex->get_image(); + } + if (metallness_image->is_compressed()) { + metallness_image->decompress(); } - if (has_metalness) { - if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) { - c.b = metallness_image->get_pixel(w, h).r; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) { - c.b = metallness_image->get_pixel(w, h).g; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) { - c.b = metallness_image->get_pixel(w, h).b; - } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) { - c.b = metallness_image->get_pixel(w, h).a; + } + Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO); + if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { + height = albedo_texture->get_height(); + width = albedo_texture->get_width(); + } + orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8); + if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) { + ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + } + if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) { + roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + } + if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) { + metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); + } + for (int32_t h = 0; h < height; h++) { + for (int32_t w = 0; w < width; w++) { + Color c = Color(1.0f, 1.0f, 1.0f); + if (has_ao) { + if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) { + c.r = ao_image->get_pixel(w, h).r; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) { + c.r = ao_image->get_pixel(w, h).g; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) { + c.r = ao_image->get_pixel(w, h).b; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) { + c.r = ao_image->get_pixel(w, h).a; + } + } + if (has_roughness) { + if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) { + c.g = roughness_image->get_pixel(w, h).r; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) { + c.g = roughness_image->get_pixel(w, h).g; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) { + c.g = roughness_image->get_pixel(w, h).b; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) { + c.g = roughness_image->get_pixel(w, h).a; + } } + if (has_metalness) { + if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) { + c.b = metallness_image->get_pixel(w, h).r; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) { + c.b = metallness_image->get_pixel(w, h).g; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) { + c.b = metallness_image->get_pixel(w, h).b; + } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) { + c.b = metallness_image->get_pixel(w, h).a; + } + } + orm_image->set_pixel(w, h, c); } - orm_image->set_pixel(w, h, c); } - } - orm_image->generate_mipmaps(); - orm_texture->set_image(orm_image); - GLTFTextureIndex orm_texture_index = -1; - if (has_ao || has_roughness || has_metalness) { - orm_texture->set_name(material->get_name() + "_orm"); - orm_texture_index = _set_texture(p_state, orm_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); - } - if (has_ao) { - Dictionary occt; - occt["index"] = orm_texture_index; - d["occlusionTexture"] = occt; - } - if (has_roughness || has_metalness) { - mrt["index"] = orm_texture_index; - Dictionary extensions = _serialize_texture_transform_uv1(material); - if (!extensions.is_empty()) { - mrt["extensions"] = extensions; - p_state->use_khr_texture_transform = true; + orm_image->generate_mipmaps(); + orm_texture->set_image(orm_image); + GLTFTextureIndex orm_texture_index = -1; + if (has_ao || has_roughness || has_metalness) { + orm_texture->set_name(material->get_name() + "_orm"); + orm_texture_index = _set_texture(p_state, orm_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); + } + if (has_ao) { + Dictionary occt; + occt["index"] = orm_texture_index; + d["occlusionTexture"] = occt; + } + if (has_roughness || has_metalness) { + mrt["index"] = orm_texture_index; + Dictionary extensions = _serialize_texture_transform_uv1(material); + if (!extensions.is_empty()) { + mrt["extensions"] = extensions; + p_state->use_khr_texture_transform = true; + } + mr["metallicRoughnessTexture"] = mrt; } - mr["metallicRoughnessTexture"] = mrt; } } d["pbrMetallicRoughness"] = mr; - if (base_material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING)) { + if (base_material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING) && _image_format != "None") { Dictionary nt; Ref<ImageTexture> tex; tex.instantiate(); @@ -3845,7 +3853,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) { d["emissiveFactor"] = arr; } - if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { + if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION) && _image_format != "None") { Dictionary et; Ref<Texture2D> emission_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_EMISSION); GLTFTextureIndex gltf_texture_index = -1; @@ -5045,7 +5053,7 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) { AnimationPlayer *animation_player = p_state->animation_players[player_i]; List<StringName> animations; animation_player->get_animation_list(&animations); - for (StringName animation_name : animations) { + for (const StringName &animation_name : animations) { _convert_animation(p_state, animation_player, animation_name); } } @@ -6151,9 +6159,9 @@ T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]); - const T from = p_values[idx * 3 + 1]; + const T &from = p_values[idx * 3 + 1]; const T c1 = from + p_values[idx * 3 + 2]; - const T to = p_values[idx * 3 + 4]; + const T &to = p_values[idx * 3 + 4]; const T c2 = to + p_values[idx * 3 + 3]; return interp.bezier(from, c1, c2, to, c); @@ -6284,6 +6292,9 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_ animation->add_track(Animation::TYPE_POSITION_3D); animation->track_set_path(position_idx, transform_node_path); animation->track_set_imported(position_idx, true); //helps merging later + if (track.position_track.interpolation == GLTFAnimation::INTERP_STEP) { + animation->track_set_interpolation_type(position_idx, Animation::InterpolationType::INTERPOLATION_NEAREST); + } base_idx++; } } @@ -6306,6 +6317,9 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_ animation->add_track(Animation::TYPE_ROTATION_3D); animation->track_set_path(rotation_idx, transform_node_path); animation->track_set_imported(rotation_idx, true); //helps merging later + if (track.rotation_track.interpolation == GLTFAnimation::INTERP_STEP) { + animation->track_set_interpolation_type(rotation_idx, Animation::InterpolationType::INTERPOLATION_NEAREST); + } base_idx++; } } @@ -6328,6 +6342,9 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_ animation->add_track(Animation::TYPE_SCALE_3D); animation->track_set_path(scale_idx, transform_node_path); animation->track_set_imported(scale_idx, true); //helps merging later + if (track.scale_track.interpolation == GLTFAnimation::INTERP_STEP) { + animation->track_set_interpolation_type(scale_idx, Animation::InterpolationType::INTERPOLATION_NEAREST); + } base_idx++; } } @@ -7052,9 +7069,9 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p } else if (String(final_track_path).contains(":")) { //Process skeleton const Vector<String> node_suffix = String(final_track_path).split(":"); - const String node = node_suffix[0]; + const String &node = node_suffix[0]; const NodePath node_path = node; - const String suffix = node_suffix[1]; + const String &suffix = node_suffix[1]; Node *godot_node = animation_base_node->get_node_or_null(node_path); if (!godot_node) { continue; @@ -7336,6 +7353,10 @@ void GLTFDocument::unregister_all_gltf_document_extensions() { all_document_extensions.clear(); } +Vector<Ref<GLTFDocumentExtension>> GLTFDocument::get_all_gltf_document_extensions() { + return all_document_extensions; +} + PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> p_state, Error *r_err) { Error err = _encode_buffer_glb(p_state, ""); if (r_err) { @@ -7454,11 +7475,13 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, boo ERR_CONTINUE(!E.value); for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); - ERR_CONTINUE(!p_state->json.has("nodes")); - Array nodes = p_state->json["nodes"]; - ERR_CONTINUE(E.key >= nodes.size()); - ERR_CONTINUE(E.key < 0); - Dictionary node_json = nodes[E.key]; + Dictionary node_json; + if (p_state->json.has("nodes")) { + Array nodes = p_state->json["nodes"]; + if (0 <= E.key && E.key < nodes.size()) { + node_json = nodes[E.key]; + } + } Ref<GLTFNode> gltf_node = p_state->nodes[E.key]; err = ext->import_node(p_state, gltf_node, node_json, E.value); ERR_CONTINUE(err != OK); diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 7e378fe94d..f321bb7111 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -86,6 +86,7 @@ public: static void register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority = false); static void unregister_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension); static void unregister_all_gltf_document_extensions(); + static Vector<Ref<GLTFDocumentExtension>> get_all_gltf_document_extensions(); void set_naming_version(int p_version); int get_naming_version() const; diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 766fe41257..0c47d5777c 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -34,6 +34,8 @@ void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("add_used_extension", "extension_name", "required"), &GLTFState::add_used_extension); + ClassDB::bind_method(D_METHOD("append_data_to_buffers", "data", "deduplication"), &GLTFState::append_data_to_buffers); + ClassDB::bind_method(D_METHOD("get_json"), &GLTFState::get_json); ClassDB::bind_method(D_METHOD("set_json", "json"), &GLTFState::set_json); ClassDB::bind_method(D_METHOD("get_major_version"), &GLTFState::get_major_version); @@ -399,3 +401,29 @@ Variant GLTFState::get_additional_data(const StringName &p_extension_name) { void GLTFState::set_additional_data(const StringName &p_extension_name, Variant p_additional_data) { additional_data[p_extension_name] = p_additional_data; } + +GLTFBufferViewIndex GLTFState::append_data_to_buffers(const Vector<uint8_t> &p_data, const bool p_deduplication = false) { + if (p_deduplication) { + for (int i = 0; i < buffer_views.size(); i++) { + Ref<GLTFBufferView> buffer_view = buffer_views[i]; + Vector<uint8_t> buffer_view_data = buffer_view->load_buffer_view_data(this); + if (buffer_view_data == p_data) { + return i; + } + } + } + // Append the given data to a buffer and create a buffer view for it. + if (unlikely(buffers.is_empty())) { + buffers.push_back(Vector<uint8_t>()); + } + Vector<uint8_t> &destination_buffer = buffers.write[0]; + Ref<GLTFBufferView> buffer_view; + buffer_view.instantiate(); + buffer_view->set_buffer(0); + buffer_view->set_byte_offset(destination_buffer.size()); + buffer_view->set_byte_length(p_data.size()); + destination_buffer.append_array(p_data); + const int new_index = buffer_views.size(); + buffer_views.push_back(buffer_view); + return new_index; +} diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 1ed8ce3629..3edf9a722f 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -105,6 +105,7 @@ protected: public: void add_used_extension(const String &p_extension, bool p_required = false); + GLTFBufferViewIndex append_data_to_buffers(const Vector<uint8_t> &p_data, const bool p_deduplication); enum GLTFHandleBinary { HANDLE_BINARY_DISCARD_TEXTURES = 0, diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index 0bf02cf890..94c9d66f78 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -118,6 +118,7 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(GLTFTexture); GDREGISTER_CLASS(GLTFTextureSampler); // Register GLTFDocumentExtension classes with GLTFDocument. + // Ensure physics is first in this list so that physics nodes are created before other nodes. GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionPhysics); GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionTextureKTX); GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionTextureWebP); diff --git a/modules/gltf/structures/gltf_buffer_view.cpp b/modules/gltf/structures/gltf_buffer_view.cpp index 7678f23f57..d40ed69915 100644 --- a/modules/gltf/structures/gltf_buffer_view.cpp +++ b/modules/gltf/structures/gltf_buffer_view.cpp @@ -30,7 +30,11 @@ #include "gltf_buffer_view.h" +#include "../gltf_state.h" + void GLTFBufferView::_bind_methods() { + ClassDB::bind_method(D_METHOD("load_buffer_view_data", "state"), &GLTFBufferView::load_buffer_view_data); + ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer); ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &GLTFBufferView::set_buffer); ClassDB::bind_method(D_METHOD("get_byte_offset"), &GLTFBufferView::get_byte_offset); @@ -88,3 +92,12 @@ bool GLTFBufferView::get_indices() { void GLTFBufferView::set_indices(bool p_indices) { indices = p_indices; } + +Vector<uint8_t> GLTFBufferView::load_buffer_view_data(const Ref<GLTFState> p_state) const { + ERR_FAIL_COND_V_MSG(byte_stride > 0, Vector<uint8_t>(), "Buffer views with byte stride are not yet supported by this method."); + const TypedArray<Vector<uint8_t>> &buffers = p_state->get_buffers(); + ERR_FAIL_INDEX_V(buffer, buffers.size(), Vector<uint8_t>()); + const PackedByteArray &buffer_data = buffers[buffer]; + const int64_t byte_end = byte_offset + byte_length; + return buffer_data.slice(byte_offset, byte_end); +} diff --git a/modules/gltf/structures/gltf_buffer_view.h b/modules/gltf/structures/gltf_buffer_view.h index 6d138dbf11..e4b7168130 100644 --- a/modules/gltf/structures/gltf_buffer_view.h +++ b/modules/gltf/structures/gltf_buffer_view.h @@ -64,7 +64,8 @@ public: bool get_indices(); void set_indices(bool p_indices); - // matrices need to be transformed to this + + Vector<uint8_t> load_buffer_view_data(const Ref<GLTFState> p_state) const; }; #endif // GLTF_BUFFER_VIEW_H diff --git a/modules/gltf/structures/gltf_skeleton.h b/modules/gltf/structures/gltf_skeleton.h index 72a4a06e5c..b2f2dcb2a2 100644 --- a/modules/gltf/structures/gltf_skeleton.h +++ b/modules/gltf/structures/gltf_skeleton.h @@ -82,7 +82,7 @@ public: //RBMap<int32_t, GLTFNodeIndex> get_godot_bone_node() { // return this->godot_bone_node; //} - //void set_godot_bone_node(RBMap<int32_t, GLTFNodeIndex> p_godot_bone_node) { + //void set_godot_bone_node(const RBMap<int32_t, GLTFNodeIndex> &p_godot_bone_node) { // this->godot_bone_node = p_godot_bone_node; //} Dictionary get_godot_bone_node(); diff --git a/modules/gltf/structures/gltf_skin.h b/modules/gltf/structures/gltf_skin.h index 164cabfe12..cd5f2d9ca2 100644 --- a/modules/gltf/structures/gltf_skin.h +++ b/modules/gltf/structures/gltf_skin.h @@ -34,6 +34,7 @@ #include "../gltf_defines.h" #include "core/io/resource.h" +#include "scene/resources/skin.h" template <typename T> class TypedArray; diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index f7c01ff840..b8902694c9 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -36,11 +36,11 @@ #include "core/input/input.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/node_3d_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "scene/3d/camera_3d.h" #include "scene/gui/dialogs.h" #include "scene/gui/label.h" @@ -1316,6 +1316,7 @@ GridMapEditor::GridMapEditor() { EDITOR_DEF("editors/grid_map/preview_size", 64); mesh_library_palette = memnew(ItemList); + mesh_library_palette->set_auto_translate(false); add_child(mesh_library_palette); mesh_library_palette->set_v_size_flags(SIZE_EXPAND_FILL); mesh_library_palette->connect("gui_input", callable_mp(this, &GridMapEditor::_mesh_library_palette_input)); diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 6f493f48e3..e3475b3959 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -32,7 +32,6 @@ #include "core/core_string_names.h" #include "core/io/marshalls.h" -#include "core/object/message_queue.h" #include "scene/3d/light_3d.h" #include "scene/resources/mesh_library.h" #include "scene/resources/physics_material.h" @@ -975,7 +974,7 @@ void GridMap::_queue_octants_dirty() { return; } - MessageQueue::get_singleton()->push_call(this, "_update_octants_callback"); + callable_mp(this, &GridMap::_update_octants_callback).call_deferred(); awaiting_update = true; } @@ -1082,7 +1081,6 @@ void GridMap::_bind_methods() { ClassDB::bind_method(D_METHOD("local_to_map", "local_position"), &GridMap::local_to_map); ClassDB::bind_method(D_METHOD("map_to_local", "map_position"), &GridMap::map_to_local); - ClassDB::bind_method(D_METHOD("_update_octants_callback"), &GridMap::_update_octants_callback); #ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &GridMap::resource_changed); #endif diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp index e7fa909706..ada0cd01fa 100644 --- a/modules/jpg/image_loader_jpegd.cpp +++ b/modules/jpg/image_loader_jpegd.cpp @@ -162,6 +162,7 @@ static Error _jpgd_save_to_output_stream(jpge::output_stream *p_output_stream, c ERR_FAIL_COND_V_MSG(error != OK, error, "Couldn't decompress image."); } if (image->get_format() != Image::FORMAT_RGB8) { + image = p_img->duplicate(); image->convert(Image::FORMAT_RGB8); } @@ -173,12 +174,16 @@ static Error _jpgd_save_to_output_stream(jpge::output_stream *p_output_stream, c const uint8_t *src_data = image->get_data().ptr(); for (int i = 0; i < image->get_height(); i++) { - enc.process_scanline(&src_data[i * image->get_width() * 3]); + if (!enc.process_scanline(&src_data[i * image->get_width() * 3])) { + return FAILED; + } } - enc.process_scanline(nullptr); - - return OK; + if (enc.process_scanline(nullptr)) { + return OK; + } else { + return FAILED; + } } static Vector<uint8_t> _jpgd_buffer_save_func(const Ref<Image> &p_img, float p_quality) { diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index a4ecb767a7..4746ffb79b 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -357,7 +357,7 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i for (int m_i = 0; m_i < mesh_instances.size(); m_i++) { if (p_step_function) { - float p = float(m_i + 1) / mesh_instances.size() * 0.1; + float p = float(m_i + 1) / MAX(1, mesh_instances.size()) * 0.1; p_step_function(0.3 + p, vformat(RTR("Plotting mesh into acceleration structure %d/%d"), m_i + 1, mesh_instances.size()), p_bake_userdata, false); } @@ -703,7 +703,7 @@ void LightmapperRD::_raster_geometry(RenderingDevice *rd, Size2i atlas_size, int raster_push_constant.uv_offset[0] = -0.5f / float(atlas_size.x); raster_push_constant.uv_offset[1] = -0.5f / float(atlas_size.y); - RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); //draw opaque rd->draw_list_bind_render_pipeline(draw_list, raster_pipeline); rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); @@ -756,7 +756,7 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShade rd->compute_list_bind_uniform_set(compute_list, dilate_uniform_set, 1); push_constant.region_ofs[0] = 0; push_constant.region_ofs[1] = 0; - Vector3i group_size((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); //restore group size + Vector3i group_size(Math::division_round_up(atlas_size.x, 8), Math::division_round_up(atlas_size.y, 8), 1); //restore group size for (int i = 0; i < atlas_slices; i++) { push_constant.atlas_slice = i; @@ -939,8 +939,8 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh // We use a region with 1/4 the amount of pixels if we're denoising SH lightmaps, as // all four of them are denoised in the shader in one dispatch. const int max_region_size = p_bake_sh ? 512 : 1024; - int x_regions = (p_atlas_size.width - 1) / max_region_size + 1; - int y_regions = (p_atlas_size.height - 1) / max_region_size + 1; + int x_regions = Math::division_round_up(p_atlas_size.width, max_region_size); + int y_regions = Math::division_round_up(p_atlas_size.height, max_region_size); for (int s = 0; s < p_atlas_slices; s++) { p_push_constant.atlas_slice = s; @@ -958,7 +958,7 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh p_rd->compute_list_bind_uniform_set(compute_list, p_compute_base_uniform_set, 0); p_rd->compute_list_bind_uniform_set(compute_list, denoise_uniform_set, 1); p_rd->compute_list_set_push_constant(compute_list, &p_push_constant, sizeof(PushConstant)); - p_rd->compute_list_dispatch(compute_list, (w - 1) / 8 + 1, (h - 1) / 8 + 1, 1); + p_rd->compute_list_dispatch(compute_list, Math::division_round_up(w, 8), Math::division_round_up(h, 8), 1); p_rd->compute_list_end(); p_rd->submit(); @@ -1399,7 +1399,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d rd->free(compute_shader_secondary); \ rd->free(compute_shader_light_probes); - Vector3i group_size((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); + Vector3i group_size(Math::division_round_up(atlas_size.x, 8), Math::division_round_up(atlas_size.y, 8), 1); rd->submit(); rd->sync(); @@ -1592,10 +1592,10 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d int max_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/lightmapping/bake_performance/region_size"))); int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_pass"); - int x_regions = (atlas_size.width - 1) / max_region_size + 1; - int y_regions = (atlas_size.height - 1) / max_region_size + 1; + int x_regions = Math::division_round_up(atlas_size.width, max_region_size); + int y_regions = Math::division_round_up(atlas_size.height, max_region_size); - int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1; + int ray_iterations = Math::division_round_up((int32_t)push_constant.ray_count, max_rays); rd->submit(); rd->sync(); @@ -1614,7 +1614,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d push_constant.region_ofs[0] = x; push_constant.region_ofs[1] = y; - group_size = Vector3i((w - 1) / 8 + 1, (h - 1) / 8 + 1, 1); + group_size = Vector3i(Math::division_round_up(w, 8), Math::division_round_up(h, 8), 1); for (int k = 0; k < ray_iterations; k++) { RD::ComputeListID compute_list = rd->compute_list_begin(); @@ -1700,7 +1700,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d push_constant.probe_count = probe_positions.size(); int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_probe_pass"); - int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1; + int ray_iterations = Math::division_round_up((int32_t)push_constant.ray_count, max_rays); for (int i = 0; i < ray_iterations; i++) { RD::ComputeListID compute_list = rd->compute_list_begin(); @@ -1711,7 +1711,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d push_constant.ray_from = i * max_rays; push_constant.ray_to = MIN((i + 1) * max_rays, int32_t(push_constant.ray_count)); rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); - rd->compute_list_dispatch(compute_list, (probe_positions.size() - 1) / 64 + 1, 1, 1); + rd->compute_list_dispatch(compute_list, Math::division_round_up(probe_positions.size(), 64), 1, 1); rd->compute_list_end(); //done rd->submit(); @@ -1863,7 +1863,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d seams_push_constant.slice = uint32_t(i * subslices + k); seams_push_constant.debug = debug; - RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); rd->draw_list_bind_uniform_set(draw_list, blendseams_raster_uniform, 1); diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl index a2a480043a..21e039396d 100644 --- a/modules/lightmapper_rd/lm_compute.glsl +++ b/modules/lightmapper_rd/lm_compute.glsl @@ -264,7 +264,16 @@ uint trace_ray(vec3 p_from, vec3 p_to, bool p_any_hit, out float r_distance, out break; } - bvec3 mask = lessThanEqual(side.xyz, min(side.yzx, side.zxy)); + // There should be only one axis updated at a time for DDA to work properly. + bvec3 mask = bvec3(true, false, false); + float m = side.x; + if (side.y < m) { + m = side.y; + mask = bvec3(false, true, false); + } + if (side.z < m) { + mask = bvec3(false, false, true); + } side += vec3(mask) * delta; icell += ivec3(vec3(mask)) * step; iters++; diff --git a/modules/lightmapper_rd/register_types.cpp b/modules/lightmapper_rd/register_types.cpp index 8103799974..4fe8f20723 100644 --- a/modules/lightmapper_rd/register_types.cpp +++ b/modules/lightmapper_rd/register_types.cpp @@ -46,18 +46,18 @@ void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level) { return; } - GLOBAL_DEF("rendering/lightmapping/bake_quality/low_quality_ray_count", 32); - GLOBAL_DEF("rendering/lightmapping/bake_quality/medium_quality_ray_count", 128); - GLOBAL_DEF("rendering/lightmapping/bake_quality/high_quality_ray_count", 512); - GLOBAL_DEF("rendering/lightmapping/bake_quality/ultra_quality_ray_count", 2048); - GLOBAL_DEF("rendering/lightmapping/bake_performance/max_rays_per_pass", 32); - GLOBAL_DEF("rendering/lightmapping/bake_performance/region_size", 512); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/low_quality_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 32); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/medium_quality_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 128); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/high_quality_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 512); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/ultra_quality_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 2048); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_performance/max_rays_per_pass", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 32); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_performance/region_size", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 512); - GLOBAL_DEF("rendering/lightmapping/bake_quality/low_quality_probe_ray_count", 64); - GLOBAL_DEF("rendering/lightmapping/bake_quality/medium_quality_probe_ray_count", 256); - GLOBAL_DEF("rendering/lightmapping/bake_quality/high_quality_probe_ray_count", 512); - GLOBAL_DEF("rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count", 2048); - GLOBAL_DEF("rendering/lightmapping/bake_performance/max_rays_per_probe_pass", 64); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/low_quality_probe_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 64); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/medium_quality_probe_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 256); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/high_quality_probe_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 512); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 2048); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_performance/max_rays_per_probe_pass", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64); GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/denoising/denoiser", PROPERTY_HINT_ENUM, "JNLM,OIDN"), 0); #ifndef _3D_DISABLED diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp index 4efa4d329e..a46a1c93b5 100644 --- a/modules/minimp3/audio_stream_mp3.cpp +++ b/modules/minimp3/audio_stream_mp3.cpp @@ -46,7 +46,9 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) { int frames_mixed_this_step = p_frames; int beat_length_frames = -1; - bool beat_loop = mp3_stream->has_loop() && mp3_stream->get_bpm() > 0 && mp3_stream->get_beat_count() > 0; + bool use_loop = looping_override ? looping : mp3_stream->loop; + + bool beat_loop = use_loop && mp3_stream->get_bpm() > 0 && mp3_stream->get_beat_count() > 0; if (beat_loop) { beat_length_frames = mp3_stream->get_beat_count() * mp3_stream->sample_rate * 60 / mp3_stream->get_bpm(); } @@ -82,7 +84,7 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) { else { //EOF - if (mp3_stream->loop) { + if (use_loop) { seek(mp3_stream->loop_offset); loops++; } else { @@ -143,6 +145,25 @@ void AudioStreamPlaybackMP3::tag_used_streams() { mp3_stream->tag_used(get_playback_position()); } +void AudioStreamPlaybackMP3::set_parameter(const StringName &p_name, const Variant &p_value) { + if (p_name == SNAME("looping")) { + if (p_value == Variant()) { + looping_override = false; + looping = false; + } else { + looping_override = true; + looping = p_value; + } + } +} + +Variant AudioStreamPlaybackMP3::get_parameter(const StringName &p_name) const { + if (looping_override && p_name == SNAME("looping")) { + return looping; + } + return Variant(); +} + AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() { if (mp3d) { mp3dec_ex_close(mp3d); @@ -232,6 +253,10 @@ bool AudioStreamMP3::is_monophonic() const { return false; } +void AudioStreamMP3::get_parameter_list(List<Parameter> *r_parameters) { + r_parameters->push_back(Parameter(PropertyInfo(Variant::BOOL, "looping", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE), Variant())); +} + void AudioStreamMP3::set_bpm(double p_bpm) { ERR_FAIL_COND(p_bpm < 0); bpm = p_bpm; diff --git a/modules/minimp3/audio_stream_mp3.h b/modules/minimp3/audio_stream_mp3.h index 30760703e3..7d85e0a321 100644 --- a/modules/minimp3/audio_stream_mp3.h +++ b/modules/minimp3/audio_stream_mp3.h @@ -47,6 +47,8 @@ class AudioStreamPlaybackMP3 : public AudioStreamPlaybackResampled { AudioFrame loop_fade[FADE_SIZE]; int loop_fade_remaining = FADE_SIZE; + bool looping_override = false; + bool looping = false; mp3dec_ex_t *mp3d = nullptr; uint32_t frames_mixed = 0; bool active = false; @@ -72,6 +74,9 @@ public: virtual void tag_used_streams() override; + virtual void set_parameter(const StringName &p_name, const Variant &p_value) override; + virtual Variant get_parameter(const StringName &p_name) const override; + AudioStreamPlaybackMP3() {} ~AudioStreamPlaybackMP3(); }; @@ -126,6 +131,8 @@ public: virtual bool is_monophonic() const override; + virtual void get_parameter_list(List<Parameter> *r_parameters) override; + AudioStreamMP3(); virtual ~AudioStreamMP3(); }; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 8e1587997b..ef24dc35ca 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -371,7 +371,7 @@ Ref<Script> CSharpLanguage::make_template(const String &p_template, const String return scr; } -Vector<ScriptLanguage::ScriptTemplate> CSharpLanguage::get_built_in_templates(StringName p_object) { +Vector<ScriptLanguage::ScriptTemplate> CSharpLanguage::get_built_in_templates(const StringName &p_object) { Vector<ScriptLanguage::ScriptTemplate> templates; #ifdef TOOLS_ENABLED for (int i = 0; i < TEMPLATES_ARRAY_SIZE; i++) { @@ -720,11 +720,22 @@ void CSharpLanguage::reload_all_scripts() { #endif } -void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { - (void)p_script; // UNUSED - +void CSharpLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload) { CRASH_COND(!Engine::get_singleton()->is_editor_hint()); + bool has_csharp_script = false; + for (int i = 0; i < p_scripts.size(); ++i) { + Ref<CSharpScript> cs_script = p_scripts[i]; + if (cs_script.is_valid()) { + has_csharp_script = true; + break; + } + } + + if (!has_csharp_script) { + return; + } + #ifdef TOOLS_ENABLED get_godotsharp_editor()->get_node(NodePath("HotReloadAssemblyWatcher"))->call("RestartTimer"); #endif @@ -736,6 +747,12 @@ void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft #endif } +void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { + Array scripts; + scripts.push_back(p_script); + reload_scripts(scripts, p_soft_reload); +} + #ifdef GD_MONO_HOT_RELOAD bool CSharpLanguage::is_assembly_reloading_needed() { ERR_FAIL_NULL_V(gdmono, false); @@ -1074,7 +1091,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } // The script instance could not be instantiated or wasn't in the list of placeholders to replace. obj->set_script(scr); -#if DEBUG_ENABLED +#ifdef DEBUG_ENABLED // If we reached here, the instantiated script must be a placeholder. CRASH_COND(!obj->get_script_instance()->is_placeholder()); #endif @@ -2246,6 +2263,17 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda } else { p_instance_to_update->update(propnames, values); } + } else if (placeholders.size()) { + uint64_t script_modified_time = FileAccess::get_modified_time(get_path()); + uint64_t last_valid_build_time = GDMono::get_singleton()->get_project_assembly_modified_time(); + if (script_modified_time > last_valid_build_time) { + for (PlaceHolderScriptInstance *instance : placeholders) { + Object *owner = instance->get_owner(); + if (owner->get_script_instance() == instance) { + owner->notify_property_list_changed(); + } + } + } } } #endif @@ -2299,7 +2327,7 @@ void CSharpScript::reload_registered_script(Ref<CSharpScript> p_script) { p_script->_update_exports(); -#if TOOLS_ENABLED +#ifdef TOOLS_ENABLED // If the EditorFileSystem singleton is available, update the file; // otherwise, the file will be updated when the singleton becomes available. EditorFileSystem *efs = EditorFileSystem::get_singleton(); @@ -2354,6 +2382,8 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) { MethodInfo mi; mi.name = name; + mi.return_val = PropertyInfo::from_dict(method_info_dict["return_val"]); + Array params = method_info_dict["params"]; for (int j = 0; j < params.size(); j++) { @@ -2653,7 +2683,7 @@ Error CSharpScript::reload(bool p_keep_state) { _update_exports(); -#if TOOLS_ENABLED +#ifdef TOOLS_ENABLED // If the EditorFileSystem singleton is available, update the file; // otherwise, the file will be updated when the singleton becomes available. EditorFileSystem *efs = EditorFileSystem::get_singleton(); diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 401f5c62e5..310cb81929 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -423,7 +423,7 @@ public: void get_string_delimiters(List<String> *p_delimiters) const override; bool is_using_templates() override; virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override; - virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override; + virtual Vector<ScriptTemplate> get_built_in_templates(const StringName &p_object) override; /* TODO */ bool validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const override { return true; @@ -478,6 +478,7 @@ public: /* TODO? */ void get_public_annotations(List<MethodInfo> *p_annotations) const override {} void reload_all_scripts() override; + void reload_scripts(const Array &p_scripts, bool p_soft_reload) override; void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) override; /* LOADER FUNCTIONS */ diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln index 03a7dc453c..9674626183 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators", "G EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators.Sample", "Godot.SourceGenerators.Sample\Godot.SourceGenerators.Sample.csproj", "{7297A614-8DF5-43DE-9EAD-99671B26BD1F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators.Tests", "Godot.SourceGenerators.Tests\Godot.SourceGenerators.Tests.csproj", "{07E6D201-35C9-4463-9B29-D16621EA733D}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharp", "..\..\glue\GodotSharp\GodotSharp\GodotSharp.csproj", "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}" EndProject Global @@ -26,6 +28,10 @@ Global {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Debug|Any CPU.Build.0 = Debug|Any CPU {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Release|Any CPU.ActiveCfg = Release|Any CPU {7297A614-8DF5-43DE-9EAD-99671B26BD1F}.Release|Any CPU.Build.0 = Release|Any CPU + {07E6D201-35C9-4463-9B29-D16621EA733D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07E6D201-35C9-4463-9B29-D16621EA733D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07E6D201-35C9-4463-9B29-D16621EA733D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07E6D201-35C9-4463-9B29-D16621EA733D}.Release|Any CPU.Build.0 = Release|Any CPU {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.Build.0 = Debug|Any CPU {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/GlobalClass.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/GlobalClass.cs new file mode 100644 index 0000000000..b9f11908e1 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/GlobalClass.cs @@ -0,0 +1,14 @@ +namespace Godot.SourceGenerators.Sample; + +[GlobalClass] +public partial class CustomGlobalClass : GodotObject +{ +} + +// This doesn't works because global classes can't have any generic type parameter. +/* +[GlobalClass] +public partial class CustomGlobalClass<T> : Node +{ +} +*/ diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj index 3f569ebac3..d0907c1cd4 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj @@ -2,6 +2,7 @@ <PropertyGroup> <TargetFramework>net6.0</TargetFramework> + <LangVersion>11</LangVersion> </PropertyGroup> <PropertyGroup> diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MustBeVariantSamples.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MustBeVariantSamples.cs new file mode 100644 index 0000000000..1e06091e80 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MustBeVariantSamples.cs @@ -0,0 +1,164 @@ +using System; +using Godot.Collections; +using Array = Godot.Collections.Array; + +namespace Godot.SourceGenerators.Sample; + +public class MustBeVariantMethods +{ + public void MustBeVariantMethodCalls() + { + Method<bool>(); + Method<char>(); + Method<sbyte>(); + Method<byte>(); + Method<short>(); + Method<ushort>(); + Method<int>(); + Method<uint>(); + Method<long>(); + Method<ulong>(); + Method<float>(); + Method<double>(); + Method<string>(); + Method<Vector2>(); + Method<Vector2I>(); + Method<Rect2>(); + Method<Rect2I>(); + Method<Transform2D>(); + Method<Vector3>(); + Method<Vector3I>(); + Method<Vector4>(); + Method<Vector4I>(); + Method<Basis>(); + Method<Quaternion>(); + Method<Transform3D>(); + Method<Projection>(); + Method<Aabb>(); + Method<Color>(); + Method<Plane>(); + Method<Callable>(); + Method<Signal>(); + Method<GodotObject>(); + Method<StringName>(); + Method<NodePath>(); + Method<Rid>(); + Method<Dictionary>(); + Method<Array>(); + Method<byte[]>(); + Method<int[]>(); + Method<long[]>(); + Method<float[]>(); + Method<double[]>(); + Method<string[]>(); + Method<Vector2[]>(); + Method<Vector3[]>(); + Method<Color[]>(); + Method<GodotObject[]>(); + Method<StringName[]>(); + Method<NodePath[]>(); + Method<Rid[]>(); + + // This call fails because generic type is not Variant-compatible. + //Method<object>(); + } + + public void Method<[MustBeVariant] T>() + { + } + + public void MustBeVariantClasses() + { + new ClassWithGenericVariant<bool>(); + new ClassWithGenericVariant<char>(); + new ClassWithGenericVariant<sbyte>(); + new ClassWithGenericVariant<byte>(); + new ClassWithGenericVariant<short>(); + new ClassWithGenericVariant<ushort>(); + new ClassWithGenericVariant<int>(); + new ClassWithGenericVariant<uint>(); + new ClassWithGenericVariant<long>(); + new ClassWithGenericVariant<ulong>(); + new ClassWithGenericVariant<float>(); + new ClassWithGenericVariant<double>(); + new ClassWithGenericVariant<string>(); + new ClassWithGenericVariant<Vector2>(); + new ClassWithGenericVariant<Vector2I>(); + new ClassWithGenericVariant<Rect2>(); + new ClassWithGenericVariant<Rect2I>(); + new ClassWithGenericVariant<Transform2D>(); + new ClassWithGenericVariant<Vector3>(); + new ClassWithGenericVariant<Vector3I>(); + new ClassWithGenericVariant<Vector4>(); + new ClassWithGenericVariant<Vector4I>(); + new ClassWithGenericVariant<Basis>(); + new ClassWithGenericVariant<Quaternion>(); + new ClassWithGenericVariant<Transform3D>(); + new ClassWithGenericVariant<Projection>(); + new ClassWithGenericVariant<Aabb>(); + new ClassWithGenericVariant<Color>(); + new ClassWithGenericVariant<Plane>(); + new ClassWithGenericVariant<Callable>(); + new ClassWithGenericVariant<Signal>(); + new ClassWithGenericVariant<GodotObject>(); + new ClassWithGenericVariant<StringName>(); + new ClassWithGenericVariant<NodePath>(); + new ClassWithGenericVariant<Rid>(); + new ClassWithGenericVariant<Dictionary>(); + new ClassWithGenericVariant<Array>(); + new ClassWithGenericVariant<byte[]>(); + new ClassWithGenericVariant<int[]>(); + new ClassWithGenericVariant<long[]>(); + new ClassWithGenericVariant<float[]>(); + new ClassWithGenericVariant<double[]>(); + new ClassWithGenericVariant<string[]>(); + new ClassWithGenericVariant<Vector2[]>(); + new ClassWithGenericVariant<Vector3[]>(); + new ClassWithGenericVariant<Color[]>(); + new ClassWithGenericVariant<GodotObject[]>(); + new ClassWithGenericVariant<StringName[]>(); + new ClassWithGenericVariant<NodePath[]>(); + new ClassWithGenericVariant<Rid[]>(); + + // This class fails because generic type is not Variant-compatible. + //new ClassWithGenericVariant<object>(); + } +} + +public class ClassWithGenericVariant<[MustBeVariant] T> +{ +} + +public class MustBeVariantAnnotatedMethods +{ + [GenericTypeAttribute<string>()] + public void MethodWithAttributeOk() + { + } + + // This method definition fails because generic type is not Variant-compatible. + /* + [GenericTypeAttribute<object>()] + public void MethodWithWrongAttribute() + { + } + */ +} + +[GenericTypeAttribute<string>()] +public class ClassVariantAnnotated +{ +} + +// This class definition fails because generic type is not Variant-compatible. +/* +[GenericTypeAttribute<object>()] +public class ClassNonVariantAnnotated +{ +} +*/ + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] +public class GenericTypeAttribute<[MustBeVariant] T> : Attribute +{ +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/CSharpAnalyzerVerifier.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/CSharpAnalyzerVerifier.cs new file mode 100644 index 0000000000..e3e7373b2e --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/CSharpAnalyzerVerifier.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.Text; + +namespace Godot.SourceGenerators.Tests; + +public static class CSharpAnalyzerVerifier<TAnalyzer> +where TAnalyzer : DiagnosticAnalyzer, new() +{ + public class Test : CSharpAnalyzerTest<TAnalyzer, XUnitVerifier> + { + public Test() + { + ReferenceAssemblies = ReferenceAssemblies.Net.Net60; + + SolutionTransforms.Add((Solution solution, ProjectId projectId) => + { + Project project = + solution.GetProject(projectId)!.AddMetadataReference(Constants.GodotSharpAssembly + .CreateMetadataReference()); + + return project.Solution; + }); + } + } + + public static Task Verify(string sources, params DiagnosticResult[] expected) + { + return MakeVerifier(new string[] { sources }, expected).RunAsync(); + } + + public static Test MakeVerifier(ICollection<string> sources, params DiagnosticResult[] expected) + { + var verifier = new Test(); + + verifier.TestState.AnalyzerConfigFiles.Add(("/.globalconfig", $""" + is_global = true + build_property.GodotProjectDir = {Constants.ExecutingAssemblyPath} + """)); + + verifier.TestState.Sources.AddRange(sources.Select(source => + { + return (source, SourceText.From(File.ReadAllText(Path.Combine(Constants.SourceFolderPath, source)))); + })); + + verifier.ExpectedDiagnostics.AddRange(expected); + return verifier; + } +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/GlobalClassAnalyzerTests.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/GlobalClassAnalyzerTests.cs new file mode 100644 index 0000000000..74d6afceb3 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/GlobalClassAnalyzerTests.cs @@ -0,0 +1,20 @@ +using Xunit; + +namespace Godot.SourceGenerators.Tests; + +public class GlobalClassAnalyzerTests +{ + [Fact] + public async void GlobalClassMustDeriveFromGodotObjectTest() + { + const string GlobalClassGD0401 = "GlobalClass.GD0401.cs"; + await CSharpAnalyzerVerifier<GlobalClassAnalyzer>.Verify(GlobalClassGD0401); + } + + [Fact] + public async void GlobalClassMustNotBeGenericTest() + { + const string GlobalClassGD0402 = "GlobalClass.GD0402.cs"; + await CSharpAnalyzerVerifier<GlobalClassAnalyzer>.Verify(GlobalClassGD0402); + } +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj index e39c14f049..13e54a543f 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj @@ -17,6 +17,8 @@ <ItemGroup> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing.XUnit" Version="1.1.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" /> + <PackageReference Include="Microsoft.CodeAnalysis.Testing.Verifiers.XUnit" Version="1.1.1" /> + <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit" Version="1.1.1" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/MustBeVariantAnalyzerTests.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/MustBeVariantAnalyzerTests.cs new file mode 100644 index 0000000000..62c602efbb --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/MustBeVariantAnalyzerTests.cs @@ -0,0 +1,20 @@ +using Xunit; + +namespace Godot.SourceGenerators.Tests; + +public class MustBeVariantAnalyzerTests +{ + [Fact] + public async void GenericTypeArgumentMustBeVariantTest() + { + const string MustBeVariantGD0301 = "MustBeVariant.GD0301.cs"; + await CSharpAnalyzerVerifier<MustBeVariantAnalyzer>.Verify(MustBeVariantGD0301); + } + + [Fact] + public async void GenericTypeParameterMustBeVariantAnnotatedTest() + { + const string MustBeVariantGD0302 = "MustBeVariant.GD0302.cs"; + await CSharpAnalyzerVerifier<MustBeVariantAnalyzer>.Verify(MustBeVariantGD0302); + } +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/GlobalClass.GD0401.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/GlobalClass.GD0401.cs new file mode 100644 index 0000000000..6e6d3a6f39 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/GlobalClass.GD0401.cs @@ -0,0 +1,22 @@ +using Godot; + +// This works because it inherits from GodotObject. +[GlobalClass] +public partial class CustomGlobalClass1 : GodotObject +{ + +} + +// This works because it inherits from an object that inherits from GodotObject +[GlobalClass] +public partial class CustomGlobalClass2 : Node +{ + +} + +// This raises a GD0401 diagnostic error: global classes must inherit from GodotObject +{|GD0401:[GlobalClass] +public partial class CustomGlobalClass3 +{ + +}|} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/GlobalClass.GD0402.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/GlobalClass.GD0402.cs new file mode 100644 index 0000000000..1c0a169841 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/GlobalClass.GD0402.cs @@ -0,0 +1,15 @@ +using Godot; + +// This works because it inherits from GodotObject and it doesn't have any generic type parameter. +[GlobalClass] +public partial class CustomGlobalClass : GodotObject +{ + +} + +// This raises a GD0402 diagnostic error: global classes can't have any generic type parameter +{|GD0402:[GlobalClass] +public partial class CustomGlobalClass<T> : GodotObject +{ + +}|} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0301.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0301.cs new file mode 100644 index 0000000000..031039cba1 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0301.cs @@ -0,0 +1,71 @@ +using System; +using Godot; +using Godot.Collections; +using Array = Godot.Collections.Array; + +public class MustBeVariantGD0301 +{ + public void MethodCallsError() + { + // This raises a GD0301 diagnostic error: object is not Variant (and Method<T> requires a variant generic type). + Method<{|GD0301:object|}>(); + } + public void MethodCallsOk() + { + // All these calls are valid because they are Variant types. + Method<bool>(); + Method<char>(); + Method<sbyte>(); + Method<byte>(); + Method<short>(); + Method<ushort>(); + Method<int>(); + Method<uint>(); + Method<long>(); + Method<ulong>(); + Method<float>(); + Method<double>(); + Method<string>(); + Method<Vector2>(); + Method<Vector2I>(); + Method<Rect2>(); + Method<Rect2I>(); + Method<Transform2D>(); + Method<Vector3>(); + Method<Vector3I>(); + Method<Vector4>(); + Method<Vector4I>(); + Method<Basis>(); + Method<Quaternion>(); + Method<Transform3D>(); + Method<Projection>(); + Method<Aabb>(); + Method<Color>(); + Method<Plane>(); + Method<Callable>(); + Method<Signal>(); + Method<GodotObject>(); + Method<StringName>(); + Method<NodePath>(); + Method<Rid>(); + Method<Dictionary>(); + Method<Array>(); + Method<byte[]>(); + Method<int[]>(); + Method<long[]>(); + Method<float[]>(); + Method<double[]>(); + Method<string[]>(); + Method<Vector2[]>(); + Method<Vector3[]>(); + Method<Color[]>(); + Method<GodotObject[]>(); + Method<StringName[]>(); + Method<NodePath[]>(); + Method<Rid[]>(); + } + + public void Method<[MustBeVariant] T>() + { + } +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0302.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0302.cs new file mode 100644 index 0000000000..ce182e8c62 --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0302.cs @@ -0,0 +1,27 @@ +using Godot; + +public class MustBeVariantGD0302 +{ + public void MethodOk<[MustBeVariant] T>() + { + // T is guaranteed to be a Variant-compatible type because it's annotated with the [MustBeVariant] attribute, so it can be used here. + new ExampleClass<T>(); + Method<T>(); + } + + public void MethodFail<T>() + { + // These two calls raise a GD0302 diagnostic error: T is not valid here because it may not a Variant type and method call and class require it. + new ExampleClass<{|GD0302:T|}>(); + Method<{|GD0302:T|}>(); + } + + public void Method<[MustBeVariant] T>() + { + } +} + +public class ExampleClass<[MustBeVariant] T> +{ + +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs index 147ef852b3..1113629fef 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs @@ -146,7 +146,7 @@ namespace Godot.SourceGenerators DiagnosticSeverity.Error, isEnabledByDefault: true, description, - helpLinkUri: string.Format(_helpLinkFormat, "GD1003")), + helpLinkUri: string.Format(_helpLinkFormat, "GD0103")), location, location?.SourceTree?.FilePath)); } diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj index 9e36497b06..d0972f1eae 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj @@ -1,8 +1,8 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <ProjectGuid>{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}</ProjectGuid> - <TargetFramework>netstandard2.0</TargetFramework> - <LangVersion>7.2</LangVersion> + <TargetFramework>net6.0</TargetFramework> + <LangVersion>10</LangVersion> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" ExcludeAssets="runtime" /> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj index d2132115f3..eb6ac8bafc 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj @@ -2,13 +2,10 @@ <PropertyGroup> <ProjectGuid>{B06C2951-C8E3-4F28-80B2-717CF327EB19}</ProjectGuid> <OutputType>Exe</OutputType> - <TargetFramework>net472</TargetFramework> - <LangVersion>7.2</LangVersion> + <TargetFramework>net6.0</TargetFramework> + <LangVersion>10</LangVersion> </PropertyGroup> <ItemGroup> - <Reference Include="System" /> - </ItemGroup> - <ItemGroup> <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" /> </ItemGroup> <ItemGroup> diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj index c05096bdcc..22778f21cb 100644 --- a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj @@ -1,12 +1,15 @@ <Project Sdk="Microsoft.NET.Sdk"> - <PropertyGroup> - <ProjectGuid>{EAFFF236-FA96-4A4D-BD23-0E51EF988277}</ProjectGuid> - <OutputType>Exe</OutputType> - <TargetFramework>net472</TargetFramework> - <LangVersion>7.2</LangVersion> - </PropertyGroup> - <ItemGroup> - <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="EnvDTE" Version="8.0.2" /> - </ItemGroup> + <PropertyGroup> + <ProjectGuid>{EAFFF236-FA96-4A4D-BD23-0E51EF988277}</ProjectGuid> + <OutputType>Exe</OutputType> + <TargetFramework>net6.0-windows</TargetFramework> + <LangVersion>10</LangVersion> + </PropertyGroup> + <PropertyGroup Condition="Exists('$(SolutionDir)/../../../../bin/GodotSharp/Api/Debug/GodotSharp.dll') And ('$(GodotPlatform)' == 'windows' Or ('$(GodotPlatform)' == '' And '$(OS)' == 'Windows_NT'))"> + <OutputPath>$(SolutionDir)/../../../../bin/GodotSharp/Tools</OutputPath> + <AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="EnvDTE" Version="17.8.37221" /> + </ItemGroup> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs index cc0deb6cc0..8e8eaa79b8 100644 --- a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs +++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs @@ -129,7 +129,7 @@ namespace GodotTools.OpenVisualStudio { var mainWindow = dte.MainWindow; mainWindow.Activate(); - SetForegroundWindow(new IntPtr(mainWindow.HWnd)); + SetForegroundWindow(mainWindow.HWnd); MessageFilter.Revoke(); } diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 650afb4cdf..5408b9b13e 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -9,6 +9,7 @@ using System.Linq; using GodotTools.Build; using GodotTools.Ides; using GodotTools.Ides.Rider; +using GodotTools.Inspector; using GodotTools.Internals; using GodotTools.ProjectEditor; using JetBrains.Annotations; @@ -45,6 +46,7 @@ namespace GodotTools // TODO Use WeakReference once we have proper serialization. private WeakRef _exportPluginWeak; + private WeakRef _inspectorPluginWeak; public GodotIdeManager GodotIdeManager { get; private set; } @@ -52,6 +54,8 @@ namespace GodotTools public bool SkipBuildBeforePlaying { get; set; } = false; + public DateTime LastValidBuildDateTime { get; private set; } + [UsedImplicitly] private bool CreateProjectSolutionIfNeeded() { @@ -437,6 +441,21 @@ namespace GodotTools } } + private void UpdateLastValidBuildDateTime() + { + var dllName = $"{GodotSharpDirs.ProjectAssemblyName}.dll"; + var path = Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, "Debug", dllName); + LastValidBuildDateTime = File.GetLastWriteTime(path); + } + + private void BuildFinished(BuildResult buildResult) + { + if (buildResult == BuildResult.Success) + { + UpdateLastValidBuildDateTime(); + } + } + private void BuildStateChanged() { if (_bottomPanelBtn != null) @@ -447,6 +466,8 @@ namespace GodotTools { base._EnablePlugin(); + UpdateLastValidBuildDateTime(); + ProjectSettings.SettingsChanged += GodotSharpDirs.DetermineProjectLocation; if (Instance != null) @@ -615,6 +636,12 @@ namespace GodotTools AddExportPlugin(exportPlugin); _exportPluginWeak = WeakRef(exportPlugin); + // Inspector plugin + var inspectorPlugin = new InspectorPlugin(); + AddInspectorPlugin(inspectorPlugin); + _inspectorPluginWeak = WeakRef(inspectorPlugin); + BuildManager.BuildFinished += BuildFinished; + BuildManager.Initialize(); RiderPathManager.Initialize(); @@ -627,6 +654,10 @@ namespace GodotTools base._DisablePlugin(); _editorSettings.SettingsChanged -= OnSettingsChanged; + + // Custom signals aren't automatically disconnected currently. + MSBuildPanel.BuildStateChanged -= BuildStateChanged; + BuildManager.BuildFinished -= BuildFinished; } public override void _ExitTree() @@ -661,6 +692,13 @@ namespace GodotTools _exportPluginWeak.Dispose(); } + if (IsInstanceValid(_inspectorPluginWeak)) + { + (_inspectorPluginWeak.GetRef().AsGodotObject() as InspectorPlugin)?.Dispose(); + + _inspectorPluginWeak.Dispose(); + } + GodotIdeManager?.Dispose(); } diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index 56ae37b4dd..b5567ea3c7 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -28,7 +28,7 @@ </PropertyGroup> <ItemGroup> <PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" /> - <PackageReference Include="JetBrains.Rider.PathLocator" Version="1.0.4" /> + <PackageReference Include="JetBrains.Rider.PathLocator" Version="1.0.8" /> <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <Reference Include="GodotSharp"> @@ -49,7 +49,5 @@ <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" /> <ProjectReference Include="..\GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj" /> <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" /> - <!-- Include it if this is an SCons build targeting Windows, or if it's not an SCons build but we're on Windows --> - <ProjectReference Include="..\GodotTools.OpenVisualStudio\GodotTools.OpenVisualStudio.csproj" Condition=" '$(GodotPlatform)' == 'windows' Or ( '$(GodotPlatform)' == '' And '$(OS)' == 'Windows_NT' ) " /> </ItemGroup> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools/Inspector/InspectorOutOfSyncWarning.cs b/modules/mono/editor/GodotTools/GodotTools/Inspector/InspectorOutOfSyncWarning.cs new file mode 100644 index 0000000000..c5c451f143 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools/Inspector/InspectorOutOfSyncWarning.cs @@ -0,0 +1,37 @@ +using Godot; +using GodotTools.Internals; + +namespace GodotTools.Inspector +{ + public partial class InspectorOutOfSyncWarning : HBoxContainer + { + public override void _Ready() + { + SetAnchorsPreset(LayoutPreset.TopWide); + + var iconTexture = GetThemeIcon("StatusWarning", "EditorIcons"); + + var icon = new TextureRect() + { + Texture = iconTexture, + ExpandMode = TextureRect.ExpandModeEnum.FitWidthProportional, + CustomMinimumSize = iconTexture.GetSize(), + }; + + icon.SizeFlagsVertical = SizeFlags.ShrinkCenter; + + var label = new Label() + { + Text = "This inspector might be out of date. Please build the C# project.".TTR(), + AutowrapMode = TextServer.AutowrapMode.WordSmart, + CustomMinimumSize = new Vector2(100f, 0f), + }; + + label.AddThemeColorOverride("font_color", GetThemeColor("warning_color", "Editor")); + label.SizeFlagsHorizontal = SizeFlags.Fill | SizeFlags.Expand; + + AddChild(icon); + AddChild(label); + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools/Inspector/InspectorPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Inspector/InspectorPlugin.cs new file mode 100644 index 0000000000..8282ca6ea6 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools/Inspector/InspectorPlugin.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using Godot; +using GodotTools.Utils; + +namespace GodotTools.Inspector +{ + public partial class InspectorPlugin : EditorInspectorPlugin + { + public override bool _CanHandle(GodotObject godotObject) + { + foreach (var script in EnumerateScripts(godotObject)) + { + if (script is CSharpScript) + { + return true; + } + } + return false; + } + + public override void _ParseBegin(GodotObject godotObject) + { + foreach (var script in EnumerateScripts(godotObject)) + { + if (script is not CSharpScript) continue; + + if (File.GetLastWriteTime(script.ResourcePath) > GodotSharpEditor.Instance.LastValidBuildDateTime) + { + AddCustomControl(new InspectorOutOfSyncWarning()); + break; + } + } + } + + private static IEnumerable<Script> EnumerateScripts(GodotObject godotObject) + { + var script = godotObject.GetScript().As<Script>(); + while (script != null) + { + yield return script; + script = script.GetBaseScript(); + } + } + } +} diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp index fc99f3ceda..05dacd28fb 100644 --- a/modules/mono/editor/editor_internal_calls.cpp +++ b/modules/mono/editor/editor_internal_calls.cpp @@ -43,10 +43,10 @@ #include "editor/debugger/editor_debugger_node.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/gui/editor_run_bar.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "main/main.h" #ifdef UNIX_ENABLED @@ -148,7 +148,7 @@ void godot_icall_Internal_ReloadAssemblies(bool p_soft_reload) { } void godot_icall_Internal_EditorDebuggerNodeReloadScripts() { - EditorDebuggerNode::get_singleton()->reload_scripts(); + EditorDebuggerNode::get_singleton()->reload_all_scripts(); } bool godot_icall_Internal_ScriptEditorEdit(Resource *p_resource, int32_t p_line, int32_t p_col, bool p_grab_focus) { @@ -175,7 +175,7 @@ void godot_icall_Internal_EditorPlugin_AddControlToEditorRunBar(Control *p_contr void godot_icall_Internal_ScriptEditorDebugger_ReloadScripts() { EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton(); if (ed) { - ed->reload_scripts(); + ed->reload_all_scripts(); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs index 57b5b09ebb..63af6ee6e8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs @@ -98,11 +98,11 @@ namespace Godot Vector3 dstMax = with._position + with._size; return srcMin.X <= dstMin.X && - srcMax.X > dstMax.X && + srcMax.X >= dstMax.X && srcMin.Y <= dstMin.Y && - srcMax.Y > dstMax.Y && + srcMax.Y >= dstMax.Y && srcMin.Z <= dstMin.Z && - srcMax.Z > dstMax.Z; + srcMax.Z >= dstMax.Z; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index a087b20308..968afa664b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -662,6 +662,19 @@ namespace Godot.Bridge methodInfo.Add("name", method.Name); + var returnVal = new Collections.Dictionary() + { + { "name", method.ReturnVal.Name }, + { "type", (int)method.ReturnVal.Type }, + { "usage", (int)method.ReturnVal.Usage } + }; + if (method.ReturnVal.ClassName != null) + { + returnVal["class_name"] = method.ReturnVal.ClassName; + } + + methodInfo.Add("return_val", returnVal); + var methodParams = new Collections.Array(); if (method.Arguments != null) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs index 71a35ab809..cf4ac45a9f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs @@ -123,8 +123,8 @@ namespace Godot public readonly bool Encloses(Rect2 b) { return b._position.X >= _position.X && b._position.Y >= _position.Y && - b._position.X + b._size.X < _position.X + _size.X && - b._position.Y + b._size.Y < _position.Y + _size.Y; + b._position.X + b._size.X <= _position.X + _size.X && + b._position.Y + b._size.Y <= _position.Y + _size.Y; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2I.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2I.cs index ef7e9eacd8..58560df0c5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2I.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2I.cs @@ -113,8 +113,8 @@ namespace Godot public readonly bool Encloses(Rect2I b) { return b._position.X >= _position.X && b._position.Y >= _position.Y && - b._position.X + b._size.X < _position.X + _size.X && - b._position.Y + b._size.Y < _position.Y + _size.Y; + b._position.X + b._size.X <= _position.X + _size.X && + b._position.Y + b._size.Y <= _position.Y + _size.Y; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs index 104e30981f..8960323754 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs @@ -124,6 +124,29 @@ namespace Godot } /// <summary> + /// Returns the squared distance between this vector and <paramref name="to"/>. + /// This method runs faster than <see cref="DistanceTo"/>, so prefer it if + /// you need to compare vectors or need the squared distance for some formula. + /// </summary> + /// <param name="to">The other vector to use.</param> + /// <returns>The squared distance between the two vectors.</returns> + public readonly int DistanceSquaredTo(Vector2I to) + { + return (to - this).LengthSquared(); + } + + /// <summary> + /// Returns the distance between this vector and <paramref name="to"/>. + /// </summary> + /// <seealso cref="DistanceSquaredTo(Vector2I)"/> + /// <param name="to">The other vector to use.</param> + /// <returns>The distance between the two vectors.</returns> + public readonly real_t DistanceTo(Vector2I to) + { + return (to - this).Length(); + } + + /// <summary> /// Returns the length (magnitude) of this vector. /// </summary> /// <seealso cref="LengthSquared"/> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs index 4af9fd878b..2d7bbc926d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs @@ -132,6 +132,29 @@ namespace Godot } /// <summary> + /// Returns the squared distance between this vector and <paramref name="to"/>. + /// This method runs faster than <see cref="DistanceTo"/>, so prefer it if + /// you need to compare vectors or need the squared distance for some formula. + /// </summary> + /// <param name="to">The other vector to use.</param> + /// <returns>The squared distance between the two vectors.</returns> + public readonly int DistanceSquaredTo(Vector3I to) + { + return (to - this).LengthSquared(); + } + + /// <summary> + /// Returns the distance between this vector and <paramref name="to"/>. + /// </summary> + /// <seealso cref="DistanceSquaredTo(Vector3I)"/> + /// <param name="to">The other vector to use.</param> + /// <returns>The distance between the two vectors.</returns> + public readonly real_t DistanceTo(Vector3I to) + { + return (to - this).Length(); + } + + /// <summary> /// Returns the length (magnitude) of this vector. /// </summary> /// <seealso cref="LengthSquared"/> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs index 7d4d3dd353..9a85f359d7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs @@ -149,6 +149,29 @@ namespace Godot } /// <summary> + /// Returns the squared distance between this vector and <paramref name="to"/>. + /// This method runs faster than <see cref="DistanceTo"/>, so prefer it if + /// you need to compare vectors or need the squared distance for some formula. + /// </summary> + /// <param name="to">The other vector to use.</param> + /// <returns>The squared distance between the two vectors.</returns> + public readonly int DistanceSquaredTo(Vector4I to) + { + return (to - this).LengthSquared(); + } + + /// <summary> + /// Returns the distance between this vector and <paramref name="to"/>. + /// </summary> + /// <seealso cref="DistanceSquaredTo(Vector4I)"/> + /// <param name="to">The other vector to use.</param> + /// <returns>The distance between the two vectors.</returns> + public readonly real_t DistanceTo(Vector4I to) + { + return (to - this).Length(); + } + + /// <summary> /// Returns the length (magnitude) of this vector. /// </summary> /// <seealso cref="LengthSquared"/> diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index 3518507f8c..0089e9c2a2 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -316,7 +316,7 @@ void godotsharp_internal_new_csharp_script(Ref<CSharpScript> *r_dest) { } void godotsharp_internal_editor_file_system_update_file(const String *p_script_path) { -#if TOOLS_ENABLED +#ifdef TOOLS_ENABLED // If the EditorFileSystem singleton is available, update the file; // otherwise, the file will be updated when the singleton becomes available. EditorFileSystem *efs = EditorFileSystem::get_singleton(); diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index aa97534675..ee17a668d7 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -152,7 +152,7 @@ String realpath(const String &p_path) { } return result.simplify_path(); -#elif UNIX_ENABLED +#elif defined(UNIX_ENABLED) char *resolved_path = ::realpath(p_path.utf8().get_data(), nullptr); if (!resolved_path) { diff --git a/modules/multiplayer/editor/editor_network_profiler.cpp b/modules/multiplayer/editor/editor_network_profiler.cpp index a53eefc452..a45e5ffdc0 100644 --- a/modules/multiplayer/editor/editor_network_profiler.cpp +++ b/modules/multiplayer/editor/editor_network_profiler.cpp @@ -31,9 +31,9 @@ #include "editor_network_profiler.h" #include "core/os/os.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" void EditorNetworkProfiler::_bind_methods() { ADD_SIGNAL(MethodInfo("enable_profiling", PropertyInfo(Variant::BOOL, "enable"))); diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp index eab1f5d51d..2e3df732e2 100644 --- a/modules/multiplayer/editor/replication_editor.cpp +++ b/modules/multiplayer/editor/replication_editor.cpp @@ -33,13 +33,13 @@ #include "../multiplayer_synchronizer.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/scene_tree_editor.h" #include "editor/inspector_dock.h" #include "editor/property_selector.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/dialogs.h" #include "scene/gui/separator.h" #include "scene/gui/tree.h" diff --git a/modules/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp index c95e4ff9c9..31307e648d 100644 --- a/modules/multiplayer/scene_replication_interface.cpp +++ b/modules/multiplayer/scene_replication_interface.cpp @@ -707,7 +707,7 @@ MultiplayerSynchronizer *SceneReplicationInterface::_find_synchronizer(int p_pee return sync; } -void SceneReplicationInterface::_send_delta(int p_peer, const HashSet<ObjectID> p_synchronizers, uint64_t p_usec, const HashMap<ObjectID, uint64_t> p_last_watch_usecs) { +void SceneReplicationInterface::_send_delta(int p_peer, const HashSet<ObjectID> &p_synchronizers, uint64_t p_usec, const HashMap<ObjectID, uint64_t> &p_last_watch_usecs) { MAKE_ROOM(/* header */ 1 + /* element */ 4 + 8 + 4 + delta_mtu); uint8_t *ptr = packet_cache.ptrw(); ptr[0] = SceneMultiplayer::NETWORK_COMMAND_SYNC | (1 << SceneMultiplayer::CMD_FLAG_0_SHIFT); @@ -799,7 +799,7 @@ Error SceneReplicationInterface::on_delta_receive(int p_from, const uint8_t *p_b return OK; } -void SceneReplicationInterface::_send_sync(int p_peer, const HashSet<ObjectID> p_synchronizers, uint16_t p_sync_net_time, uint64_t p_usec) { +void SceneReplicationInterface::_send_sync(int p_peer, const HashSet<ObjectID> &p_synchronizers, uint16_t p_sync_net_time, uint64_t p_usec) { MAKE_ROOM(/* header */ 3 + /* element */ 4 + 4 + sync_mtu); uint8_t *ptr = packet_cache.ptrw(); ptr[0] = SceneMultiplayer::NETWORK_COMMAND_SYNC; diff --git a/modules/multiplayer/scene_replication_interface.h b/modules/multiplayer/scene_replication_interface.h index 3b3ec6a9ef..31211bb108 100644 --- a/modules/multiplayer/scene_replication_interface.h +++ b/modules/multiplayer/scene_replication_interface.h @@ -101,8 +101,8 @@ private: bool _verify_synchronizer(int p_peer, MultiplayerSynchronizer *p_sync, uint32_t &r_net_id); MultiplayerSynchronizer *_find_synchronizer(int p_peer, uint32_t p_net_ida); - void _send_sync(int p_peer, const HashSet<ObjectID> p_synchronizers, uint16_t p_sync_net_time, uint64_t p_usec); - void _send_delta(int p_peer, const HashSet<ObjectID> p_synchronizers, uint64_t p_usec, const HashMap<ObjectID, uint64_t> p_last_watch_usecs); + void _send_sync(int p_peer, const HashSet<ObjectID> &p_synchronizers, uint16_t p_sync_net_time, uint64_t p_usec); + void _send_delta(int p_peer, const HashSet<ObjectID> &p_synchronizers, uint64_t p_usec, const HashMap<ObjectID, uint64_t> &p_last_watch_usecs); Error _make_spawn_packet(Node *p_node, MultiplayerSpawner *p_spawner, int &r_len); Error _make_despawn_packet(Node *p_node, int &r_len); Error _send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable); diff --git a/modules/navigation/nav_agent.cpp b/modules/navigation/nav_agent.cpp index cb219ac6c0..5a87ff6c4b 100644 --- a/modules/navigation/nav_agent.cpp +++ b/modules/navigation/nav_agent.cpp @@ -326,7 +326,7 @@ const Dictionary NavAgent::get_avoidance_data() const { _avoidance_data["new_velocity"] = Vector3(rvo_agent_3d.newVelocity_.x(), rvo_agent_3d.newVelocity_.y(), rvo_agent_3d.newVelocity_.z()); _avoidance_data["velocity"] = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z()); _avoidance_data["position"] = Vector3(rvo_agent_3d.position_.x(), rvo_agent_3d.position_.y(), rvo_agent_3d.position_.z()); - _avoidance_data["prefered_velocity"] = Vector3(rvo_agent_3d.prefVelocity_.x(), rvo_agent_3d.prefVelocity_.y(), rvo_agent_3d.prefVelocity_.z()); + _avoidance_data["preferred_velocity"] = Vector3(rvo_agent_3d.prefVelocity_.x(), rvo_agent_3d.prefVelocity_.y(), rvo_agent_3d.prefVelocity_.z()); _avoidance_data["radius"] = float(rvo_agent_3d.radius_); _avoidance_data["time_horizon_agents"] = float(rvo_agent_3d.timeHorizon_); _avoidance_data["time_horizon_obstacles"] = 0.0; @@ -341,7 +341,7 @@ const Dictionary NavAgent::get_avoidance_data() const { _avoidance_data["new_velocity"] = Vector3(rvo_agent_2d.newVelocity_.x(), 0.0, rvo_agent_2d.newVelocity_.y()); _avoidance_data["velocity"] = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y()); _avoidance_data["position"] = Vector3(rvo_agent_2d.position_.x(), 0.0, rvo_agent_2d.position_.y()); - _avoidance_data["prefered_velocity"] = Vector3(rvo_agent_2d.prefVelocity_.x(), 0.0, rvo_agent_2d.prefVelocity_.y()); + _avoidance_data["preferred_velocity"] = Vector3(rvo_agent_2d.prefVelocity_.x(), 0.0, rvo_agent_2d.prefVelocity_.y()); _avoidance_data["radius"] = float(rvo_agent_2d.radius_); _avoidance_data["time_horizon_agents"] = float(rvo_agent_2d.timeHorizon_); _avoidance_data["time_horizon_obstacles"] = float(rvo_agent_2d.timeHorizonObst_); diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp index 91e9f7d477..917fa0cd15 100644 --- a/modules/noise/editor/noise_editor_plugin.cpp +++ b/modules/noise/editor/noise_editor_plugin.cpp @@ -36,7 +36,7 @@ #include "../noise_texture_2d.h" #include "editor/editor_inspector.h" -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/button.h" #include "scene/gui/texture_rect.h" diff --git a/modules/noise/noise_texture_2d.cpp b/modules/noise/noise_texture_2d.cpp index 1b0c5cb9e3..0443fec4a0 100644 --- a/modules/noise/noise_texture_2d.cpp +++ b/modules/noise/noise_texture_2d.cpp @@ -49,10 +49,6 @@ NoiseTexture2D::~NoiseTexture2D() { } void NoiseTexture2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture2D::_update_texture); - ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture2D::_generate_texture); - ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture2D::_thread_done); - ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture2D::set_width); ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture2D::set_height); @@ -138,7 +134,7 @@ void NoiseTexture2D::_thread_done(const Ref<Image> &p_image) { void NoiseTexture2D::_thread_function(void *p_ud) { NoiseTexture2D *tex = static_cast<NoiseTexture2D *>(p_ud); - tex->call_deferred(SNAME("_thread_done"), tex->_generate_texture()); + callable_mp(tex, &NoiseTexture2D::_thread_done).call_deferred(tex->_generate_texture()); } void NoiseTexture2D::_queue_update() { @@ -147,7 +143,7 @@ void NoiseTexture2D::_queue_update() { } update_queued = true; - call_deferred(SNAME("_update_texture")); + callable_mp(this, &NoiseTexture2D::_update_texture).call_deferred(); } Ref<Image> NoiseTexture2D::_generate_texture() { diff --git a/modules/noise/noise_texture_3d.cpp b/modules/noise/noise_texture_3d.cpp index 33e257a5c2..f2e01b0612 100644 --- a/modules/noise/noise_texture_3d.cpp +++ b/modules/noise/noise_texture_3d.cpp @@ -49,10 +49,6 @@ NoiseTexture3D::~NoiseTexture3D() { } void NoiseTexture3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture3D::_update_texture); - ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture3D::_generate_texture); - ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture3D::_thread_done); - ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture3D::set_width); ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture3D::set_height); ClassDB::bind_method(D_METHOD("set_depth", "depth"), &NoiseTexture3D::set_depth); @@ -126,7 +122,7 @@ void NoiseTexture3D::_thread_done(const TypedArray<Image> &p_data) { void NoiseTexture3D::_thread_function(void *p_ud) { NoiseTexture3D *tex = static_cast<NoiseTexture3D *>(p_ud); - tex->call_deferred(SNAME("_thread_done"), tex->_generate_texture()); + callable_mp(tex, &NoiseTexture3D::_thread_done).call_deferred(tex->_generate_texture()); } void NoiseTexture3D::_queue_update() { @@ -135,7 +131,7 @@ void NoiseTexture3D::_queue_update() { } update_queued = true; - call_deferred(SNAME("_update_texture")); + callable_mp(this, &NoiseTexture3D::_update_texture).call_deferred(); } TypedArray<Image> NoiseTexture3D::_generate_texture() { diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub index c64b6de78c..4cf810f905 100644 --- a/modules/openxr/SCsub +++ b/modules/openxr/SCsub @@ -120,6 +120,7 @@ env_openxr.add_source_files(module_obj, "extensions/openxr_wmr_controller_extens env_openxr.add_source_files(module_obj, "extensions/openxr_ml2_controller_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_extension_wrapper_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_api_extension.cpp") +env_openxr.add_source_files(module_obj, "extensions/openxr_meta_controller_extension.cpp") env.modules_sources += module_obj diff --git a/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp b/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp index df607b0def..75cfb095bb 100644 --- a/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp @@ -360,6 +360,9 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() { register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbrest touch", "/user/hand/left", "/user/hand/left/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbrest touch", "/user/hand/right", "/user/hand/right/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); register_io_path("/interaction_profiles/oculus/touch_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); diff --git a/modules/openxr/doc_classes/OpenXRHand.xml b/modules/openxr/doc_classes/OpenXRHand.xml index cc7766507f..1c4da83138 100644 --- a/modules/openxr/doc_classes/OpenXRHand.xml +++ b/modules/openxr/doc_classes/OpenXRHand.xml @@ -1,14 +1,20 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="OpenXRHand" inherits="Node3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> - Node supporting finger tracking in OpenXR. + Node supporting hand and finger tracking in OpenXR. </brief_description> <description> - This node enables OpenXR's hand tracking functionality. The node should be a child node of an [XROrigin3D] node, tracking will update its position to where the player's actual hand is positioned. This node also updates the skeleton of a properly skinned hand model. The hand mesh should be a child node of this node. + This node enables OpenXR's hand tracking functionality. The node should be a child node of an [XROrigin3D] node, tracking will update its position to the player's tracked hand Palm joint location (the center of the middle finger's metacarpal bone). This node also updates the skeleton of a properly skinned hand or avatar model. + If the skeleton is a hand (one of the hand bones is the root node of the skeleton), then the skeleton will be placed relative to the hand palm location and the hand mesh and skeleton should be children of the OpenXRHand node. + If the hand bones are part of a full skeleton, then the root of the hand will keep its location with the assumption that IK is used to position the hand and arm. + By default the skeleton hand bones are repositioned to match the size of the tracked hand. To preserve the modeled bone sizes change [member bone_update] to apply rotation only. </description> <tutorials> </tutorials> <members> + <member name="bone_update" type="int" setter="set_bone_update" getter="get_bone_update" enum="OpenXRHand.BoneUpdate" default="0"> + Specify the type of updates to perform on the bone. + </member> <member name="hand" type="int" setter="set_hand" getter="get_hand" enum="OpenXRHand.Hands" default="0"> Specifies whether this node tracks the left or right hand of the player. </member> @@ -18,6 +24,9 @@ <member name="motion_range" type="int" setter="set_motion_range" getter="get_motion_range" enum="OpenXRHand.MotionRange" default="0"> Set the motion range (if supported) limiting the hand motion. </member> + <member name="skeleton_rig" type="int" setter="set_skeleton_rig" getter="get_skeleton_rig" enum="OpenXRHand.SkeletonRig" default="0"> + Set the type of skeleton rig the [member hand_skeleton] is compliant with. + </member> </members> <constants> <constant name="HAND_LEFT" value="0" enum="Hands"> @@ -38,5 +47,23 @@ <constant name="MOTION_RANGE_MAX" value="2" enum="MotionRange"> Maximum supported motion ranges. </constant> + <constant name="SKELETON_RIG_OPENXR" value="0" enum="SkeletonRig"> + An OpenXR compliant skeleton. + </constant> + <constant name="SKELETON_RIG_HUMANOID" value="1" enum="SkeletonRig"> + A [SkeletonProfileHumanoid] compliant skeleton. + </constant> + <constant name="SKELETON_RIG_MAX" value="2" enum="SkeletonRig"> + Maximum supported hands. + </constant> + <constant name="BONE_UPDATE_FULL" value="0" enum="BoneUpdate"> + The skeletons bones are fully updated (both position and rotation) to match the tracked bones. + </constant> + <constant name="BONE_UPDATE_ROTATION_ONLY" value="1" enum="BoneUpdate"> + The skeletons bones are only rotated to align with the tracked bones, preserving bone length. + </constant> + <constant name="BONE_UPDATE_MAX" value="2" enum="BoneUpdate"> + Maximum supported bone update mode. + </constant> </constants> </class> diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml index 666d20d7e7..caaaeb90ff 100644 --- a/modules/openxr/doc_classes/OpenXRInterface.xml +++ b/modules/openxr/doc_classes/OpenXRInterface.xml @@ -71,6 +71,13 @@ If handtracking is enabled, returns the rotation of a joint ([param joint]) of a hand ([param hand]) as provided by OpenXR. </description> </method> + <method name="get_hand_tracking_source" qualifiers="const"> + <return type="int" enum="OpenXRInterface.HandTrackedSource" /> + <param index="0" name="hand" type="int" enum="OpenXRInterface.Hand" /> + <description> + If handtracking is enabled and hand tracking source is supported, gets the source of the hand tracking data for [param hand]. + </description> + </method> <method name="get_motion_range" qualifiers="const"> <return type="int" enum="OpenXRInterface.HandMotionRange" /> <param index="0" name="hand" type="int" enum="OpenXRInterface.Hand" /> @@ -177,10 +184,25 @@ Maximum value for the hand enum. </constant> <constant name="HAND_MOTION_RANGE_UNOBSTRUCTED" value="0" enum="HandMotionRange"> + Full hand range, if user closes their hands, we make a full fist. </constant> <constant name="HAND_MOTION_RANGE_CONFORM_TO_CONTROLLER" value="1" enum="HandMotionRange"> + Conform to controller, if user closes their hands, the tracked data conforms to the shape of the controller. </constant> <constant name="HAND_MOTION_RANGE_MAX" value="2" enum="HandMotionRange"> + Maximum value for the motion range enum. + </constant> + <constant name="HAND_TRACKED_SOURCE_UNKNOWN" value="0" enum="HandTrackedSource"> + The source of hand tracking data is unknown (the extension is likely unsupported). + </constant> + <constant name="HAND_TRACKED_SOURCE_UNOBSTRUCTED" value="1" enum="HandTrackedSource"> + The source of hand tracking is unobstructed, this means that an accurate method of hand tracking is used, e.g. optical hand tracking, data gloves, etc. + </constant> + <constant name="HAND_TRACKED_SOURCE_CONTROLLER" value="2" enum="HandTrackedSource"> + The source of hand tracking is a controller, bone positions are inferred from controller inputs. + </constant> + <constant name="HAND_TRACKED_SOURCE_MAX" value="3" enum="HandTrackedSource"> + Maximum value for the hand tracked source enum. </constant> <constant name="HAND_JOINT_PALM" value="0" enum="HandJoints"> Palm joint. diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp index 64e07eff21..15468a1c67 100644 --- a/modules/openxr/editor/openxr_action_map_editor.cpp +++ b/modules/openxr/editor/openxr_action_map_editor.cpp @@ -32,9 +32,9 @@ #include "core/config/project_settings.h" #include "editor/editor_node.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/themes/editor_scale.h" // TODO implement redo/undo system @@ -43,7 +43,6 @@ void OpenXRActionMapEditor::_bind_methods() { ClassDB::bind_method("_add_interaction_profile_editor", &OpenXRActionMapEditor::_add_interaction_profile_editor); ClassDB::bind_method(D_METHOD("_add_action_set", "name"), &OpenXRActionMapEditor::_add_action_set); - ClassDB::bind_method(D_METHOD("_set_focus_on_action_set", "action_set"), &OpenXRActionMapEditor::_set_focus_on_action_set); ClassDB::bind_method(D_METHOD("_remove_action_set", "name"), &OpenXRActionMapEditor::_remove_action_set); ClassDB::bind_method(D_METHOD("_do_add_action_set_editor", "action_set_editor"), &OpenXRActionMapEditor::_do_add_action_set_editor); @@ -175,7 +174,7 @@ void OpenXRActionMapEditor::_on_add_action_set() { // Make sure our action set is the current tab tabs->set_current_tab(0); - call_deferred("_set_focus_on_action_set", new_action_set_editor); + callable_mp(this, &OpenXRActionMapEditor::_set_focus_on_action_set).call_deferred(new_action_set_editor); } void OpenXRActionMapEditor::_set_focus_on_action_set(OpenXRActionSetEditor *p_action_set_editor) { diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp index 08fcdaf771..51642d8503 100644 --- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp +++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp @@ -77,7 +77,7 @@ void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_inclu // in with the new PackedStringArray interaction_profiles = OpenXRInteractionProfileMetadata::get_singleton()->get_interaction_profile_paths(); for (int i = 0; i < interaction_profiles.size(); i++) { - String path = interaction_profiles[i]; + const String &path = interaction_profiles[i]; if (!p_do_not_include.has(path)) { Button *ip_button = memnew(Button); ip_button->set_flat(true); diff --git a/modules/openxr/extensions/openxr_fb_update_swapchain_extension.cpp b/modules/openxr/extensions/openxr_fb_update_swapchain_extension.cpp index 1289183ea4..c3f692185b 100644 --- a/modules/openxr/extensions/openxr_fb_update_swapchain_extension.cpp +++ b/modules/openxr/extensions/openxr_fb_update_swapchain_extension.cpp @@ -30,7 +30,7 @@ #include "openxr_fb_update_swapchain_extension.h" -// always include this as late as possible +// Always include this as late as possible. #include "../openxr_platform_inc.h" OpenXRFBUpdateSwapchainExtension *OpenXRFBUpdateSwapchainExtension::singleton = nullptr; diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp index 0d667b56c6..04fc4bf890 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp @@ -60,6 +60,7 @@ HashMap<String, bool *> OpenXRHandTrackingExtension::get_requested_extensions() request_extensions[XR_EXT_HAND_TRACKING_EXTENSION_NAME] = &hand_tracking_ext; request_extensions[XR_EXT_HAND_JOINTS_MOTION_RANGE_EXTENSION_NAME] = &hand_motion_range_ext; + request_extensions[XR_EXT_HAND_TRACKING_DATA_SOURCE_EXTENSION_NAME] = &hand_tracking_source_ext; return request_extensions; } @@ -137,20 +138,32 @@ void OpenXRHandTrackingExtension::on_process() { for (int i = 0; i < OPENXR_MAX_TRACKED_HANDS; i++) { if (hand_trackers[i].hand_tracker == XR_NULL_HANDLE) { - XrHandTrackerCreateInfoEXT createInfo = { + void *next_pointer = nullptr; + + // Originally not all XR runtimes supported hand tracking data sourced both from controllers and normal hand tracking. + // With this extension we can indicate we accept input from both sources so hand tracking data is consistently provided + // on runtimes that support this. + XrHandTrackingDataSourceEXT data_sources[2] = { XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT, XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT }; + XrHandTrackingDataSourceInfoEXT data_source_info = { XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT, next_pointer, 2, data_sources }; + if (hand_tracking_source_ext) { + // If supported include this info + next_pointer = &data_source_info; + } + + XrHandTrackerCreateInfoEXT create_info = { XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT, // type - nullptr, // next + next_pointer, // next i == 0 ? XR_HAND_LEFT_EXT : XR_HAND_RIGHT_EXT, // hand XR_HAND_JOINT_SET_DEFAULT_EXT, // handJointSet }; - result = xrCreateHandTrackerEXT(OpenXRAPI::get_singleton()->get_session(), &createInfo, &hand_trackers[i].hand_tracker); + result = xrCreateHandTrackerEXT(OpenXRAPI::get_singleton()->get_session(), &create_info, &hand_trackers[i].hand_tracker); if (XR_FAILED(result)) { // not successful? then we do nothing. print_line("OpenXR: Failed to obtain hand tracking information [", OpenXRAPI::get_singleton()->get_error_string(result), "]"); hand_trackers[i].is_initialized = false; } else { - void *next_pointer = nullptr; + next_pointer = nullptr; hand_trackers[i].velocities.type = XR_TYPE_HAND_JOINT_VELOCITIES_EXT; hand_trackers[i].velocities.next = next_pointer; @@ -158,6 +171,14 @@ void OpenXRHandTrackingExtension::on_process() { hand_trackers[i].velocities.jointVelocities = hand_trackers[i].joint_velocities; next_pointer = &hand_trackers[i].velocities; + if (hand_tracking_source_ext) { + hand_trackers[i].data_source.type = XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT; + hand_trackers[i].data_source.next = next_pointer; + hand_trackers[i].data_source.isActive = false; + hand_trackers[i].data_source.dataSource = XrHandTrackingDataSourceEXT(0); + next_pointer = &hand_trackers[i].data_source; + } + hand_trackers[i].locations.type = XR_TYPE_HAND_JOINT_LOCATIONS_EXT; hand_trackers[i].locations.next = next_pointer; hand_trackers[i].locations.isActive = false; @@ -171,14 +192,9 @@ void OpenXRHandTrackingExtension::on_process() { if (hand_trackers[i].is_initialized) { void *next_pointer = nullptr; - XrHandJointsMotionRangeInfoEXT motionRangeInfo; - + XrHandJointsMotionRangeInfoEXT motion_range_info = { XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT, next_pointer, hand_trackers[i].motion_range }; if (hand_motion_range_ext) { - motionRangeInfo.type = XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT; - motionRangeInfo.next = next_pointer; - motionRangeInfo.handJointsMotionRange = hand_trackers[i].motion_range; - - next_pointer = &motionRangeInfo; + next_pointer = &motion_range_info; } XrHandJointsLocateInfoEXT locateInfo = { @@ -240,6 +256,25 @@ XrHandJointsMotionRangeEXT OpenXRHandTrackingExtension::get_motion_range(HandTra return hand_trackers[p_hand].motion_range; } +OpenXRHandTrackingExtension::HandTrackedSource OpenXRHandTrackingExtension::get_hand_tracking_source(HandTrackedHands p_hand) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, OPENXR_SOURCE_UNKNOWN); + + if (hand_tracking_source_ext && hand_trackers[p_hand].data_source.isActive) { + switch (hand_trackers[p_hand].data_source.dataSource) { + case XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT: + return OPENXR_SOURCE_UNOBSTRUCTED; + + case XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT: + return OPENXR_SOURCE_CONTROLLER; + + default: + return OPENXR_SOURCE_UNKNOWN; + } + } + + return OPENXR_SOURCE_UNKNOWN; +} + void OpenXRHandTrackingExtension::set_motion_range(HandTrackedHands p_hand, XrHandJointsMotionRangeEXT p_motion_range) { ERR_FAIL_UNSIGNED_INDEX(p_hand, OPENXR_MAX_TRACKED_HANDS); hand_trackers[p_hand].motion_range = p_motion_range; diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.h b/modules/openxr/extensions/openxr_hand_tracking_extension.h index f9b26fd604..967538b377 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.h +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.h @@ -43,9 +43,17 @@ public: OPENXR_MAX_TRACKED_HANDS }; + enum HandTrackedSource { + OPENXR_SOURCE_UNKNOWN, + OPENXR_SOURCE_UNOBSTRUCTED, + OPENXR_SOURCE_CONTROLLER, + OPENXR_SOURCE_MAX + }; + struct HandTracker { bool is_initialized = false; XrHandJointsMotionRangeEXT motion_range = XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT; + HandTrackedSource source = OPENXR_SOURCE_UNKNOWN; XrHandTrackerEXT hand_tracker = XR_NULL_HANDLE; XrHandJointLocationEXT joint_locations[XR_HAND_JOINT_COUNT_EXT]; @@ -53,6 +61,7 @@ public: XrHandJointVelocitiesEXT velocities; XrHandJointLocationsEXT locations; + XrHandTrackingDataSourceStateEXT data_source; }; static OpenXRHandTrackingExtension *get_singleton(); @@ -77,6 +86,8 @@ public: XrHandJointsMotionRangeEXT get_motion_range(HandTrackedHands p_hand) const; void set_motion_range(HandTrackedHands p_hand, XrHandJointsMotionRangeEXT p_motion_range); + HandTrackedSource get_hand_tracking_source(HandTrackedHands p_hand) const; + XrSpaceLocationFlags get_hand_joint_location_flags(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; Quaternion get_hand_joint_rotation(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; Vector3 get_hand_joint_position(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; @@ -96,6 +107,7 @@ private: // related extensions bool hand_tracking_ext = false; bool hand_motion_range_ext = false; + bool hand_tracking_source_ext = false; // functions void cleanup_hand_tracking(); diff --git a/modules/openxr/extensions/openxr_meta_controller_extension.cpp b/modules/openxr/extensions/openxr_meta_controller_extension.cpp new file mode 100644 index 0000000000..72dc74bf64 --- /dev/null +++ b/modules/openxr/extensions/openxr_meta_controller_extension.cpp @@ -0,0 +1,184 @@ +/**************************************************************************/ +/* openxr_meta_controller_extension.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "openxr_meta_controller_extension.h" + +#include "../action_map/openxr_interaction_profile_metadata.h" + +HashMap<String, bool *> OpenXRMetaControllerExtension::get_requested_extensions() { + HashMap<String, bool *> request_extensions; + + request_extensions[XR_FB_TOUCH_CONTROLLER_PROXIMITY_EXTENSION_NAME] = &available[META_TOUCH_PROXIMITY]; + request_extensions[XR_FB_TOUCH_CONTROLLER_PRO_EXTENSION_NAME] = &available[META_TOUCH_PRO]; + request_extensions[XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME] = &available[META_TOUCH_PLUS]; + + return request_extensions; +} + +bool OpenXRMetaControllerExtension::is_available(MetaControllers p_type) { + return available[p_type]; +} + +void OpenXRMetaControllerExtension::on_register_metadata() { + OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton(); + ERR_FAIL_NULL(metadata); + + // Note, we register controllers regardless if they are supported on the current hardware. + + // Normal touch controller is part of the core spec, but we do have some extensions. + metadata->register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger proximity", "/user/hand/left", "/user/hand/left/input/trigger/proximity_fb ", "XR_FB_touch_controller_proximity", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger proximity", "/user/hand/right", "/user/hand/right/input/trigger/proximity_fb ", "XR_FB_touch_controller_proximity", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/oculus/touch_controller", "Thumb proximity", "/user/hand/left", "/user/hand/left/input/thumb_fb/proximity_fb ", "XR_FB_touch_controller_proximity", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/oculus/touch_controller", "Thumb proximity", "/user/hand/right", "/user/hand/right/input/thumb_fb/proximity_fb ", "XR_FB_touch_controller_proximity", OpenXRAction::OPENXR_ACTION_BOOL); + + // Touch controller pro (Quest Pro) + metadata->register_interaction_profile("Touch controller pro", "/interaction_profiles/facebook/touch_controller_pro", "XR_FB_touch_controller_pro"); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "X touch", "/user/hand/left", "/user/hand/left/input/x/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Y touch", "/user/hand/left", "/user/hand/left/input/y/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger proximity", "/user/hand/left", "/user/hand/left/input/trigger/proximity_fb", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger curl", "/user/hand/left", "/user/hand/left/input/trigger/curl_fb", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger slide", "/user/hand/left", "/user/hand/left/input/trigger/slide_fb", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger force", "/user/hand/left", "/user/hand/left/input/trigger/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger proximity", "/user/hand/right", "/user/hand/right/input/trigger/proximity_fb", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger curl", "/user/hand/right", "/user/hand/right/input/trigger/curl_fb", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger slide", "/user/hand/right", "/user/hand/right/input/trigger/slide_fb", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Trigger force", "/user/hand/right", "/user/hand/right/input/trigger/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumb proximity", "/user/hand/left", "/user/hand/left/input/thumb_fb/proximity_fb", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumb proximity", "/user/hand/right", "/user/hand/right/input/thumb_fb/proximity_fb", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick X", "/user/hand/left", "/user/hand/left/input/thumbstick/x", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick Y", "/user/hand/left", "/user/hand/left/input/thumbstick/y", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick X", "/user/hand/right", "/user/hand/right/input/thumbstick/x", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick Y", "/user/hand/right", "/user/hand/right/input/thumbstick/y", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbrest touch", "/user/hand/left", "/user/hand/left/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbrest force", "/user/hand/left", "/user/hand/left/input/thumbrest/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbrest touch", "/user/hand/right", "/user/hand/right/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Thumbrest force", "/user/hand/right", "/user/hand/right/input/thumbrest/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Stylus force", "/user/hand/left", "/user/hand/left/input/stylus_fb/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Stylus force", "/user/hand/right", "/user/hand/right/input/stylus_fb/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Haptic trigger output", "/user/hand/left", "/user/hand/left/output/haptic_trigger_fb", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Haptic thumb output", "/user/hand/left", "/user/hand/left/output/haptic_thumb_fb", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Haptic trigger output", "/user/hand/right", "/user/hand/right/output/haptic_trigger_fb", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + metadata->register_io_path("/interaction_profiles/facebook/touch_controller_pro", "Haptic thumb output", "/user/hand/right", "/user/hand/right/output/haptic_thumb_fb", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // Touch controller plus (Quest 3) + metadata->register_interaction_profile("Touch controller plus", "/interaction_profiles/meta/touch_controller_plus", "XR_META_touch_controller_plus"); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "X touch", "/user/hand/left", "/user/hand/left/input/x/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Y touch", "/user/hand/left", "/user/hand/left/input/y/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger proximity", "/user/hand/left", "/user/hand/left/input/trigger/proximity_meta", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger curl", "/user/hand/left", "/user/hand/left/input/trigger/curl_meta", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger slide", "/user/hand/left", "/user/hand/left/input/trigger/slide_meta", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger force", "/user/hand/left", "/user/hand/left/input/trigger/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger proximity", "/user/hand/right", "/user/hand/right/input/trigger/proximity_meta", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger curl", "/user/hand/right", "/user/hand/right/input/trigger/curl_meta", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger slide", "/user/hand/right", "/user/hand/right/input/trigger/slide_meta", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Trigger force", "/user/hand/right", "/user/hand/right/input/trigger/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumb proximity", "/user/hand/left", "/user/hand/left/input/thumb_meta/proximity_meta", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumb proximity", "/user/hand/right", "/user/hand/right/input/thumb_meta/proximity_meta", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick X", "/user/hand/left", "/user/hand/left/input/thumbstick/x", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick Y", "/user/hand/left", "/user/hand/left/input/thumbstick/y", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick X", "/user/hand/right", "/user/hand/right/input/thumbstick/x", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick Y", "/user/hand/right", "/user/hand/right/input/thumbstick/y", "", OpenXRAction::OPENXR_ACTION_FLOAT); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbrest touch", "/user/hand/left", "/user/hand/left/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Thumbrest touch", "/user/hand/right", "/user/hand/right/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + metadata->register_io_path("/interaction_profiles/meta/touch_controller_plus", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); +} diff --git a/modules/openxr/extensions/openxr_meta_controller_extension.h b/modules/openxr/extensions/openxr_meta_controller_extension.h new file mode 100644 index 0000000000..7a60d2a0b9 --- /dev/null +++ b/modules/openxr/extensions/openxr_meta_controller_extension.h @@ -0,0 +1,55 @@ +/**************************************************************************/ +/* openxr_meta_controller_extension.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef OPENXR_META_CONTROLLER_EXTENSION_H +#define OPENXR_META_CONTROLLER_EXTENSION_H + +#include "openxr_extension_wrapper.h" + +class OpenXRMetaControllerExtension : public OpenXRExtensionWrapper { +public: + enum MetaControllers { + META_TOUCH_PROXIMITY, // Proximity extensions for normal touch controllers + META_TOUCH_PRO, // Touch controller for the Quest Pro + META_TOUCH_PLUS, // Touch controller for the Quest Plus + META_MAX_CONTROLLERS + }; + + virtual HashMap<String, bool *> get_requested_extensions() override; + + bool is_available(MetaControllers p_type); + + virtual void on_register_metadata() override; + +private: + bool available[META_MAX_CONTROLLERS] = { false, false, false }; +}; + +#endif // OPENXR_META_CONTROLLER_EXTENSION_H diff --git a/modules/openxr/extensions/openxr_opengl_extension.h b/modules/openxr/extensions/openxr_opengl_extension.h index 3b0aa0bce9..5f529829a7 100644 --- a/modules/openxr/extensions/openxr_opengl_extension.h +++ b/modules/openxr/extensions/openxr_opengl_extension.h @@ -39,7 +39,7 @@ #include "core/templates/vector.h" -// always include this as late as possible +// Always include this as late as possible. #include "../openxr_platform_inc.h" class OpenXROpenGLExtension : public OpenXRGraphicsExtensionWrapper { @@ -65,9 +65,9 @@ private: #ifdef WIN32 static XrGraphicsBindingOpenGLWin32KHR graphics_binding_gl; -#elif ANDROID_ENABLED +#elif defined(ANDROID_ENABLED) static XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl; -#else +#else // Linux/X11 static XrGraphicsBindingOpenGLXlibKHR graphics_binding_gl; #endif diff --git a/modules/openxr/extensions/openxr_vulkan_extension.h b/modules/openxr/extensions/openxr_vulkan_extension.h index f31621fda0..86c0f327dd 100644 --- a/modules/openxr/extensions/openxr_vulkan_extension.h +++ b/modules/openxr/extensions/openxr_vulkan_extension.h @@ -37,7 +37,7 @@ #include "core/templates/vector.h" -// always include this as late as possible +// Always include this as late as possible. #include "../openxr_platform_inc.h" class OpenXRVulkanExtension : public OpenXRGraphicsExtensionWrapper, VulkanHooks { diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 66f8192c9e..ceeb1b0278 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -77,6 +77,8 @@ void OpenXRInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("set_motion_range", "hand", "motion_range"), &OpenXRInterface::set_motion_range); ClassDB::bind_method(D_METHOD("get_motion_range", "hand"), &OpenXRInterface::get_motion_range); + ClassDB::bind_method(D_METHOD("get_hand_tracking_source", "hand"), &OpenXRInterface::get_hand_tracking_source); + ClassDB::bind_method(D_METHOD("get_hand_joint_flags", "hand", "joint"), &OpenXRInterface::get_hand_joint_flags); ClassDB::bind_method(D_METHOD("get_hand_joint_rotation", "hand", "joint"), &OpenXRInterface::get_hand_joint_rotation); @@ -97,6 +99,11 @@ void OpenXRInterface::_bind_methods() { BIND_ENUM_CONSTANT(HAND_MOTION_RANGE_CONFORM_TO_CONTROLLER); BIND_ENUM_CONSTANT(HAND_MOTION_RANGE_MAX); + BIND_ENUM_CONSTANT(HAND_TRACKED_SOURCE_UNKNOWN); + BIND_ENUM_CONSTANT(HAND_TRACKED_SOURCE_UNOBSTRUCTED); + BIND_ENUM_CONSTANT(HAND_TRACKED_SOURCE_CONTROLLER); + BIND_ENUM_CONSTANT(HAND_TRACKED_SOURCE_MAX); + BIND_ENUM_CONSTANT(HAND_JOINT_PALM); BIND_ENUM_CONSTANT(HAND_JOINT_WRIST); BIND_ENUM_CONSTANT(HAND_JOINT_THUMB_METACARPAL); @@ -1269,6 +1276,27 @@ OpenXRInterface::HandMotionRange OpenXRInterface::get_motion_range(const Hand p_ return HAND_MOTION_RANGE_MAX; } +OpenXRInterface::HandTrackedSource OpenXRInterface::get_hand_tracking_source(const Hand p_hand) const { + ERR_FAIL_INDEX_V(p_hand, HAND_MAX, HAND_TRACKED_SOURCE_UNKNOWN); + + OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); + if (hand_tracking_ext && hand_tracking_ext->get_active()) { + OpenXRHandTrackingExtension::HandTrackedSource source = hand_tracking_ext->get_hand_tracking_source(OpenXRHandTrackingExtension::HandTrackedHands(p_hand)); + switch (source) { + case OpenXRHandTrackingExtension::OPENXR_SOURCE_UNOBSTRUCTED: + return HAND_TRACKED_SOURCE_UNOBSTRUCTED; + case OpenXRHandTrackingExtension::OPENXR_SOURCE_CONTROLLER: + return HAND_TRACKED_SOURCE_CONTROLLER; + case OpenXRHandTrackingExtension::OPENXR_SOURCE_UNKNOWN: + return HAND_TRACKED_SOURCE_UNKNOWN; + default: + ERR_FAIL_V_MSG(HAND_TRACKED_SOURCE_UNKNOWN, "Unknown hand tracking source returned by OpenXR"); + } + } + + return HAND_TRACKED_SOURCE_UNKNOWN; +} + BitField<OpenXRInterface::HandJointFlags> OpenXRInterface::get_hand_joint_flags(Hand p_hand, HandJoints p_joint) const { BitField<OpenXRInterface::HandJointFlags> bits; diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index 489d0845ba..ca95fdf04d 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -194,6 +194,15 @@ public: void set_motion_range(const Hand p_hand, const HandMotionRange p_motion_range); HandMotionRange get_motion_range(const Hand p_hand) const; + enum HandTrackedSource { + HAND_TRACKED_SOURCE_UNKNOWN, + HAND_TRACKED_SOURCE_UNOBSTRUCTED, + HAND_TRACKED_SOURCE_CONTROLLER, + HAND_TRACKED_SOURCE_MAX + }; + + HandTrackedSource get_hand_tracking_source(const Hand p_hand) const; + enum HandJoints { HAND_JOINT_PALM = 0, HAND_JOINT_WRIST = 1, @@ -248,6 +257,7 @@ public: VARIANT_ENUM_CAST(OpenXRInterface::Hand) VARIANT_ENUM_CAST(OpenXRInterface::HandMotionRange) +VARIANT_ENUM_CAST(OpenXRInterface::HandTrackedSource) VARIANT_ENUM_CAST(OpenXRInterface::HandJoints) VARIANT_BITFIELD_CAST(OpenXRInterface::HandJointFlags) diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp index 544932bdeb..5cc793dca3 100644 --- a/modules/openxr/register_types.cpp +++ b/modules/openxr/register_types.cpp @@ -49,6 +49,7 @@ #include "extensions/openxr_htc_controller_extension.h" #include "extensions/openxr_htc_vive_tracker_extension.h" #include "extensions/openxr_huawei_controller_extension.h" +#include "extensions/openxr_meta_controller_extension.h" #include "extensions/openxr_ml2_controller_extension.h" #include "extensions/openxr_palm_pose_extension.h" #include "extensions/openxr_pico_controller_extension.h" @@ -115,6 +116,7 @@ void initialize_openxr_module(ModuleInitializationLevel p_level) { OpenXRAPI::register_extension_wrapper(memnew(OpenXRDisplayRefreshRateExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRWMRControllerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRML2ControllerExtension)); + OpenXRAPI::register_extension_wrapper(memnew(OpenXRMetaControllerExtension)); // register gated extensions if (GLOBAL_GET("xr/openxr/extensions/eye_gaze_interaction") && (!OS::get_singleton()->has_feature("mobile") || OS::get_singleton()->has_feature(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME))) { diff --git a/modules/openxr/scene/openxr_hand.cpp b/modules/openxr/scene/openxr_hand.cpp index c48fac8055..2a4104f6ee 100644 --- a/modules/openxr/scene/openxr_hand.cpp +++ b/modules/openxr/scene/openxr_hand.cpp @@ -46,9 +46,17 @@ void OpenXRHand::_bind_methods() { ClassDB::bind_method(D_METHOD("set_motion_range", "motion_range"), &OpenXRHand::set_motion_range); ClassDB::bind_method(D_METHOD("get_motion_range"), &OpenXRHand::get_motion_range); + ClassDB::bind_method(D_METHOD("set_skeleton_rig", "skeleton_rig"), &OpenXRHand::set_skeleton_rig); + ClassDB::bind_method(D_METHOD("get_skeleton_rig"), &OpenXRHand::get_skeleton_rig); + + ClassDB::bind_method(D_METHOD("set_bone_update", "bone_update"), &OpenXRHand::set_bone_update); + ClassDB::bind_method(D_METHOD("get_bone_update"), &OpenXRHand::get_bone_update); + ADD_PROPERTY(PropertyInfo(Variant::INT, "hand", PROPERTY_HINT_ENUM, "Left,Right"), "set_hand", "get_hand"); ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_range", PROPERTY_HINT_ENUM, "Unobstructed,Conform to controller"), "set_motion_range", "get_motion_range"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "hand_skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton3D"), "set_hand_skeleton", "get_hand_skeleton"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "skeleton_rig", PROPERTY_HINT_ENUM, "OpenXR,Humanoid"), "set_skeleton_rig", "get_skeleton_rig"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_update", PROPERTY_HINT_ENUM, "Full,Rotation Only"), "set_bone_update", "get_bone_update"); BIND_ENUM_CONSTANT(HAND_LEFT); BIND_ENUM_CONSTANT(HAND_RIGHT); @@ -57,6 +65,14 @@ void OpenXRHand::_bind_methods() { BIND_ENUM_CONSTANT(MOTION_RANGE_UNOBSTRUCTED); BIND_ENUM_CONSTANT(MOTION_RANGE_CONFORM_TO_CONTROLLER); BIND_ENUM_CONSTANT(MOTION_RANGE_MAX); + + BIND_ENUM_CONSTANT(SKELETON_RIG_OPENXR); + BIND_ENUM_CONSTANT(SKELETON_RIG_HUMANOID); + BIND_ENUM_CONSTANT(SKELETON_RIG_MAX); + + BIND_ENUM_CONSTANT(BONE_UPDATE_FULL); + BIND_ENUM_CONSTANT(BONE_UPDATE_ROTATION_ONLY); + BIND_ENUM_CONSTANT(BONE_UPDATE_MAX); } OpenXRHand::OpenXRHand() { @@ -64,7 +80,7 @@ OpenXRHand::OpenXRHand() { hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); } -void OpenXRHand::set_hand(const Hands p_hand) { +void OpenXRHand::set_hand(Hands p_hand) { ERR_FAIL_INDEX(p_hand, HAND_MAX); hand = p_hand; @@ -80,7 +96,7 @@ void OpenXRHand::set_hand_skeleton(const NodePath &p_hand_skeleton) { // TODO if inside tree call _get_bones() } -void OpenXRHand::set_motion_range(const MotionRange p_motion_range) { +void OpenXRHand::set_motion_range(MotionRange p_motion_range) { ERR_FAIL_INDEX(p_motion_range, MOTION_RANGE_MAX); motion_range = p_motion_range; @@ -116,6 +132,26 @@ void OpenXRHand::_set_motion_range() { hand_tracking_ext->set_motion_range(OpenXRHandTrackingExtension::HandTrackedHands(hand), xr_motion_range); } +void OpenXRHand::set_skeleton_rig(SkeletonRig p_skeleton_rig) { + ERR_FAIL_INDEX(p_skeleton_rig, SKELETON_RIG_MAX); + + skeleton_rig = p_skeleton_rig; +} + +OpenXRHand::SkeletonRig OpenXRHand::get_skeleton_rig() const { + return skeleton_rig; +} + +void OpenXRHand::set_bone_update(BoneUpdate p_bone_update) { + ERR_FAIL_INDEX(p_bone_update, BONE_UPDATE_MAX); + + bone_update = p_bone_update; +} + +OpenXRHand::BoneUpdate OpenXRHand::get_bone_update() const { + return bone_update; +} + Skeleton3D *OpenXRHand::get_skeleton() { if (!has_node(hand_skeleton)) { return nullptr; @@ -130,39 +166,81 @@ Skeleton3D *OpenXRHand::get_skeleton() { return skeleton; } -void OpenXRHand::_get_bones() { - const char *bone_names[XR_HAND_JOINT_COUNT_EXT] = { - "Palm", - "Wrist", - "Thumb_Metacarpal", - "Thumb_Proximal", - "Thumb_Distal", - "Thumb_Tip", - "Index_Metacarpal", - "Index_Proximal", - "Index_Intermediate", - "Index_Distal", - "Index_Tip", - "Middle_Metacarpal", - "Middle_Proximal", - "Middle_Intermediate", - "Middle_Distal", - "Middle_Tip", - "Ring_Metacarpal", - "Ring_Proximal", - "Ring_Intermediate", - "Ring_Distal", - "Ring_Tip", - "Little_Metacarpal", - "Little_Proximal", - "Little_Intermediate", - "Little_Distal", - "Little_Tip", +void OpenXRHand::_get_joint_data() { + // Table of bone names for different rig types. + static const String bone_names[SKELETON_RIG_MAX][XR_HAND_JOINT_COUNT_EXT] = { + // SKELETON_RIG_OPENXR bone names. + { + "Palm", + "Wrist", + "Thumb_Metacarpal", + "Thumb_Proximal", + "Thumb_Distal", + "Thumb_Tip", + "Index_Metacarpal", + "Index_Proximal", + "Index_Intermediate", + "Index_Distal", + "Index_Tip", + "Middle_Metacarpal", + "Middle_Proximal", + "Middle_Intermediate", + "Middle_Distal", + "Middle_Tip", + "Ring_Metacarpal", + "Ring_Proximal", + "Ring_Intermediate", + "Ring_Distal", + "Ring_Tip", + "Little_Metacarpal", + "Little_Proximal", + "Little_Intermediate", + "Little_Distal", + "Little_Tip" }, + + // SKELETON_RIG_HUMANOID bone names. + { + "Palm", + "Hand", + "ThumbMetacarpal", + "ThumbProximal", + "ThumbDistal", + "ThumbTip", + "IndexMetacarpal", + "IndexProximal", + "IndexIntermediate", + "IndexDistal", + "IndexTip", + "MiddleMetacarpal", + "MiddleProximal", + "MiddleIntermediate", + "MiddleDistal", + "MiddleTip", + "RingMetacarpal", + "RingProximal", + "RingIntermediate", + "RingDistal", + "RingTip", + "LittleMetacarpal", + "LittleProximal", + "LittleIntermediate", + "LittleDistal", + "LittleTip" } + }; + + // Table of bone name formats for different rig types and left/right hands. + static const String bone_name_formats[SKELETON_RIG_MAX][2] = { + // SKELETON_RIG_OPENXR bone name format. + { "<bone>_L", "<bone>_R" }, + + // SKELETON_RIG_HUMANOID bone name format. + { "Left<bone>", "Right<bone>" } }; // reset JIC for (int i = 0; i < XR_HAND_JOINT_COUNT_EXT; i++) { - bones[i] = -1; + joints[i].bone = -1; + joints[i].parent_joint = -1; } Skeleton3D *skeleton = get_skeleton(); @@ -170,20 +248,46 @@ void OpenXRHand::_get_bones() { return; } - // We cast to spatials which should allow us to use any subclass of that. + // Find the skeleton-bones associated with each OpenXR joint. + int bones[XR_HAND_JOINT_COUNT_EXT]; for (int i = 0; i < XR_HAND_JOINT_COUNT_EXT; i++) { - String bone_name = bone_names[i]; - if (hand == 0) { - bone_name += String("_L"); - } else { - bone_name += String("_R"); - } + // Construct the expected bone name. + String bone_name = bone_name_formats[skeleton_rig][hand].replace("<bone>", bone_names[skeleton_rig][i]); + // Find the skeleton bone. bones[i] = skeleton->find_bone(bone_name); if (bones[i] == -1) { print_line("Couldn't obtain bone for", bone_name); } } + + // Assemble the OpenXR joint relationship to the available skeleton bones. + for (int i = 0; i < XR_HAND_JOINT_COUNT_EXT; i++) { + // Get the skeleton bone (skip if not found). + const int bone = bones[i]; + if (bone == -1) { + continue; + } + + // Find the parent skeleton-bone. + const int parent_bone = skeleton->get_bone_parent(bone); + if (parent_bone == -1) { + // If no parent skeleton-bone exists then drive this relative to palm joint. + joints[i].bone = bone; + joints[i].parent_joint = XR_HAND_JOINT_PALM_EXT; + continue; + } + + // Find the OpenXR joint associated with the parent skeleton-bone. + for (int j = 0; j < XR_HAND_JOINT_COUNT_EXT; ++j) { + if (bones[j] == parent_bone) { + // If a parent joint is found then drive this bone relative to it. + joints[i].bone = bone; + joints[i].parent_joint = j; + break; + } + } + } } void OpenXRHand::_update_skeleton() { @@ -198,12 +302,25 @@ void OpenXRHand::_update_skeleton() { return; } + // Table of bone adjustments for different rig types + static const Quaternion bone_adjustments[SKELETON_RIG_MAX] = { + // SKELETON_RIG_OPENXR bone adjustment. This is an identity quaternion + // because the incoming quaternions are already in OpenXR format. + Quaternion(), + + // SKELETON_RIG_HUMANOID bone adjustment. This rotation performs: + // OpenXR Z+ -> Godot Humanoid Y- (Back along the bone) + // OpenXR Y+ -> Godot Humanoid Z- (Out the back of the hand) + Quaternion(0.0, -Math_SQRT12, Math_SQRT12, 0.0), + }; + // we cache our transforms so we can quickly calculate local transforms XRPose::TrackingConfidence confidences[XR_HAND_JOINT_COUNT_EXT]; Quaternion quaternions[XR_HAND_JOINT_COUNT_EXT]; Quaternion inv_quaternions[XR_HAND_JOINT_COUNT_EXT]; Vector3 positions[XR_HAND_JOINT_COUNT_EXT]; + const Quaternion &rig_adjustment = bone_adjustments[skeleton_rig]; const OpenXRHandTrackingExtension::HandTracker *hand_tracker = hand_tracking_ext->get_hand_tracker(OpenXRHandTrackingExtension::HandTrackedHands(hand)); const float ws = XRServer::get_singleton()->get_world_scale(); @@ -218,7 +335,7 @@ void OpenXRHand::_update_skeleton() { if (location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) { if (pose.orientation.x != 0 || pose.orientation.y != 0 || pose.orientation.z != 0 || pose.orientation.w != 0) { - quaternions[i] = Quaternion(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w); + quaternions[i] = Quaternion(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w) * rig_adjustment; inv_quaternions[i] = quaternions[i].inverse(); if (location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) { @@ -234,40 +351,29 @@ void OpenXRHand::_update_skeleton() { } if (confidences[XR_HAND_JOINT_PALM_EXT] != XRPose::XR_TRACKING_CONFIDENCE_NONE) { - // now update our skeleton - for (int i = 0; i < XR_HAND_JOINT_COUNT_EXT; i++) { - if (bones[i] != -1) { - int bone = bones[i]; - int parent = skeleton->get_bone_parent(bone); - - // Get our target quaternion - Quaternion q = quaternions[i]; - - // Get our target position - Vector3 p = positions[i]; + // Iterate over all the OpenXR joints. + for (int joint = 0; joint < XR_HAND_JOINT_COUNT_EXT; joint++) { + // Get the skeleton bone (skip if none). + const int bone = joints[joint].bone; + if (bone == -1) { + continue; + } - // get local translation, parent should already be processed - if (parent == -1) { - // use our palm location here, that is what we are tracking - q = inv_quaternions[XR_HAND_JOINT_PALM_EXT] * q; - p = inv_quaternions[XR_HAND_JOINT_PALM_EXT].xform(p - positions[XR_HAND_JOINT_PALM_EXT]); - } else { - int found = false; - for (int b = 0; b < XR_HAND_JOINT_COUNT_EXT && !found; b++) { - if (bones[b] == parent) { - q = inv_quaternions[b] * q; - p = inv_quaternions[b].xform(p - positions[b]); - found = true; - } - } - } + // Calculate the relative relationship to the parent bone joint. + const int parent_joint = joints[joint].parent_joint; + const Quaternion q = inv_quaternions[parent_joint] * quaternions[joint]; + const Vector3 p = inv_quaternions[parent_joint].xform(positions[joint] - positions[parent_joint]); - // and set our pose - skeleton->set_bone_pose_position(bones[i], p); - skeleton->set_bone_pose_rotation(bones[i], q); + // Update the bone position if enabled by update mode. + if (bone_update == BONE_UPDATE_FULL) { + skeleton->set_bone_pose_position(joints[joint].bone, p); } + + // Always update the bone rotation. + skeleton->set_bone_pose_rotation(joints[joint].bone, q); } + // Transform the OpenXRHand to the skeleton pose. Transform3D t; t.basis = Basis(quaternions[XR_HAND_JOINT_PALM_EXT]); t.origin = positions[XR_HAND_JOINT_PALM_EXT]; @@ -288,7 +394,7 @@ void OpenXRHand::_update_skeleton() { void OpenXRHand::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - _get_bones(); + _get_joint_data(); set_process_internal(true); } break; @@ -297,7 +403,8 @@ void OpenXRHand::_notification(int p_what) { // reset for (int i = 0; i < XR_HAND_JOINT_COUNT_EXT; i++) { - bones[i] = -1; + joints[i].bone = -1; + joints[i].parent_joint = -1; } } break; case NOTIFICATION_INTERNAL_PROCESS: { diff --git a/modules/openxr/scene/openxr_hand.h b/modules/openxr/scene/openxr_hand.h index edfb474ac7..4c77e7277c 100644 --- a/modules/openxr/scene/openxr_hand.h +++ b/modules/openxr/scene/openxr_hand.h @@ -55,20 +55,39 @@ public: MOTION_RANGE_MAX }; + enum SkeletonRig { + SKELETON_RIG_OPENXR, + SKELETON_RIG_HUMANOID, + SKELETON_RIG_MAX + }; + + enum BoneUpdate { + BONE_UPDATE_FULL, + BONE_UPDATE_ROTATION_ONLY, + BONE_UPDATE_MAX + }; + private: + struct JointData { + int bone = -1; + int parent_joint = -1; + }; + OpenXRAPI *openxr_api = nullptr; OpenXRHandTrackingExtension *hand_tracking_ext = nullptr; Hands hand = HAND_LEFT; MotionRange motion_range = MOTION_RANGE_UNOBSTRUCTED; NodePath hand_skeleton; + SkeletonRig skeleton_rig = SKELETON_RIG_OPENXR; + BoneUpdate bone_update = BONE_UPDATE_FULL; - int64_t bones[XR_HAND_JOINT_COUNT_EXT]; + JointData joints[XR_HAND_JOINT_COUNT_EXT]; void _set_motion_range(); Skeleton3D *get_skeleton(); - void _get_bones(); + void _get_joint_data(); void _update_skeleton(); protected: @@ -77,19 +96,27 @@ protected: public: OpenXRHand(); - void set_hand(const Hands p_hand); + void set_hand(Hands p_hand); Hands get_hand() const; - void set_motion_range(const MotionRange p_motion_range); + void set_motion_range(MotionRange p_motion_range); MotionRange get_motion_range() const; void set_hand_skeleton(const NodePath &p_hand_skeleton); NodePath get_hand_skeleton() const; + void set_skeleton_rig(SkeletonRig p_skeleton_rig); + SkeletonRig get_skeleton_rig() const; + + void set_bone_update(BoneUpdate p_bone_update); + BoneUpdate get_bone_update() const; + void _notification(int p_what); }; VARIANT_ENUM_CAST(OpenXRHand::Hands) VARIANT_ENUM_CAST(OpenXRHand::MotionRange) +VARIANT_ENUM_CAST(OpenXRHand::SkeletonRig) +VARIANT_ENUM_CAST(OpenXRHand::BoneUpdate) #endif // OPENXR_HAND_H diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp index 704c107f20..d49578d2a9 100644 --- a/modules/regex/regex.cpp +++ b/modules/regex/regex.cpp @@ -270,16 +270,18 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) TypedArray<RegExMatch> RegEx::search_all(const String &p_subject, int p_offset, int p_end) const { ERR_FAIL_COND_V_MSG(p_offset < 0, Array(), "RegEx search offset must be >= 0"); - int last_end = -1; + int last_end = 0; TypedArray<RegExMatch> result; Ref<RegExMatch> match = search(p_subject, p_offset, p_end); + while (match.is_valid()) { - if (last_end == match->get_end(0)) { - break; + last_end = match->get_end(0); + if (match->get_start(0) == last_end) { + last_end++; } + result.push_back(match); - last_end = match->get_end(0); - match = search(p_subject, match->get_end(0), p_end); + match = search(p_subject, last_end, p_end); } return result; } diff --git a/modules/regex/tests/test_regex.h b/modules/regex/tests/test_regex.h index 3e4d769377..0b401da831 100644 --- a/modules/regex/tests/test_regex.h +++ b/modules/regex/tests/test_regex.h @@ -164,7 +164,7 @@ TEST_CASE("[RegEx] Uninitialized use") { ERR_PRINT_ON } -TEST_CASE("[RegEx] Empty Pattern") { +TEST_CASE("[RegEx] Empty pattern") { const String s = "Godot"; RegEx re; @@ -222,6 +222,143 @@ TEST_CASE("[RegEx] Match start and end positions") { CHECK(match->get_start("vowel") == 2); CHECK(match->get_end("vowel") == 3); } + +TEST_CASE("[RegEx] Asterisk search all") { + const String s = "Godot Engine"; + + RegEx re("o*"); + REQUIRE(re.is_valid()); + Ref<RegExMatch> match; + const Array all_results = re.search_all(s); + CHECK(all_results.size() == 13); + + match = all_results[0]; + CHECK(match->get_string(0) == ""); + match = all_results[1]; + CHECK(match->get_string(0) == "o"); + match = all_results[2]; + CHECK(match->get_string(0) == ""); + match = all_results[3]; + CHECK(match->get_string(0) == "o"); + + for (int i = 4; i < 13; i++) { + match = all_results[i]; + CHECK(match->get_string(0) == ""); + } +} + +TEST_CASE("[RegEx] Simple lookahead") { + const String s = "Godot Engine"; + + RegEx re("o(?=t)"); + REQUIRE(re.is_valid()); + Ref<RegExMatch> match = re.search(s); + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 3); + CHECK(match->get_end(0) == 4); +} + +TEST_CASE("[RegEx] Lookahead groups empty matches") { + const String s = "12"; + + RegEx re("(?=(\\d+))"); + REQUIRE(re.is_valid()); + Ref<RegExMatch> match = re.search(s); + CHECK(match->get_string(0) == ""); + CHECK(match->get_string(1) == "12"); + + const Array all_results = re.search_all(s); + CHECK(all_results.size() == 2); + + match = all_results[0]; + REQUIRE(match != nullptr); + CHECK(match->get_string(0) == String("")); + CHECK(match->get_string(1) == String("12")); + + match = all_results[1]; + REQUIRE(match != nullptr); + CHECK(match->get_string(0) == String("")); + CHECK(match->get_string(1) == String("2")); +} + +TEST_CASE("[RegEx] Simple lookbehind") { + const String s = "Godot Engine"; + + RegEx re("(?<=d)o"); + REQUIRE(re.is_valid()); + Ref<RegExMatch> match = re.search(s); + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 3); + CHECK(match->get_end(0) == 4); +} + +TEST_CASE("[RegEx] Simple lookbehind search all") { + const String s = "ababbaabab"; + + RegEx re("(?<=a)b"); + REQUIRE(re.is_valid()); + const Array all_results = re.search_all(s); + CHECK(all_results.size() == 4); + + Ref<RegExMatch> match = all_results[0]; + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 1); + CHECK(match->get_end(0) == 2); + + match = all_results[1]; + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 3); + CHECK(match->get_end(0) == 4); + + match = all_results[2]; + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 7); + CHECK(match->get_end(0) == 8); + + match = all_results[3]; + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 9); + CHECK(match->get_end(0) == 10); +} + +TEST_CASE("[RegEx] Lookbehind groups empty matches") { + const String s = "abaaabab"; + + RegEx re("(?<=(b))"); + REQUIRE(re.is_valid()); + Ref<RegExMatch> match; + + const Array all_results = re.search_all(s); + CHECK(all_results.size() == 3); + + match = all_results[0]; + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 2); + CHECK(match->get_end(0) == 2); + CHECK(match->get_start(1) == 1); + CHECK(match->get_end(1) == 2); + CHECK(match->get_string(0) == String("")); + CHECK(match->get_string(1) == String("b")); + + match = all_results[1]; + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 6); + CHECK(match->get_end(0) == 6); + CHECK(match->get_start(1) == 5); + CHECK(match->get_end(1) == 6); + CHECK(match->get_string(0) == String("")); + CHECK(match->get_string(1) == String("b")); + + match = all_results[2]; + REQUIRE(match != nullptr); + CHECK(match->get_start(0) == 8); + CHECK(match->get_end(0) == 8); + CHECK(match->get_start(1) == 7); + CHECK(match->get_end(1) == 8); + CHECK(match->get_string(0) == String("")); + CHECK(match->get_string(1) == String("b")); +} + } // namespace TestRegEx #endif // TEST_REGEX_H diff --git a/modules/svg/SCsub b/modules/svg/SCsub index d0c6250b11..ff0c3c9141 100644 --- a/modules/svg/SCsub +++ b/modules/svg/SCsub @@ -43,6 +43,8 @@ thirdparty_sources = [ "src/renderer/tvgShape.cpp", "src/renderer/tvgSwCanvas.cpp", "src/renderer/tvgTaskScheduler.cpp", + "src/renderer/tvgText.cpp", + # "src/renderer/tvgWgCanvas.cpp", # renderer sw_engine "src/renderer/sw_engine/tvgSwFill.cpp", "src/renderer/sw_engine/tvgSwImage.cpp", diff --git a/modules/svg/register_types.cpp b/modules/svg/register_types.cpp index 7b61749f61..82d816d833 100644 --- a/modules/svg/register_types.cpp +++ b/modules/svg/register_types.cpp @@ -34,6 +34,12 @@ #include <thorvg.h> +#ifdef THREADS_ENABLED +#define TVG_THREADS 1 +#else +#define TVG_THREADS 0 +#endif + static Ref<ImageLoaderSVG> image_loader_svg; void initialize_svg_module(ModuleInitializationLevel p_level) { @@ -42,7 +48,8 @@ void initialize_svg_module(ModuleInitializationLevel p_level) { } tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; - if (tvg::Initializer::init(tvgEngine, 1) != tvg::Result::Success) { + + if (tvg::Initializer::init(tvgEngine, TVG_THREADS) != tvg::Result::Success) { return; } diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 3c468e61d7..09d9b2dd67 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -401,6 +401,8 @@ if env["builtin_icu4c"]: "common/uloc.cpp", "common/uloc_keytype.cpp", "common/uloc_tag.cpp", + "common/ulocale.cpp", + "common/ulocbuilder.cpp", "common/umapfile.cpp", "common/umath.cpp", "common/umutablecptrie.cpp", @@ -466,7 +468,7 @@ if env["builtin_icu4c"]: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - icu_data_name = "icudt73l.dat" + icu_data_name = "icudt74l.dat" if env.editor_build: env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name) diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct index 4093842650..cd4331b60e 100644 --- a/modules/text_server_adv/gdextension_build/SConstruct +++ b/modules/text_server_adv/gdextension_build/SConstruct @@ -74,6 +74,8 @@ if env["thorvg_enabled"] and env["freetype_enabled"]: "src/renderer/tvgShape.cpp", "src/renderer/tvgSwCanvas.cpp", "src/renderer/tvgTaskScheduler.cpp", + "src/renderer/tvgText.cpp", + # "src/renderer/tvgWgCanvas.cpp", # renderer sw_engine "src/renderer/sw_engine/tvgSwFill.cpp", "src/renderer/sw_engine/tvgSwImage.cpp", @@ -623,6 +625,8 @@ thirdparty_icu_sources = [ "common/uloc.cpp", "common/uloc_keytype.cpp", "common/uloc_tag.cpp", + "common/ulocale.cpp", + "common/ulocbuilder.cpp", "common/umapfile.cpp", "common/umath.cpp", "common/umutablecptrie.cpp", @@ -688,7 +692,7 @@ thirdparty_icu_sources = [ ] thirdparty_icu_sources = [thirdparty_icu_dir + file for file in thirdparty_icu_sources] -icu_data_name = "icudt73l.dat" +icu_data_name = "icudt74l.dat" if env["static_icu_data"]: env_icu.Depends("../../../thirdparty/icu4c/icudata.gen.h", "../../../thirdparty/icu4c/" + icu_data_name) diff --git a/modules/text_server_adv/register_types.h b/modules/text_server_adv/register_types.h index c11765048d..477e030e03 100644 --- a/modules/text_server_adv/register_types.h +++ b/modules/text_server_adv/register_types.h @@ -34,7 +34,7 @@ #ifdef GDEXTENSION #include <godot_cpp/core/class_db.hpp> using namespace godot; -#else +#elif defined(GODOT_MODULE) #include "modules/register_module_types.h" #endif diff --git a/modules/text_server_adv/script_iterator.h b/modules/text_server_adv/script_iterator.h index 164fdec784..f7876d6cbc 100644 --- a/modules/text_server_adv/script_iterator.h +++ b/modules/text_server_adv/script_iterator.h @@ -40,7 +40,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/string/ustring.h" diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index bcc7bff909..19f302423c 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -44,7 +44,7 @@ using namespace godot; #define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get_setting_with_override(m_var) -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/config/project_settings.h" @@ -370,7 +370,7 @@ bool TextServerAdvanced::_has_feature(Feature p_feature) const { String TextServerAdvanced::_get_name() const { #ifdef GDEXTENSION return "ICU / HarfBuzz / Graphite (GDExtension)"; -#else +#elif defined(GODOT_MODULE) return "ICU / HarfBuzz / Graphite (Built-in)"; #endif } @@ -4852,7 +4852,7 @@ RID TextServerAdvanced::_find_sys_font_for_text(const RID &p_fdef, const String #ifdef GDEXTENSION for (int fb = 0; fb < fallback_font_name.size(); fb++) { const String &E = fallback_font_name[fb]; -#else +#elif defined(GODOT_MODULE) for (const String &E : fallback_font_name) { #endif SystemFontKey key = SystemFontKey(E, font_style & TextServer::FONT_ITALIC, font_weight, font_stretch, p_fdef, this); @@ -6757,7 +6757,7 @@ String TextServerAdvanced::_strip_diacritics(const String &p_string) const { if (u_getCombiningClass(normalized_string[i]) == 0) { #ifdef GDEXTENSION result = result + String::chr(normalized_string[i]); -#else +#elif defined(GODOT_MODULE) result = result + normalized_string[i]; #endif } diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index e5d0ab3105..0b5fe47b8b 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -78,7 +78,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/extension/ext_wrappers.gen.inc" diff --git a/modules/text_server_adv/thorvg_bounds_iterator.cpp b/modules/text_server_adv/thorvg_bounds_iterator.cpp index 807f356b83..d273eef97f 100644 --- a/modules/text_server_adv/thorvg_bounds_iterator.cpp +++ b/modules/text_server_adv/thorvg_bounds_iterator.cpp @@ -35,7 +35,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/typedefs.h" diff --git a/modules/text_server_adv/thorvg_bounds_iterator.h b/modules/text_server_adv/thorvg_bounds_iterator.h index a44cbb99a7..afa2c13764 100644 --- a/modules/text_server_adv/thorvg_bounds_iterator.h +++ b/modules/text_server_adv/thorvg_bounds_iterator.h @@ -39,7 +39,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/typedefs.h" diff --git a/modules/text_server_adv/thorvg_svg_in_ot.cpp b/modules/text_server_adv/thorvg_svg_in_ot.cpp index 828f8d7d56..136ccf3aaf 100644 --- a/modules/text_server_adv/thorvg_svg_in_ot.cpp +++ b/modules/text_server_adv/thorvg_svg_in_ot.cpp @@ -38,7 +38,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/error/error_macros.h" diff --git a/modules/text_server_adv/thorvg_svg_in_ot.h b/modules/text_server_adv/thorvg_svg_in_ot.h index 034fffb5e6..ce048674fd 100644 --- a/modules/text_server_adv/thorvg_svg_in_ot.h +++ b/modules/text_server_adv/thorvg_svg_in_ot.h @@ -40,7 +40,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/os/mutex.h" diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct index 0d2fbd97fd..0efced0bfc 100644 --- a/modules/text_server_fb/gdextension_build/SConstruct +++ b/modules/text_server_fb/gdextension_build/SConstruct @@ -69,6 +69,8 @@ if env["thorvg_enabled"] and env["freetype_enabled"]: "src/renderer/tvgShape.cpp", "src/renderer/tvgSwCanvas.cpp", "src/renderer/tvgTaskScheduler.cpp", + "src/renderer/tvgText.cpp", + # "src/renderer/tvgWgCanvas.cpp", # renderer sw_engine "src/renderer/sw_engine/tvgSwFill.cpp", "src/renderer/sw_engine/tvgSwImage.cpp", diff --git a/modules/text_server_fb/register_types.h b/modules/text_server_fb/register_types.h index 97bc06a8f7..0933ea83c5 100644 --- a/modules/text_server_fb/register_types.h +++ b/modules/text_server_fb/register_types.h @@ -34,7 +34,7 @@ #ifdef GDEXTENSION #include <godot_cpp/core/class_db.hpp> using namespace godot; -#else +#elif defined(GODOT_MODULE) #include "modules/register_module_types.h" #endif diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 8fc7694aa4..0b486b7d7b 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -44,7 +44,7 @@ using namespace godot; #define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get_setting_with_override(m_var) -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/config/project_settings.h" @@ -95,7 +95,7 @@ bool TextServerFallback::_has_feature(Feature p_feature) const { String TextServerFallback::_get_name() const { #ifdef GDEXTENSION return "Fallback (GDExtension)"; -#else +#elif defined(GODOT_MODULE) return "Fallback (Built-in)"; #endif } @@ -3654,7 +3654,7 @@ RID TextServerFallback::_find_sys_font_for_text(const RID &p_fdef, const String #ifdef GDEXTENSION for (int fb = 0; fb < fallback_font_name.size(); fb++) { const String &E = fallback_font_name[fb]; -#else +#elif defined(GODOT_MODULE) for (const String &E : fallback_font_name) { #endif SystemFontKey key = SystemFontKey(E, font_style & TextServer::FONT_ITALIC, font_weight, font_stretch, p_fdef, this); diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 68e0cbff6c..2bb3724858 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -76,7 +76,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/extension/ext_wrappers.gen.inc" diff --git a/modules/text_server_fb/thorvg_bounds_iterator.cpp b/modules/text_server_fb/thorvg_bounds_iterator.cpp index 807f356b83..d273eef97f 100644 --- a/modules/text_server_fb/thorvg_bounds_iterator.cpp +++ b/modules/text_server_fb/thorvg_bounds_iterator.cpp @@ -35,7 +35,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/typedefs.h" diff --git a/modules/text_server_fb/thorvg_bounds_iterator.h b/modules/text_server_fb/thorvg_bounds_iterator.h index a44cbb99a7..afa2c13764 100644 --- a/modules/text_server_fb/thorvg_bounds_iterator.h +++ b/modules/text_server_fb/thorvg_bounds_iterator.h @@ -39,7 +39,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/typedefs.h" diff --git a/modules/text_server_fb/thorvg_svg_in_ot.cpp b/modules/text_server_fb/thorvg_svg_in_ot.cpp index 7c8fedabc8..1ad33a88d4 100644 --- a/modules/text_server_fb/thorvg_svg_in_ot.cpp +++ b/modules/text_server_fb/thorvg_svg_in_ot.cpp @@ -38,7 +38,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/error/error_macros.h" diff --git a/modules/text_server_fb/thorvg_svg_in_ot.h b/modules/text_server_fb/thorvg_svg_in_ot.h index 034fffb5e6..ce048674fd 100644 --- a/modules/text_server_fb/thorvg_svg_in_ot.h +++ b/modules/text_server_fb/thorvg_svg_in_ot.h @@ -40,7 +40,7 @@ using namespace godot; -#else +#elif defined(GODOT_MODULE) // Headers for building as built-in module. #include "core/os/mutex.h" diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp index 7ec0b697bf..e6003f35df 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp @@ -46,8 +46,9 @@ int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram int todo = p_frames; int beat_length_frames = -1; - bool beat_loop = vorbis_stream->has_loop(); - if (beat_loop && vorbis_stream->get_bpm() > 0 && vorbis_stream->get_beat_count() > 0) { + bool use_loop = looping_override ? looping : vorbis_stream->loop; + + if (use_loop && vorbis_stream->get_bpm() > 0 && vorbis_stream->get_beat_count() > 0) { beat_length_frames = vorbis_stream->get_beat_count() * vorbis_data->get_sampling_rate() * 60 / vorbis_stream->get_bpm(); } @@ -99,7 +100,7 @@ int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram } else **/ - if (beat_loop && beat_length_frames <= (int)frames_mixed) { + if (use_loop && beat_length_frames <= (int)frames_mixed) { // End of file when doing beat-based looping. <= used instead of == because importer editing if (!have_packets_left && !have_samples_left) { //Nothing remaining, so do nothing. @@ -125,7 +126,7 @@ int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram if (!have_packets_left && !have_samples_left) { // Actual end of file! bool is_not_empty = mixed > 0 || vorbis_stream->get_length() > 0; - if (vorbis_stream->loop && is_not_empty) { + if (use_loop && is_not_empty) { //loop seek(vorbis_stream->loop_offset); @@ -257,6 +258,25 @@ void AudioStreamPlaybackOggVorbis::tag_used_streams() { vorbis_stream->tag_used(get_playback_position()); } +void AudioStreamPlaybackOggVorbis::set_parameter(const StringName &p_name, const Variant &p_value) { + if (p_name == SNAME("looping")) { + if (p_value == Variant()) { + looping_override = false; + looping = false; + } else { + looping_override = true; + looping = p_value; + } + } +} + +Variant AudioStreamPlaybackOggVorbis::get_parameter(const StringName &p_name) const { + if (looping_override && p_name == SNAME("looping")) { + return looping; + } + return Variant(); +} + void AudioStreamPlaybackOggVorbis::seek(double p_time) { ERR_FAIL_COND(!ready); ERR_FAIL_COND(vorbis_stream.is_null()); @@ -493,6 +513,10 @@ bool AudioStreamOggVorbis::is_monophonic() const { return false; } +void AudioStreamOggVorbis::get_parameter_list(List<Parameter> *r_parameters) { + r_parameters->push_back(Parameter(PropertyInfo(Variant::BOOL, "looping", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE), Variant())); +} + void AudioStreamOggVorbis::_bind_methods() { ClassDB::bind_static_method("AudioStreamOggVorbis", D_METHOD("load_from_buffer", "buffer"), &AudioStreamOggVorbis::load_from_buffer); ClassDB::bind_static_method("AudioStreamOggVorbis", D_METHOD("load_from_file", "path"), &AudioStreamOggVorbis::load_from_file); diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h index 6abaeaaebd..64a7815b57 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.h +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -44,6 +44,8 @@ class AudioStreamPlaybackOggVorbis : public AudioStreamPlaybackResampled { uint32_t frames_mixed = 0; bool active = false; + bool looping_override = false; + bool looping = false; int loops = 0; enum { @@ -95,6 +97,9 @@ public: virtual void tag_used_streams() override; + virtual void set_parameter(const StringName &p_name, const Variant &p_value) override; + virtual Variant get_parameter(const StringName &p_name) const override; + AudioStreamPlaybackOggVorbis() {} ~AudioStreamPlaybackOggVorbis(); }; @@ -152,6 +157,8 @@ public: virtual bool is_monophonic() const override; + virtual void get_parameter_list(List<Parameter> *r_parameters) override; + AudioStreamOggVorbis(); virtual ~AudioStreamOggVorbis(); }; diff --git a/modules/zip/zip_packer.cpp b/modules/zip/zip_packer.cpp index e67c65d4d1..e96d9da7a9 100644 --- a/modules/zip/zip_packer.cpp +++ b/modules/zip/zip_packer.cpp @@ -88,7 +88,7 @@ Error ZIPPacker::start_file(const String &p_path) { Z_DEFAULT_STRATEGY, nullptr, 0, - 0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions. + 0, // "version made by", indicates the compatibility of the file attribute information (the `external_fa` field above). 1 << 11); // Bit 11 is the language encoding flag. When set, filename and comment fields must be encoded using UTF-8. return err == ZIP_OK ? OK : FAILED; } diff --git a/platform/android/detect.py b/platform/android/detect.py index a417ef454b..b396e5eb2d 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -200,7 +200,7 @@ def configure(env: "Environment"): env.Append(LIBS=["OpenSLES", "EGL", "android", "log", "z", "dl"]) if env["vulkan"]: - env.Append(CPPDEFINES=["VULKAN_ENABLED"]) + env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"]) if not env["use_volk"]: env.Append(LIBS=["vulkan"]) diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index ee1ec2790d..e276048d40 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -48,6 +48,7 @@ void register_android_exporter() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks")); EDITOR_DEF("export/android/debug_keystore_user", "androiddebugkey"); EDITOR_DEF("export/android/debug_keystore_pass", "android"); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore_pass", PROPERTY_HINT_PASSWORD)); EDITOR_DEF("export/android/force_system_user", false); EDITOR_DEF("export/android/shutdown_adb_on_exit", true); diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 10d54e8d97..653e7bfe6f 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -45,9 +45,9 @@ #include "editor/editor_log.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/import/resource_importer_texture_settings.h" +#include "editor/themes/editor_scale.h" #include "main/splash.gen.h" #include "scene/resources/image_texture.h" @@ -1111,7 +1111,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p } for (int i = 0; i < feature_names.size(); i++) { - String feature_name = feature_names[i]; + const String &feature_name = feature_names[i]; bool feature_required = feature_required_list[i]; int feature_version = feature_versions[i]; bool has_version_attribute = feature_version != -1; @@ -1605,7 +1605,11 @@ void EditorExportPlatformAndroid::load_icon_refs(const Ref<EditorExportPreset> & print_verbose("Loading regular icon from " + path); if (path.is_empty() || ImageLoader::load_image(path, icon) != OK) { print_verbose("- falling back to project icon: " + project_icon_path); - ImageLoader::load_image(project_icon_path, icon); + if (!project_icon_path.is_empty()) { + ImageLoader::load_image(project_icon_path, icon); + } else { + ERR_PRINT("No project icon specified. Please specify one in the Project Settings under Application -> Config -> Icon"); + } } // Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default). @@ -1823,10 +1827,10 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password", PROPERTY_HINT_PASSWORD, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password", PROPERTY_HINT_PASSWORD, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); @@ -2229,6 +2233,54 @@ String EditorExportPlatformAndroid::get_apksigner_path(int p_target_sdk, bool p_ return apksigner_path; } +static bool has_valid_keystore_credentials(String &r_error_str, const String &p_keystore, const String &p_username, const String &p_password, const String &p_type) { + String output; + List<String> args; + args.push_back("-list"); + args.push_back("-keystore"); + args.push_back(p_keystore); + args.push_back("-storepass"); + args.push_back(p_password); + args.push_back("-alias"); + args.push_back(p_username); + Error error = OS::get_singleton()->execute("keytool", args, &output, nullptr, true); + String keytool_error = "keytool error:"; + bool valid = output.substr(0, keytool_error.length()) != keytool_error; + + if (error != OK) { + r_error_str = TTR("Error: There was a problem validating the keystore username and password"); + return false; + } + if (!valid) { + r_error_str = TTR(p_type + " Username and/or Password is invalid for the given " + p_type + " Keystore"); + return false; + } + r_error_str = ""; + return true; +} + +bool EditorExportPlatformAndroid::has_valid_username_and_password(const Ref<EditorExportPreset> &p_preset, String &r_error) { + String dk = p_preset->get_or_env("keystore/debug", ENV_ANDROID_KEYSTORE_DEBUG_PATH); + String dk_user = p_preset->get_or_env("keystore/debug_user", ENV_ANDROID_KEYSTORE_DEBUG_USER); + String dk_password = p_preset->get_or_env("keystore/debug_password", ENV_ANDROID_KEYSTORE_DEBUG_PASS); + String rk = p_preset->get_or_env("keystore/release", ENV_ANDROID_KEYSTORE_RELEASE_PATH); + String rk_user = p_preset->get_or_env("keystore/release_user", ENV_ANDROID_KEYSTORE_RELEASE_USER); + String rk_password = p_preset->get_or_env("keystore/release_password", ENV_ANDROID_KEYSTORE_RELEASE_PASS); + + bool valid = true; + if (!dk.is_empty() && !dk_user.is_empty() && !dk_password.is_empty()) { + String err = ""; + valid = has_valid_keystore_credentials(err, dk, dk_user, dk_password, "Debug"); + r_error += err; + } + if (!rk.is_empty() && !rk_user.is_empty() && !rk_password.is_empty()) { + String err = ""; + valid = has_valid_keystore_credentials(err, rk, rk_user, rk_password, "Release"); + r_error += err; + } + return valid; +} + bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const { String err; bool valid = false; @@ -2842,6 +2894,11 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unsupported export format!")); return ERR_UNCONFIGURED; } + String err_string; + if (!has_valid_username_and_password(p_preset, err_string)) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR(err_string)); + return ERR_UNCONFIGURED; + } if (use_gradle_build) { print_verbose("Starting gradle build..."); diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index a2d0417c5d..5b585581b0 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -228,6 +228,7 @@ public: virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override; virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override; + static bool has_valid_username_and_password(const Ref<EditorExportPreset> &p_preset, String &r_error); virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override; diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp index 1249f2219f..f56eda4694 100644 --- a/platform/android/file_access_android.cpp +++ b/platform/android/file_access_android.cpp @@ -121,6 +121,75 @@ uint8_t FileAccessAndroid::get_8() const { return byte; } +uint16_t FileAccessAndroid::get_16() const { + if (pos >= len) { + eof = true; + return 0; + } + + uint16_t bytes = 0; + int r = AAsset_read(asset, &bytes, 2); + + if (r >= 0) { + pos += r; + if (pos >= len) { + eof = true; + } + } + + if (big_endian) { + bytes = BSWAP16(bytes); + } + + return bytes; +} + +uint32_t FileAccessAndroid::get_32() const { + if (pos >= len) { + eof = true; + return 0; + } + + uint32_t bytes = 0; + int r = AAsset_read(asset, &bytes, 4); + + if (r >= 0) { + pos += r; + if (pos >= len) { + eof = true; + } + } + + if (big_endian) { + bytes = BSWAP32(bytes); + } + + return bytes; +} + +uint64_t FileAccessAndroid::get_64() const { + if (pos >= len) { + eof = true; + return 0; + } + + uint64_t bytes = 0; + int r = AAsset_read(asset, &bytes, 8); + + if (r >= 0) { + pos += r; + if (pos >= len) { + eof = true; + } + } + + if (big_endian) { + bytes = BSWAP64(bytes); + } + + return bytes; +} + uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); @@ -151,6 +220,18 @@ void FileAccessAndroid::store_8(uint8_t p_dest) { ERR_FAIL(); } +void FileAccessAndroid::store_16(uint16_t p_dest) { + ERR_FAIL(); +} + +void FileAccessAndroid::store_32(uint32_t p_dest) { + ERR_FAIL(); +} + +void FileAccessAndroid::store_64(uint64_t p_dest) { + ERR_FAIL(); +} + bool FileAccessAndroid::file_exists(const String &p_path) { String path = fix_path(p_path).simplify_path(); if (path.begins_with("/")) { diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index 3aa4ca98fc..ec613b6687 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -66,12 +66,18 @@ public: virtual bool eof_reached() const override; // reading passed EOF virtual uint8_t get_8() const override; // get a byte + virtual uint16_t get_16() const override; + virtual uint32_t get_32() const override; + virtual uint64_t get_64() const override; virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; virtual Error get_error() const override; // get last error virtual void flush() override; virtual void store_8(uint8_t p_dest) override; // store a byte + virtual void store_16(uint16_t p_dest) override; + virtual void store_32(uint32_t p_dest) override; + virtual void store_64(uint64_t p_dest) override; virtual bool file_exists(const String &p_path) override; // return true if a file exists diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp index beea73fd61..46d9728632 100644 --- a/platform/android/file_access_filesystem_jandroid.cpp +++ b/platform/android/file_access_filesystem_jandroid.cpp @@ -181,6 +181,36 @@ uint8_t FileAccessFilesystemJAndroid::get_8() const { return byte; } +uint16_t FileAccessFilesystemJAndroid::get_16() const { + ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); + uint16_t bytes = 0; + get_buffer(reinterpret_cast<uint8_t *>(&bytes), 2); + if (big_endian) { + bytes = BSWAP16(bytes); + } + return bytes; +} + +uint32_t FileAccessFilesystemJAndroid::get_32() const { + ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); + uint32_t bytes = 0; + get_buffer(reinterpret_cast<uint8_t *>(&bytes), 4); + if (big_endian) { + bytes = BSWAP32(bytes); + } + return bytes; +} + +uint64_t FileAccessFilesystemJAndroid::get_64() const { + ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); + uint64_t bytes = 0; + get_buffer(reinterpret_cast<uint8_t *>(&bytes), 8); + if (big_endian) { + bytes = BSWAP64(bytes); + } + return bytes; +} + String FileAccessFilesystemJAndroid::get_line() const { ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use."); @@ -250,6 +280,27 @@ void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) { store_buffer(&p_dest, 1); } +void FileAccessFilesystemJAndroid::store_16(uint16_t p_dest) { + if (big_endian) { + p_dest = BSWAP16(p_dest); + } + store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 2); +} + +void FileAccessFilesystemJAndroid::store_32(uint32_t p_dest) { + if (big_endian) { + p_dest = BSWAP32(p_dest); + } + store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 4); +} + +void FileAccessFilesystemJAndroid::store_64(uint64_t p_dest) { + if (big_endian) { + p_dest = BSWAP64(p_dest); + } + store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 8); +} + void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) { if (_file_write) { ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h index 0c3f8d7259..f33aa64ebe 100644 --- a/platform/android/file_access_filesystem_jandroid.h +++ b/platform/android/file_access_filesystem_jandroid.h @@ -77,6 +77,9 @@ public: virtual bool eof_reached() const override; ///< reading passed EOF virtual uint8_t get_8() const override; ///< get a byte + virtual uint16_t get_16() const override; + virtual uint32_t get_32() const override; + virtual uint64_t get_64() const override; virtual String get_line() const override; ///< get a line virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; @@ -84,6 +87,9 @@ public: virtual void flush() override; virtual void store_8(uint8_t p_dest) override; ///< store a byte + virtual void store_16(uint16_t p_dest) override; + virtual void store_32(uint32_t p_dest) override; + virtual void store_64(uint64_t p_dest) override; virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; virtual bool file_exists(const String &p_path) override; ///< return true if a file exists diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt index 0d7017ae71..caf64bc933 100644 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt @@ -91,6 +91,10 @@ open class GodotEditor : GodotActivity() { private val commandLineParams = ArrayList<String>() override fun onCreate(savedInstanceState: Bundle?) { + // We exclude certain permissions from the set we request at startup, as they'll be + // requested on demand based on use-cases. + PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO)) + val params = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS) Log.d(TAG, "Received parameters ${params.contentToString()}") updateCommandLineParams(params) diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt index 217e7a2b60..da86e67c7d 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt @@ -484,6 +484,14 @@ class Godot(private val context: Context) : SensorEventListener { return containerLayout } + fun onStart(host: GodotHost) { + if (host != primaryHost) { + return + } + + renderView!!.onActivityStarted() + } + fun onResume(host: GodotHost) { if (host != primaryHost) { return @@ -528,6 +536,14 @@ class Godot(private val context: Context) : SensorEventListener { } } + fun onStop(host: GodotHost) { + if (host != primaryHost) { + return + } + + renderView!!.onActivityStopped() + } + fun onDestroy(primaryHost: GodotHost) { if (this.primaryHost != primaryHost) { return diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt index a60f6e997e..e01c5481d5 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt @@ -30,7 +30,6 @@ package org.godotengine.godot -import android.Manifest import android.app.Activity import android.content.Intent import android.content.pm.PackageManager @@ -65,10 +64,6 @@ abstract class GodotActivity : FragmentActivity(), GodotHost { private set override fun onCreate(savedInstanceState: Bundle?) { - // We exclude certain permissions from the set we request at startup, as they'll be - // requested on demand based on use-cases. - PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO)) - super.onCreate(savedInstanceState) setContentView(R.layout.godot_app_layout) @@ -156,7 +151,8 @@ abstract class GodotActivity : FragmentActivity(), GodotHost { super.onRequestPermissionsResult(requestCode, permissions, grantResults) godotFragment?.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (requestCode == PermissionsUtil.REQUEST_ALL_PERMISSION_REQ_CODE) { + // Logging the result of permission requests + if (requestCode == PermissionsUtil.REQUEST_ALL_PERMISSION_REQ_CODE || requestCode == PermissionsUtil.REQUEST_SINGLE_PERMISSION_REQ_CODE) { Log.d(TAG, "Received permissions request result..") for (i in permissions.indices) { val permissionGranted = grantResults[i] == PackageManager.PERMISSION_GRANTED diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java b/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java index f1c029e7a1..643c9a658e 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java @@ -271,6 +271,32 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH } @Override + public void onStop() { + super.onStop(); + if (!godot.isInitialized()) { + if (null != mDownloaderClientStub) { + mDownloaderClientStub.disconnect(getActivity()); + } + return; + } + + godot.onStop(this); + } + + @Override + public void onStart() { + super.onStart(); + if (!godot.isInitialized()) { + if (null != mDownloaderClientStub) { + mDownloaderClientStub.connect(getActivity()); + } + return; + } + + godot.onStart(this); + } + + @Override public void onResume() { super.onResume(); if (!godot.isInitialized()) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index 52350c12a6..81043ce782 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -114,12 +114,30 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView @Override public void onActivityPaused() { - onPause(); + queueEvent(() -> { + GodotLib.focusout(); + // Pause the renderer + godotRenderer.onActivityPaused(); + }); + } + + @Override + public void onActivityStopped() { + pauseGLThread(); } @Override public void onActivityResumed() { - onResume(); + queueEvent(() -> { + // Resume the renderer + godotRenderer.onActivityResumed(); + GodotLib.focusin(); + }); + } + + @Override + public void onActivityStarted() { + resumeGLThread(); } @Override @@ -283,26 +301,4 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView /* Set the renderer responsible for frame rendering */ setRenderer(godotRenderer); } - - @Override - public void onResume() { - super.onResume(); - - queueEvent(() -> { - // Resume the renderer - godotRenderer.onActivityResumed(); - GodotLib.focusin(); - }); - } - - @Override - public void onPause() { - super.onPause(); - - queueEvent(() -> { - GodotLib.focusout(); - // Pause the renderer - godotRenderer.onActivityPaused(); - }); - } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index edcd9c4d1f..4b51bd778d 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -178,12 +178,10 @@ public class GodotIO { } public int[] getDisplaySafeArea() { - DisplayMetrics metrics = activity.getResources().getDisplayMetrics(); - Display display = activity.getWindowManager().getDefaultDisplay(); - Point size = new Point(); - display.getRealSize(size); + Rect rect = new Rect(); + activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); - int[] result = { 0, 0, size.x, size.y }; + int[] result = { rect.left, rect.top, rect.right, rect.bottom }; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); DisplayCutout cutout = insets.getDisplayCutout(); diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java index ebf3a6b2fb..5b2f9f57c7 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java @@ -47,8 +47,13 @@ public interface GodotRenderView { void queueOnRenderThread(Runnable event); void onActivityPaused(); + + void onActivityStopped(); + void onActivityResumed(); + void onActivityStarted(); + void onBackPressed(); GodotInputHandler getInputHandler(); diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java index 48708152be..a1ee9bd6b4 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java @@ -92,12 +92,30 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV @Override public void onActivityPaused() { - onPause(); + queueOnVkThread(() -> { + GodotLib.focusout(); + // Pause the renderer + mRenderer.onVkPause(); + }); + } + + @Override + public void onActivityStopped() { + pauseRenderThread(); + } + + @Override + public void onActivityStarted() { + resumeRenderThread(); } @Override public void onActivityResumed() { - onResume(); + queueOnVkThread(() -> { + // Resume the renderer + mRenderer.onVkResume(); + GodotLib.focusin(); + }); } @Override @@ -211,26 +229,4 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV } return super.onResolvePointerIcon(me, pointerIndex); } - - @Override - public void onResume() { - super.onResume(); - - queueOnVkThread(() -> { - // Resume the renderer - mRenderer.onVkResume(); - GodotLib.focusin(); - }); - } - - @Override - public void onPause() { - super.onPause(); - - queueOnVkThread(() -> { - GodotLib.focusout(); - // Pause the renderer - mRenderer.onVkPause(); - }); - } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java b/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java index 56397bb2c2..ef97aaeab9 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java @@ -122,8 +122,8 @@ import javax.microedition.khronos.opengles.GL10; * <p> * <h3>Activity Life-cycle</h3> * A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients - * are required to call {@link #onPause()} when the activity stops and - * {@link #onResume()} when the activity starts. These calls allow GLSurfaceView to + * are required to call {@link #pauseGLThread()} when the activity stops and + * {@link #resumeGLThread()} when the activity starts. These calls allow GLSurfaceView to * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate * the OpenGL display. * <p> @@ -339,8 +339,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * setRenderer is called: * <ul> * <li>{@link #getRenderMode()} - * <li>{@link #onPause()} - * <li>{@link #onResume()} + * <li>{@link #pauseGLThread()} + * <li>{@link #resumeGLThread()} * <li>{@link #queueEvent(Runnable)} * <li>{@link #requestRender()} * <li>{@link #setRenderMode(int)} @@ -568,6 +568,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } + // -- GODOT start -- /** * Pause the rendering thread, optionally tearing down the EGL context * depending upon the value of {@link #setPreserveEGLContextOnPause(boolean)}. @@ -578,22 +579,23 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * * Must not be called before a renderer has been set. */ - public void onPause() { + protected final void pauseGLThread() { mGLThread.onPause(); } /** * Resumes the rendering thread, re-creating the OpenGL context if necessary. It - * is the counterpart to {@link #onPause()}. + * is the counterpart to {@link #pauseGLThread()}. * * This method should typically be called in * {@link android.app.Activity#onStart Activity.onStart}. * * Must not be called before a renderer has been set. */ - public void onResume() { + protected final void resumeGLThread() { mGLThread.onResume(); } + // -- GODOT end -- /** * Queue a runnable to be run on the GL rendering thread. This can be used diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java index 9a82204467..737b4ac20b 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java @@ -56,9 +56,9 @@ import java.util.Set; public final class PermissionsUtil { private static final String TAG = PermissionsUtil.class.getSimpleName(); - static final int REQUEST_RECORD_AUDIO_PERMISSION = 1; - static final int REQUEST_CAMERA_PERMISSION = 2; - static final int REQUEST_VIBRATE_PERMISSION = 3; + public static final int REQUEST_RECORD_AUDIO_PERMISSION = 1; + public static final int REQUEST_CAMERA_PERMISSION = 2; + public static final int REQUEST_VIBRATE_PERMISSION = 3; public static final int REQUEST_ALL_PERMISSION_REQ_CODE = 1001; public static final int REQUEST_SINGLE_PERMISSION_REQ_CODE = 1002; public static final int REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE = 2002; @@ -70,7 +70,7 @@ public final class PermissionsUtil { * Request a dangerous permission. name must be specified in <a href="https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/res/AndroidManifest.xml">this</a> * @param permissionName the name of the requested permission. * @param activity the caller activity for this method. - * @return true/false. "true" if permission was granted otherwise returns "false". + * @return true/false. "true" if permission is already granted, "false" if a permission request was dispatched. */ public static boolean requestPermission(String permissionName, Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { @@ -124,7 +124,7 @@ public final class PermissionsUtil { /** * Request dangerous permissions which are defined in the Android manifest file from the user. * @param activity the caller activity for this method. - * @return true/false. "true" if all permissions were granted otherwise returns "false". + * @return true/false. "true" if all permissions were already granted, returns "false" if permissions requests were dispatched. */ public static boolean requestManifestPermissions(Activity activity) { return requestManifestPermissions(activity, null); @@ -134,7 +134,7 @@ public final class PermissionsUtil { * Request dangerous permissions which are defined in the Android manifest file from the user. * @param activity the caller activity for this method. * @param excludes Set of permissions to exclude from the request - * @return true/false. "true" if all permissions were granted otherwise returns "false". + * @return true/false. "true" if all permissions were already granted, returns "false" if permissions requests were dispatched. */ public static boolean requestManifestPermissions(Activity activity, @Nullable Set<String> excludes) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { @@ -235,7 +235,7 @@ public final class PermissionsUtil { /** * Check if the given permission is in the AndroidManifest.xml file. * @param context the caller context for this method. - * @param permission the permession to look for in the manifest file. + * @param permission the permission to look for in the manifest file. * @return "true" if the permission is in the manifest file of the activity, "false" otherwise. */ public static boolean hasManifestPermission(Context context, String permission) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt index 3828004198..791b425444 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt @@ -99,7 +99,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf * * Must not be called before a [VkRenderer] has been set. */ - open fun onResume() { + protected fun resumeRenderThread() { vkThread.onResume() } @@ -108,7 +108,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf * * Must not be called before a [VkRenderer] has been set. */ - open fun onPause() { + protected fun pauseRenderThread() { vkThread.onPause() } diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 50075ed3f5..08e792cc04 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -484,7 +484,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * env->DeleteLocalRef(jobj); } - MessageQueue::get_singleton()->push_callp(obj, str_method, argptrs, count); + Callable(obj, str_method).call_deferredp(argptrs, count); } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result) { diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index 4e401e633e..3c950bb1b1 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -334,7 +334,7 @@ void GodotJavaWrapper::vibrate(int p_duration_ms) { } } -int GodotJavaWrapper::create_new_godot_instance(List<String> args) { +int GodotJavaWrapper::create_new_godot_instance(const List<String> &args) { if (_create_new_godot_instance) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, 0); diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index 52043c6027..93998021a9 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -104,7 +104,7 @@ public: void init_input_devices(); void vibrate(int p_duration_ms); String get_input_fallback_mapping(); - int create_new_godot_instance(List<String> args); + int create_new_godot_instance(const List<String> &args); void begin_benchmark_measure(const String &p_context, const String &p_label); void end_benchmark_measure(const String &p_context, const String &p_label); void dump_benchmark(const String &benchmark_file); diff --git a/platform/ios/SCsub b/platform/ios/SCsub index 18ba6617af..30d4216464 100644 --- a/platform/ios/SCsub +++ b/platform/ios/SCsub @@ -20,6 +20,7 @@ ios_lib = [ "device_metrics.m", "keyboard_input_view.mm", "key_mapping_ios.mm", + "ios_terminal_logger.mm", ] env_ios = env.Clone() diff --git a/platform/ios/detect.py b/platform/ios/detect.py index 26d81c8ed6..23f688501b 100644 --- a/platform/ios/detect.py +++ b/platform/ios/detect.py @@ -152,7 +152,7 @@ def configure(env: "Environment"): env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"]) if env["vulkan"]: - env.Append(CPPDEFINES=["VULKAN_ENABLED"]) + env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"]) if env["opengl3"]: env.Append(CPPDEFINES=["GLES3_ENABLED", "GLES_SILENCE_DEPRECATION"]) diff --git a/platform/ios/doc_classes/EditorExportPlatformIOS.xml b/platform/ios/doc_classes/EditorExportPlatformIOS.xml index ecae6d721e..35ef6d6a78 100644 --- a/platform/ios/doc_classes/EditorExportPlatformIOS.xml +++ b/platform/ios/doc_classes/EditorExportPlatformIOS.xml @@ -10,6 +10,13 @@ <link title="iOS plugins documentation index">$DOCS_URL/tutorials/platform/ios/index.html</link> </tutorials> <members> + <member name="application/additional_plist_content" type="String" setter="" getter=""> + Additional data added to the root [code]<dict>[/code] section of the [url=https://developer.apple.com/documentation/bundleresources/information_property_list]Info.plist[/url] file. The value should be an XML section with pairs of key-value elements, e.g.: + [codeblock] + <key>key_name</key> + <string>value</string> + [/codeblock] + </member> <member name="application/app_store_team_id" type="String" setter="" getter=""> Apple Team ID, unique 10-character string. To locate your Team ID check "Membership details" section in your Apple developer account dashboard, or "Organizational Unit" of your code signing certificate. See [url=https://developer.apple.com/help/account/manage-your-team/locate-your-team-id]Locate your Team ID[/url]. </member> @@ -34,8 +41,8 @@ <member name="application/icon_interpolation" type="int" setter="" getter=""> Interpolation method used to resize application icon. </member> - <member name="application/launch_screens_interpolation" type="int" setter="" getter=""> - Interpolation method used to resize launch screen images. + <member name="application/min_ios_version" type="String" setter="" getter=""> + Minimum version of iOS required for this application to run in the [code]major.minor.patch[/code] or [code]major.minor[/code] format, can only contain numeric characters ([code]0-9[/code]) and periods ([code].[/code]). </member> <member name="application/provisioning_profile_uuid_debug" type="String" setter="" getter=""> UUID of the provisioning profile. If left empty, Xcode will download or create a provisioning profile automatically. See [url=https://developer.apple.com/help/account/manage-profiles/edit-download-or-delete-profiles]Edit, download, or delete provisioning profiles[/url]. @@ -63,6 +70,14 @@ <member name="capabilities/access_wifi" type="bool" setter="" getter=""> If [code]true[/code], networking features related to Wi-Fi access are enabled. See [url=https://developer.apple.com/support/required-device-capabilities/]Required Device Capabilities[/url]. </member> + <member name="capabilities/performance_a12" type="bool" setter="" getter=""> + Requires the graphics performance and features of the A12 Bionic and later chips (devices supporting all Vulkan renderer features). + Enabling this option limits supported devices to: iPhone XS, iPhone XR, iPad Mini (5th gen.), iPad Air (3rd gen.), iPad (8th gen) and newer. + </member> + <member name="capabilities/performance_gaming_tier" type="bool" setter="" getter=""> + Requires the graphics performance and features of the A17 Pro and later chips. + Enabling this option limits supported devices to: iPhone 15 Pro and newer. + </member> <member name="capabilities/push_notifications" type="bool" setter="" getter=""> If [code]true[/code], push notifications are enabled. See [url=https://developer.apple.com/support/required-device-capabilities/]Required Device Capabilities[/url]. </member> @@ -108,39 +123,6 @@ <member name="icons/spotlight_80x80" type="String" setter="" getter=""> Spotlight icon file on iPad and iPhone (2x DPI). If left empty, it will fallback to [member ProjectSettings.application/config/icon]. See [url=https://developer.apple.com/design/human-interface-guidelines/foundations/app-icons]App icons[/url]. </member> - <member name="landscape_launch_screens/ipad_1024x768" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="landscape_launch_screens/ipad_2048x1536" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="landscape_launch_screens/iphone_2208x1242" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="landscape_launch_screens/iphone_2436x1125" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="portrait_launch_screens/ipad_768x1024" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="portrait_launch_screens/ipad_1536x2048" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="portrait_launch_screens/iphone_640x960" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="portrait_launch_screens/iphone_640x1136" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="portrait_launch_screens/iphone_750x1334" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="portrait_launch_screens/iphone_1125x2436" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> - <member name="portrait_launch_screens/iphone_1242x2208" type="String" setter="" getter=""> - Application launch screen image file. If left empty, it will fallback to [member ProjectSettings.application/boot_splash/image]. - </member> <member name="privacy/camera_usage_description" type="String" setter="" getter=""> A message displayed when requesting access to the device's camera (in English). </member> @@ -174,9 +156,6 @@ <member name="storyboard/use_custom_bg_color" type="bool" setter="" getter=""> If [code]true[/code], [member storyboard/custom_bg_color] is used as a launch screen background color, otherwise [code]application/boot_splash/bg_color[/code] project setting is used. </member> - <member name="storyboard/use_launch_screen_storyboard" type="bool" setter="" getter=""> - If [code]true[/code], storyboard launch screen is used instead of launch screen images. - </member> <member name="user_data/accessible_from_files_app" type="bool" setter="" getter=""> If [code]true[/code], the app "Documents" folder can be accessed via "Files" app. See [url=https://developer.apple.com/documentation/bundleresources/information_property_list/lssupportsopeningdocumentsinplace]LSSupportsOpeningDocumentsInPlace[/url]. </member> diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index b478759e45..d35819c34d 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -34,14 +34,15 @@ #include "run_icon_svg.gen.h" #include "core/io/json.h" +#include "core/io/plist.h" #include "core/string/translation.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/export/editor_export.h" #include "editor/import/resource_importer_texture_settings.h" #include "editor/plugins/script_editor_plugin.h" +#include "editor/themes/editor_scale.h" #include "modules/modules_enabled.gen.h" // For mono and svg. #ifdef MODULE_SVG_ENABLED @@ -105,29 +106,6 @@ static const IconInfo icon_infos[] = { { PNAME("icons/notification_60x60"), "iphone", "Icon-60.png", "60", "3x", "20x20", false } }; -struct LoadingScreenInfo { - const char *preset_key; - const char *export_name; - int width = 0; - int height = 0; - bool rotate = false; -}; - -static const LoadingScreenInfo loading_screen_infos[] = { - { PNAME("landscape_launch_screens/iphone_2436x1125"), "Default-Landscape-X.png", 2436, 1125, false }, - { PNAME("landscape_launch_screens/iphone_2208x1242"), "Default-Landscape-736h@3x.png", 2208, 1242, false }, - { PNAME("landscape_launch_screens/ipad_1024x768"), "Default-Landscape.png", 1024, 768, false }, - { PNAME("landscape_launch_screens/ipad_2048x1536"), "Default-Landscape@2x.png", 2048, 1536, false }, - - { PNAME("portrait_launch_screens/iphone_640x960"), "Default-480h@2x.png", 640, 960, false }, - { PNAME("portrait_launch_screens/iphone_640x1136"), "Default-568h@2x.png", 640, 1136, false }, - { PNAME("portrait_launch_screens/iphone_750x1334"), "Default-667h@2x.png", 750, 1334, false }, - { PNAME("portrait_launch_screens/iphone_1125x2436"), "Default-Portrait-X.png", 1125, 2436, false }, - { PNAME("portrait_launch_screens/ipad_768x1024"), "Default-Portrait.png", 768, 1024, false }, - { PNAME("portrait_launch_screens/ipad_1536x2048"), "Default-Portrait@2x.png", 1536, 2048, false }, - { PNAME("portrait_launch_screens/iphone_1242x2208"), "Default-Portrait-736h@3x.png", 1242, 2208, false } -}; - String EditorExportPlatformIOS::get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const { if (p_preset) { if (p_name == "application/app_store_team_id") { @@ -147,12 +125,6 @@ String EditorExportPlatformIOS::get_export_option_warning(const EditorExportPres } bool EditorExportPlatformIOS::get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const { - if (p_preset) { - bool sb = p_preset->get("storyboard/use_launch_screen_storyboard"); - if (!sb && p_option != "storyboard/use_launch_screen_storyboard" && p_option.begins_with("storyboard/")) { - return false; - } - } return true; } @@ -181,8 +153,11 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/min_ios_version"), "12.0")); + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/additional_plist_content", PROPERTY_HINT_MULTILINE_TEXT), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/launch_screens_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/export_project_only"), false)); @@ -217,6 +192,8 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/push_notifications"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/performance_gaming_tier"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/performance_a12"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_files_app"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false)); @@ -235,16 +212,11 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, icon_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); } } - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false, true)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::COLOR, "storyboard/custom_bg_color"), Color())); - - for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); - } } void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug) { @@ -262,8 +234,8 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ }; String dbg_sign_id = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : p_preset->get("application/code_sign_identity_debug"); String rel_sign_id = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : p_preset->get("application/code_sign_identity_release"); - bool dbg_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_IOS_PROFILE_UUID_DEBUG).operator String().is_empty() || (dbg_sign_id != "iPhone Developer"); - bool rel_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE).operator String().is_empty() || (rel_sign_id != "iPhone Distribution"); + bool dbg_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_IOS_PROFILE_UUID_DEBUG).operator String().is_empty() || (dbg_sign_id != "iPhone Developer" && dbg_sign_id != "iPhone Distribution"); + bool rel_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE).operator String().is_empty() || (rel_sign_id != "iPhone Developer" && rel_sign_id != "iPhone Distribution"); String str; String strnew; str.parse_utf8((const char *)pfile.ptr(), pfile.size()); @@ -287,6 +259,8 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$short_version", p_preset->get_version("application/short_version")) + "\n"; } else if (lines[i].find("$version") != -1) { strnew += lines[i].replace("$version", p_preset->get_version("application/version")) + "\n"; + } else if (lines[i].find("$min_version") != -1) { + strnew += lines[i].replace("$min_version", p_preset->get("application/min_ios_version")) + "\n"; } else if (lines[i].find("$signature") != -1) { strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n"; } else if (lines[i].find("$team_id") != -1) { @@ -359,7 +333,12 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ if ((bool)p_preset->get("capabilities/access_wifi") && !capabilities_list.has("wifi")) { capabilities_list.push_back("wifi"); } - + if ((bool)p_preset->get("capabilities/performance_gaming_tier") && !capabilities_list.has("iphone-performance-gaming-tier")) { + capabilities_list.push_back("iphone-performance-gaming-tier"); + } + if ((bool)p_preset->get("capabilities/performance_a12") && !capabilities_list.has("iphone-ipad-minimum-performance-a12")) { + capabilities_list.push_back("iphone-ipad-minimum-performance-a12"); + } for (int idx = 0; idx < capabilities_list.size(); idx++) { capabilities += "<string>" + capabilities_list[idx] + "</string>\n"; } @@ -413,29 +392,20 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ String description = p_preset->get("privacy/photolibrary_usage_description"); strnew += lines[i].replace("$photolibrary_usage_description", description) + "\n"; } else if (lines[i].find("$plist_launch_screen_name") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "<key>UILaunchStoryboardName</key>\n<string>Launch Screen</string>" : ""; + String value = "<key>UILaunchStoryboardName</key>\n<string>Launch Screen</string>"; strnew += lines[i].replace("$plist_launch_screen_name", value) + "\n"; } else if (lines[i].find("$pbx_launch_screen_file_reference") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "90DD2D9D24B36E8000717FE1 = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = \"Launch Screen.storyboard\"; sourceTree = \"<group>\"; };" : ""; + String value = "90DD2D9D24B36E8000717FE1 = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = \"Launch Screen.storyboard\"; sourceTree = \"<group>\"; };"; strnew += lines[i].replace("$pbx_launch_screen_file_reference", value) + "\n"; } else if (lines[i].find("$pbx_launch_screen_copy_files") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */," : ""; + String value = "90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */,"; strnew += lines[i].replace("$pbx_launch_screen_copy_files", value) + "\n"; } else if (lines[i].find("$pbx_launch_screen_build_phase") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */," : ""; + String value = "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */,"; strnew += lines[i].replace("$pbx_launch_screen_build_phase", value) + "\n"; } else if (lines[i].find("$pbx_launch_screen_build_reference") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */; };" : ""; + String value = "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */; };"; strnew += lines[i].replace("$pbx_launch_screen_build_reference", value) + "\n"; - } else if (lines[i].find("$pbx_launch_image_usage_setting") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "" : "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;"; - strnew += lines[i].replace("$pbx_launch_image_usage_setting", value) + "\n"; } else if (lines[i].find("$launch_screen_image_mode") != -1) { int image_scale_mode = p_preset->get("storyboard/image_scale_mode"); String value; @@ -783,94 +753,6 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor return OK; } -Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) { - Ref<DirAccess> da = DirAccess::open(p_dest_dir); - ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'."); - - for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) { - LoadingScreenInfo info = loading_screen_infos[i]; - String loading_screen_file = p_preset->get(info.preset_key); - - Color boot_bg_color = GLOBAL_GET("application/boot_splash/bg_color"); - String boot_logo_path = GLOBAL_GET("application/boot_splash/image"); - bool boot_logo_scale = GLOBAL_GET("application/boot_splash/fullsize"); - - if (loading_screen_file.size() > 0) { - // Load custom loading screens, and resize if required. - Ref<Image> img = memnew(Image); - Error err = ImageLoader::load_image(loading_screen_file, img); - if (err != OK) { - ERR_PRINT("Invalid loading screen (" + String(info.preset_key) + "): '" + loading_screen_file + "'."); - return ERR_UNCONFIGURED; - } - if (img->get_width() != info.width || img->get_height() != info.height) { - WARN_PRINT("Loading screen (" + String(info.preset_key) + "): '" + loading_screen_file + "' has incorrect size (" + String::num_int64(img->get_width()) + "x" + String::num_int64(img->get_height()) + ") and was automatically resized to " + String::num_int64(info.width) + "x" + String::num_int64(info.height) + "."); - float aspect_ratio = (float)img->get_width() / (float)img->get_height(); - if (boot_logo_scale) { - if (info.height * aspect_ratio <= info.width) { - img->resize(info.height * aspect_ratio, info.height, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int())); - } else { - img->resize(info.width, info.width / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int())); - } - } - Ref<Image> new_img = Image::create_empty(info.width, info.height, false, Image::FORMAT_RGBA8); - new_img->fill(boot_bg_color); - _blend_and_rotate(new_img, img, false); - err = new_img->save_png(p_dest_dir + info.export_name); - } else { - err = da->copy(loading_screen_file, p_dest_dir + info.export_name); - } - if (err) { - String err_str = String("Failed to export loading screen (") + info.preset_key + ") from path '" + loading_screen_file + "'."; - ERR_PRINT(err_str.utf8().get_data()); - return err; - } - } else { - // Generate loading screen from the splash screen - Ref<Image> img = Image::create_empty(info.width, info.height, false, Image::FORMAT_RGBA8); - img->fill(boot_bg_color); - - Ref<Image> img_bs; - - if (boot_logo_path.length() > 0) { - img_bs = Ref<Image>(memnew(Image)); - ImageLoader::load_image(boot_logo_path, img_bs); - } - if (!img_bs.is_valid()) { - img_bs = Ref<Image>(memnew(Image(boot_splash_png))); - } - if (img_bs.is_valid()) { - float aspect_ratio = (float)img_bs->get_width() / (float)img_bs->get_height(); - if (info.rotate) { - if (boot_logo_scale) { - if (info.width * aspect_ratio <= info.height) { - img_bs->resize(info.width * aspect_ratio, info.width, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int())); - } else { - img_bs->resize(info.height, info.height / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int())); - } - } - } else { - if (boot_logo_scale) { - if (info.height * aspect_ratio <= info.width) { - img_bs->resize(info.height * aspect_ratio, info.height, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int())); - } else { - img_bs->resize(info.width, info.width / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int())); - } - } - } - _blend_and_rotate(img, img_bs, info.rotate); - } - Error err = img->save_png(p_dest_dir + info.export_name); - if (err) { - String err_str = String("Failed to export loading screen (") + info.preset_key + ") from splash screen."; - WARN_PRINT(err_str.utf8().get_data()); - } - } - } - - return OK; -} - Error EditorExportPlatformIOS::_walk_dir_recursive(Ref<DirAccess> &p_da, FileHandler p_handler, void *p_userdata) { Vector<String> dirs; String current_dir = p_da->get_current_dir(); @@ -986,7 +868,183 @@ struct ExportLibsData { String dest_dir; }; -void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets) { +void EditorExportPlatformIOS::_check_xcframework_content(const String &p_path, int &r_total_libs, int &r_static_libs, int &r_dylibs, int &r_frameworks) const { + Ref<PList> plist; + plist.instantiate(); + plist->load_file(p_path.path_join("Info.plist")); + Ref<PListNode> root_node = plist->get_root(); + if (root_node.is_null()) { + return; + } + Dictionary root = root_node->get_value(); + if (!root.has("AvailableLibraries")) { + return; + } + Ref<PListNode> libs_node = root["AvailableLibraries"]; + if (libs_node.is_null()) { + return; + } + Array libs = libs_node->get_value(); + r_total_libs = libs.size(); + for (int j = 0; j < libs.size(); j++) { + Ref<PListNode> lib_node = libs[j]; + if (lib_node.is_null()) { + return; + } + Dictionary lib = lib_node->get_value(); + if (lib.has("BinaryPath")) { + Ref<PListNode> path_node = lib["BinaryPath"]; + if (path_node.is_valid()) { + String path = path_node->get_value(); + if (path.ends_with(".a")) { + r_static_libs++; + } + if (path.ends_with(".dylib")) { + r_dylibs++; + } + if (path.ends_with(".framework")) { + r_frameworks++; + } + } + } + } +} + +Error EditorExportPlatformIOS::_convert_to_framework(const String &p_source, const String &p_destination, const String &p_id) const { + print_line("Converting to .framework", p_source, " -> ", p_destination); + + Ref<DirAccess> da = DirAccess::create_for_path(p_source); + if (da.is_null()) { + return ERR_CANT_OPEN; + } + + Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + if (filesystem_da.is_null()) { + return ERR_CANT_OPEN; + } + + if (!filesystem_da->dir_exists(p_destination)) { + Error make_dir_err = filesystem_da->make_dir_recursive(p_destination); + if (make_dir_err) { + return make_dir_err; + } + } + + String asset = p_source.ends_with("/") ? p_source.left(p_source.length() - 1) : p_source; + if (asset.ends_with(".xcframework")) { + Ref<PList> plist; + plist.instantiate(); + plist->load_file(p_source.path_join("Info.plist")); + Ref<PListNode> root_node = plist->get_root(); + if (root_node.is_null()) { + return ERR_CANT_OPEN; + } + Dictionary root = root_node->get_value(); + if (!root.has("AvailableLibraries")) { + return ERR_CANT_OPEN; + } + Ref<PListNode> libs_node = root["AvailableLibraries"]; + if (libs_node.is_null()) { + return ERR_CANT_OPEN; + } + Array libs = libs_node->get_value(); + for (int j = 0; j < libs.size(); j++) { + Ref<PListNode> lib_node = libs[j]; + if (lib_node.is_null()) { + return ERR_CANT_OPEN; + } + Dictionary lib = lib_node->get_value(); + if (lib.has("BinaryPath") && lib.has("LibraryPath") && lib.has("LibraryIdentifier")) { + Ref<PListNode> bpath_node = lib["BinaryPath"]; + Ref<PListNode> lpath_node = lib["LibraryPath"]; + Ref<PListNode> lid_node = lib["LibraryIdentifier"]; + if (bpath_node.is_valid() && lpath_node.is_valid() && lid_node.is_valid()) { + String binary_path = bpath_node->get_value(); + String library_identifier = lid_node->get_value(); + + String file_name = binary_path.get_basename().get_file(); + String framework_name = file_name + ".framework"; + + bpath_node->data_string = framework_name.utf8(); + lpath_node->data_string = framework_name.utf8(); + if (!filesystem_da->dir_exists(p_destination.path_join(library_identifier))) { + filesystem_da->make_dir_recursive(p_destination.path_join(library_identifier)); + } + _convert_to_framework(p_source.path_join(library_identifier).path_join(binary_path), p_destination.path_join(library_identifier).path_join(framework_name), p_id); + if (lib.has("DebugSymbolsPath")) { + Ref<PListNode> dpath_node = lib["DebugSymbolsPath"]; + if (dpath_node.is_valid()) { + String dpath = dpath_node->get_value(); + if (da->dir_exists(p_source.path_join(library_identifier).path_join(dpath))) { + da->copy_dir(p_source.path_join(library_identifier).path_join(dpath), p_destination.path_join(library_identifier).path_join("dSYMs")); + } + } + } + } + } + } + String info_plist = plist->save_text(); + + Ref<FileAccess> f = FileAccess::open(p_destination.path_join("Info.plist"), FileAccess::WRITE); + if (f.is_valid()) { + f->store_string(info_plist); + } + } else { + String file_name = p_destination.get_basename().get_file(); + String framework_name = file_name + ".framework"; + + da->copy(p_source, p_destination.path_join(file_name)); + + // Performing `install_name_tool -id @rpath/{name}.framework/{name} ./{name}` on dylib + { + List<String> install_name_args; + install_name_args.push_back("-id"); + install_name_args.push_back(String("@rpath").path_join(framework_name).path_join(file_name)); + install_name_args.push_back(p_destination.path_join(file_name)); + + OS::get_singleton()->execute("install_name_tool", install_name_args); + } + + // Creating Info.plist + { + String info_plist_format = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" + "<plist version=\"1.0\">\n" + " <dict>\n" + " <key>CFBundleShortVersionString</key>\n" + " <string>1.0</string>\n" + " <key>CFBundleIdentifier</key>\n" + " <string>$id.framework.$name</string>\n" + " <key>CFBundleName</key>\n" + " <string>$name</string>\n" + " <key>CFBundleExecutable</key>\n" + " <string>$name</string>\n" + " <key>DTPlatformName</key>\n" + " <string>iphoneos</string>\n" + " <key>CFBundleInfoDictionaryVersion</key>\n" + " <string>6.0</string>\n" + " <key>CFBundleVersion</key>\n" + " <string>1</string>\n" + " <key>CFBundlePackageType</key>\n" + " <string>FMWK</string>\n" + " <key>MinimumOSVersion</key>\n" + " <string>12.0</string>\n" + " </dict>\n" + "</plist>"; + + String info_plist = info_plist_format.replace("$id", p_id).replace("$name", file_name); + + Ref<FileAccess> f = FileAccess::open(p_destination.path_join("Info.plist"), FileAccess::WRITE); + if (f.is_valid()) { + f->store_string(info_plist); + } + } + } + + return OK; +} + +void EditorExportPlatformIOS::_add_assets_to_project(const String &p_out_dir, const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets) { // that is just a random number, we just need Godot IDs not to clash with // existing IDs in the project. PbxId current_id = { 0x58938401, 0, 0 }; @@ -1011,7 +1069,12 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese String type; if (asset.exported_path.ends_with(".framework")) { - if (asset.should_embed) { + int total_libs = 0; + int static_libs = 0; + int dylibs = 0; + int frameworks = 0; + _check_xcframework_content(p_out_dir.path_join(asset.exported_path), total_libs, static_libs, dylibs, frameworks); + if (asset.should_embed && (static_libs != total_libs)) { additional_asset_info_format += "$framework_id = {isa = PBXBuildFile; fileRef = $ref_id; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n"; framework_id = (++current_id).str(); pbx_embeded_frameworks += framework_id + ",\n"; @@ -1074,12 +1137,12 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese } } -Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) { +Error EditorExportPlatformIOS::_copy_asset(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) { String binary_name = p_out_dir.get_file().get_basename(); Ref<DirAccess> da = DirAccess::create_for_path(p_asset); if (da.is_null()) { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + "."); + ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't open directory: " + p_asset + "."); } bool file_exists = da->file_exists(p_asset); bool dir_exists = da->dir_exists(p_asset); @@ -1093,7 +1156,8 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String String destination; String asset_path; - bool create_framework = false; + Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND_V_MSG(filesystem_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'."); if (p_is_framework && asset.ends_with(".dylib")) { // For iOS we need to turn .dylib into .framework @@ -1113,10 +1177,23 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String asset_path = asset_path.path_join(framework_name); destination_dir = p_out_dir.path_join(asset_path); destination = destination_dir.path_join(file_name); - create_framework = true; - } else if (p_is_framework && (asset.ends_with(".framework") || asset.ends_with(".xcframework"))) { - asset_path = String("dylibs").path_join(base_dir); + // Convert to framework and copy. + Error err = _convert_to_framework(p_asset, destination, p_preset->get("application/bundle_identifier")); + if (err) { + return err; + } + } else if (p_is_framework && asset.ends_with(".xcframework")) { + // For iOS we need to turn .dylib inside .xcframework + // into .framework to be able to send application to AppStore + + int total_libs = 0; + int static_libs = 0; + int dylibs = 0; + int frameworks = 0; + _check_xcframework_content(p_asset, total_libs, static_libs, dylibs, frameworks); + + asset_path = String("dylibs").path_join(base_dir); String file_name; if (!p_custom_file_name) { @@ -1128,8 +1205,29 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String asset_path = asset_path.path_join(file_name); destination_dir = p_out_dir.path_join(asset_path); destination = destination_dir; - } else { - asset_path = base_dir; + + if (dylibs > 0) { + // Convert to framework and copy. + Error err = _convert_to_framework(p_asset, destination, p_preset->get("application/bundle_identifier")); + if (err) { + return err; + } + } else { + // Copy as is. + if (!filesystem_da->dir_exists(destination_dir)) { + Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); + if (make_dir_err) { + return make_dir_err; + } + } + Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination); + if (err) { + return err; + } + } + } else if (p_is_framework && asset.ends_with(".framework")) { + // Framework. + asset_path = String("dylibs").path_join(base_dir); String file_name; @@ -1139,99 +1237,67 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String file_name = *p_custom_file_name; } - destination_dir = p_out_dir.path_join(asset_path); asset_path = asset_path.path_join(file_name); - destination = p_out_dir.path_join(asset_path); - } - - Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V_MSG(filesystem_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'."); + destination_dir = p_out_dir.path_join(asset_path); + destination = destination_dir; - if (!filesystem_da->dir_exists(destination_dir)) { - Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); - if (make_dir_err) { - return make_dir_err; + // Copy as is. + if (!filesystem_da->dir_exists(destination_dir)) { + Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); + if (make_dir_err) { + return make_dir_err; + } } - } - - Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination); - if (err) { - return err; - } - if (asset_path.ends_with("/")) { - asset_path = asset_path.left(asset_path.length() - 1); - } - IOSExportAsset exported_asset = { binary_name.path_join(asset_path), p_is_framework, p_should_embed }; - r_exported_assets.push_back(exported_asset); + Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination); + if (err) { + return err; + } + } else { + // Unknown resource. + asset_path = base_dir; - if (create_framework) { String file_name; if (!p_custom_file_name) { - file_name = p_asset.get_basename().get_file(); + file_name = p_asset.get_file(); } else { file_name = *p_custom_file_name; } - String framework_name = file_name + ".framework"; - - // Performing `install_name_tool -id @rpath/{name}.framework/{name} ./{name}` on dylib - { - List<String> install_name_args; - install_name_args.push_back("-id"); - install_name_args.push_back(String("@rpath").path_join(framework_name).path_join(file_name)); - install_name_args.push_back(destination); - - OS::get_singleton()->execute("install_name_tool", install_name_args); - } - - // Creating Info.plist - { - String info_plist_format = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" - "<plist version=\"1.0\">\n" - "<dict>\n" - "<key>CFBundleShortVersionString</key>\n" - "<string>1.0</string>\n" - "<key>CFBundleIdentifier</key>\n" - "<string>com.gdextension.framework.$name</string>\n" - "<key>CFBundleName</key>\n" - "<string>$name</string>\n" - "<key>CFBundleExecutable</key>\n" - "<string>$name</string>\n" - "<key>DTPlatformName</key>\n" - "<string>iphoneos</string>\n" - "<key>CFBundleInfoDictionaryVersion</key>\n" - "<string>6.0</string>\n" - "<key>CFBundleVersion</key>\n" - "<string>1</string>\n" - "<key>CFBundlePackageType</key>\n" - "<string>FMWK</string>\n" - "<key>MinimumOSVersion</key>\n" - "<string>10.0</string>\n" - "</dict>\n" - "</plist>"; - - String info_plist = info_plist_format.replace("$name", file_name); + destination_dir = p_out_dir.path_join(asset_path); + asset_path = asset_path.path_join(file_name); + destination = p_out_dir.path_join(asset_path); - Ref<FileAccess> f = FileAccess::open(destination_dir.path_join("Info.plist"), FileAccess::WRITE); - if (f.is_valid()) { - f->store_string(info_plist); + // Copy as is. + if (!filesystem_da->dir_exists(destination_dir)) { + Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); + if (make_dir_err) { + return make_dir_err; } } + Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination); + if (err) { + return err; + } } + if (asset_path.ends_with("/")) { + asset_path = asset_path.left(asset_path.length() - 1); + } + IOSExportAsset exported_asset = { binary_name.path_join(asset_path), p_is_framework, p_should_embed }; + r_exported_assets.push_back(exported_asset); + return OK; } -Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) { +Error EditorExportPlatformIOS::_export_additional_assets(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) { for (int f_idx = 0; f_idx < p_assets.size(); ++f_idx) { - String asset = p_assets[f_idx]; + const String &asset = p_assets[f_idx]; if (asset.begins_with("res://")) { - Error err = _copy_asset(p_out_dir, asset, nullptr, p_is_framework, p_should_embed, r_exported_assets); + Error err = _copy_asset(p_preset, p_out_dir, asset, nullptr, p_is_framework, p_should_embed, r_exported_assets); ERR_FAIL_COND_V(err != OK, err); } else if (ProjectSettings::get_singleton()->localize_path(asset).begins_with("res://")) { - Error err = _copy_asset(p_out_dir, ProjectSettings::get_singleton()->localize_path(asset), nullptr, p_is_framework, p_should_embed, r_exported_assets); + Error err = _copy_asset(p_preset, p_out_dir, ProjectSettings::get_singleton()->localize_path(asset), nullptr, p_is_framework, p_should_embed, r_exported_assets); ERR_FAIL_COND_V(err != OK, err); } else { // either SDK-builtin or already a part of the export template @@ -1243,26 +1309,26 @@ Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir return OK; } -Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets) { +Error EditorExportPlatformIOS::_export_additional_assets(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets) { Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); for (int i = 0; i < export_plugins.size(); i++) { Vector<String> linked_frameworks = export_plugins[i]->get_ios_frameworks(); - Error err = _export_additional_assets(p_out_dir, linked_frameworks, true, false, r_exported_assets); + Error err = _export_additional_assets(p_preset, p_out_dir, linked_frameworks, true, false, r_exported_assets); ERR_FAIL_COND_V(err, err); Vector<String> embedded_frameworks = export_plugins[i]->get_ios_embedded_frameworks(); - err = _export_additional_assets(p_out_dir, embedded_frameworks, true, true, r_exported_assets); + err = _export_additional_assets(p_preset, p_out_dir, embedded_frameworks, true, true, r_exported_assets); ERR_FAIL_COND_V(err, err); Vector<String> project_static_libs = export_plugins[i]->get_ios_project_static_libs(); for (int j = 0; j < project_static_libs.size(); j++) { project_static_libs.write[j] = project_static_libs[j].get_file(); // Only the file name as it's copied to the project } - err = _export_additional_assets(p_out_dir, project_static_libs, true, false, r_exported_assets); + err = _export_additional_assets(p_preset, p_out_dir, project_static_libs, true, false, r_exported_assets); ERR_FAIL_COND_V(err, err); Vector<String> ios_bundle_files = export_plugins[i]->get_ios_bundle_files(); - err = _export_additional_assets(p_out_dir, ios_bundle_files, false, false, r_exported_assets); + err = _export_additional_assets(p_preset, p_out_dir, ios_bundle_files, false, false, r_exported_assets); ERR_FAIL_COND_V(err, err); } @@ -1270,7 +1336,7 @@ Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir for (int i = 0; i < p_libraries.size(); ++i) { library_paths.push_back(p_libraries[i].path); } - Error err = _export_additional_assets(p_out_dir, library_paths, true, true, r_exported_assets); + Error err = _export_additional_assets(p_preset, p_out_dir, library_paths, true, true, r_exported_assets); ERR_FAIL_COND_V(err, err); return OK; @@ -1315,7 +1381,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> String plugin_binary_result_file = plugin.binary.get_file(); // We shouldn't embed .xcframework that contains static libraries. // Static libraries are not embedded anyway. - err = _copy_asset(dest_dir, plugin_main_binary, &plugin_binary_result_file, true, false, r_exported_assets); + err = _copy_asset(p_preset, dest_dir, plugin_main_binary, &plugin_binary_result_file, true, false, r_exported_assets); ERR_FAIL_COND_V(err != OK, err); // Adding dependencies. @@ -1440,15 +1506,15 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> // Export files { // Export linked plugin dependency - err = _export_additional_assets(dest_dir, plugin_linked_dependencies, true, false, r_exported_assets); + err = _export_additional_assets(p_preset, dest_dir, plugin_linked_dependencies, true, false, r_exported_assets); ERR_FAIL_COND_V(err != OK, err); // Export embedded plugin dependency - err = _export_additional_assets(dest_dir, plugin_embedded_dependencies, true, true, r_exported_assets); + err = _export_additional_assets(p_preset, dest_dir, plugin_embedded_dependencies, true, true, r_exported_assets); ERR_FAIL_COND_V(err != OK, err); // Export plugin files - err = _export_additional_assets(dest_dir, plugin_files, false, false, r_exported_assets); + err = _export_additional_assets(p_preset, dest_dir, plugin_files, false, false, r_exported_assets); ERR_FAIL_COND_V(err != OK, err); } @@ -1619,6 +1685,8 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres false }; + config_data.plist_content += p_preset->get("application/additional_plist_content").operator String() + "\n"; + Vector<IOSExportAsset> assets; Ref<DirAccess> tmp_app_path = DirAccess::create_for_path(dest_dir); @@ -1824,9 +1892,6 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres } { - bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard"); - - String launch_image_path = binary_dir + "/Images.xcassets/LaunchImage.launchimage/"; String splash_image_path = binary_dir + "/Images.xcassets/SplashImage.imageset/"; Ref<DirAccess> launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -1835,30 +1900,11 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres return ERR_CANT_CREATE; } - if (use_storyboard) { - print_line("Using Launch Storyboard"); + print_line("Exporting launch screen storyboard"); - if (launch_screen_da->change_dir(launch_image_path) == OK) { - launch_screen_da->erase_contents_recursive(); - launch_screen_da->remove(launch_image_path); - } - - err = _export_loading_screen_file(p_preset, splash_image_path); + err = _export_loading_screen_file(p_preset, splash_image_path); + if (err != OK) { add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Failed to create a file at path \"%s\" with code %d."), splash_image_path, err)); - } else { - print_line("Using Launch Images"); - - const String launch_screen_path = binary_dir + "/Launch Screen.storyboard"; - - launch_screen_da->remove(launch_screen_path); - - if (launch_screen_da->change_dir(splash_image_path) == OK) { - launch_screen_da->erase_contents_recursive(); - launch_screen_da->remove(splash_image_path); - } - - err = _export_loading_screen_images(p_preset, launch_image_path); - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Failed to create a file at path \"%s\" with code %d."), launch_image_path, err)); } } @@ -1867,8 +1913,8 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres } print_line("Exporting additional assets"); - _export_additional_assets(binary_dir, libraries, assets); - _add_assets_to_project(p_preset, project_file_data, assets); + _export_additional_assets(p_preset, binary_dir, libraries, assets); + _add_assets_to_project(dest_dir, p_preset, project_file_data, assets); String project_file_name = binary_dir + ".xcodeproj/project.pbxproj"; { Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE); @@ -2010,6 +2056,26 @@ bool EditorExportPlatformIOS::has_valid_export_configuration(const Ref<EditorExp valid = dvalid || rvalid; r_missing_templates = !valid; + const String &additional_plist_content = p_preset->get("application/additional_plist_content"); + if (!additional_plist_content.is_empty()) { + const String &plist = vformat("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" + "<plist version=\"1.0\">" + "<dict>\n" + "%s\n" + "</dict>\n" + "</plist>\n", + additional_plist_content); + + String plist_err; + Ref<PList> plist_parser; + plist_parser.instantiate(); + if (!plist_parser->load_string(plist, plist_err)) { + err += TTR("Invalid additional PList content: ") + plist_err + "\n"; + valid = false; + } + } + if (!err.is_empty()) { r_error = err; } diff --git a/platform/ios/export/export_plugin.h b/platform/ios/export/export_plugin.h index fd2243bcda..edbe566dab 100644 --- a/platform/ios/export/export_plugin.h +++ b/platform/ios/export/export_plugin.h @@ -127,17 +127,19 @@ class EditorExportPlatformIOS : public EditorExportPlatform { String _get_linker_flags(); String _get_cpp_code(); void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug); - Error _export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir); Error _export_loading_screen_file(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir); Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir); Vector<ExportArchitecture> _get_supported_architectures() const; Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset) const; - void _add_assets_to_project(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets); - Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets); - Error _copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets); - Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets); + void _check_xcframework_content(const String &p_path, int &r_total_libs, int &r_static_libs, int &r_dylibs, int &r_frameworks) const; + Error _convert_to_framework(const String &p_source, const String &p_destination, const String &p_id) const; + + void _add_assets_to_project(const String &p_out_dir, const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets); + Error _export_additional_assets(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets); + Error _copy_asset(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets); + Error _export_additional_assets(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets); Error _export_ios_plugins(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector<IOSExportAsset> &r_exported_assets, bool p_debug); Error _export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags, bool p_simulator, bool p_oneclick); diff --git a/platform/ios/ios_terminal_logger.h b/platform/ios/ios_terminal_logger.h new file mode 100644 index 0000000000..7f0bc37a07 --- /dev/null +++ b/platform/ios/ios_terminal_logger.h @@ -0,0 +1,45 @@ +/**************************************************************************/ +/* ios_terminal_logger.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef IOS_TERMINAL_LOGGER_H +#define IOS_TERMINAL_LOGGER_H + +#ifdef IOS_ENABLED + +#include "core/io/logger.h" + +class IOSTerminalLogger : public StdLogger { +public: + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR) override; +}; + +#endif // IOS_ENABLED + +#endif // IOS_TERMINAL_LOGGER_H diff --git a/platform/ios/ios_terminal_logger.mm b/platform/ios/ios_terminal_logger.mm new file mode 100644 index 0000000000..b4c9821cdc --- /dev/null +++ b/platform/ios/ios_terminal_logger.mm @@ -0,0 +1,74 @@ +/**************************************************************************/ +/* ios_terminal_logger.mm */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "ios_terminal_logger.h" + +#ifdef IOS_ENABLED + +#include <os/log.h> + +void IOSTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) { + if (!should_log(true)) { + return; + } + + const char *err_details; + if (p_rationale && p_rationale[0]) { + err_details = p_rationale; + } else { + err_details = p_code; + } + + switch (p_type) { + case ERR_WARNING: + os_log_info(OS_LOG_DEFAULT, + "WARNING: %{public}s\nat: %{public}s (%{public}s:%i)", + err_details, p_function, p_file, p_line); + break; + case ERR_SCRIPT: + os_log_error(OS_LOG_DEFAULT, + "SCRIPT ERROR: %{public}s\nat: %{public}s (%{public}s:%i)", + err_details, p_function, p_file, p_line); + break; + case ERR_SHADER: + os_log_error(OS_LOG_DEFAULT, + "SHADER ERROR: %{public}s\nat: %{public}s (%{public}s:%i)", + err_details, p_function, p_file, p_line); + break; + case ERR_ERROR: + default: + os_log_error(OS_LOG_DEFAULT, + "ERROR: %{public}s\nat: %{public}s (%{public}s:%i)", + err_details, p_function, p_file, p_line); + break; + } +} + +#endif // IOS_ENABLED diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm index a646705305..6ac21fa9c8 100644 --- a/platform/ios/os_ios.mm +++ b/platform/ios/os_ios.mm @@ -35,6 +35,7 @@ #import "app_delegate.h" #import "display_server_ios.h" #import "godot_view.h" +#import "ios_terminal_logger.h" #import "view_controller.h" #include "core/config/project_settings.h" @@ -105,12 +106,7 @@ OS_IOS::OS_IOS() { main_loop = nullptr; Vector<Logger *> loggers; - loggers.push_back(memnew(SyslogLogger)); -#ifdef DEBUG_ENABLED - // it seems iOS app's stdout/stderr is only obtainable if you launch it from - // Xcode - loggers.push_back(memnew(StdLogger)); -#endif + loggers.push_back(memnew(IOSTerminalLogger)); _set_logger(memnew(CompositeLogger(loggers))); AudioDriverManager::add_driver(&audio_driver); @@ -257,6 +253,8 @@ Error OS_IOS::open_dynamic_library(const String p_path, void *&p_library_handle, path = get_framework_executable(get_executable_path().get_base_dir().path_join("Frameworks").path_join(p_path.get_file().get_basename() + ".framework")); } + ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND); + p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW); ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror())); diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 59cc6e7962..eaaaad82b9 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -434,7 +434,7 @@ def configure(env: "Environment"): env.Append(CPPDEFINES=["X11_ENABLED"]) if env["vulkan"]: - env.Append(CPPDEFINES=["VULKAN_ENABLED"]) + env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"]) if not env["use_volk"]: env.ParseConfig("pkg-config vulkan --cflags --libs") if not env["builtin_glslang"]: diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp index 64efcffae3..773b124c6a 100644 --- a/platform/linuxbsd/export/export_plugin.cpp +++ b/platform/linuxbsd/export/export_plugin.cpp @@ -36,9 +36,9 @@ #include "core/config/project_settings.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/export/editor_export.h" +#include "editor/themes/editor_scale.h" #include "modules/modules_enabled.gen.h" // For svg. #ifdef MODULE_SVG_ENABLED diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp index 6a5b5b8064..3641f20c70 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.cpp +++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp @@ -162,7 +162,7 @@ void FreeDesktopPortalDesktop::append_dbus_dict_filters(DBusMessageIter *p_iter, append_dbus_string(&struct_iter, p_filter_names[i]); dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, "(us)", &array_iter); - String flt = p_filter_exts[i]; + const String &flt = p_filter_exts[i]; int filter_slice_count = flt.get_slice_count(","); for (int j = 0; j < filter_slice_count; j++) { dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, nullptr, &array_struct_iter); diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index d22d398a67..aed8574902 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -316,7 +316,7 @@ Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const { continue; } String device_class = columns[1].trim_suffix(":"); - String vendor_device_id_mapping = columns[2]; + const String &vendor_device_id_mapping = columns[2]; #ifdef MODULE_REGEX_ENABLED if (regex_id_format.search(vendor_device_id_mapping).is_null()) { diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index d774a117e8..2fff4ce32c 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -2891,10 +2891,15 @@ void DisplayServerX11::window_move_to_foreground(WindowID p_window) { XFlush(x11_display); } +DisplayServerX11::WindowID DisplayServerX11::get_focused_window() const { + return last_focused_window; +} + bool DisplayServerX11::window_is_focused(WindowID p_window) const { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(!windows.has(p_window), false); + const WindowData &wd = windows[p_window]; return wd.focused; @@ -3875,7 +3880,7 @@ void DisplayServerX11::_xim_preedit_draw_callback(::XIM xim, ::XPointer client_d ds->im_selection = Point2i(); } - OS_Unix::get_singleton()->get_main_loop()->call_deferred(SNAME("notification"), MainLoop::NOTIFICATION_OS_IME_UPDATE); + callable_mp((Object *)OS_Unix::get_singleton()->get_main_loop(), &Object::notification).call_deferred(MainLoop::NOTIFICATION_OS_IME_UPDATE, false); } } diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index 3ecc4dca3f..3b362e5c22 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -492,6 +492,8 @@ public: virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override; virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual WindowID get_focused_window() const override; + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override; virtual bool can_any_window_draw() const override; diff --git a/platform/linuxbsd/x11/key_mapping_x11.cpp b/platform/linuxbsd/x11/key_mapping_x11.cpp index 0f709872cb..c0e6b91d57 100644 --- a/platform/linuxbsd/x11/key_mapping_x11.cpp +++ b/platform/linuxbsd/x11/key_mapping_x11.cpp @@ -88,7 +88,6 @@ void KeyMappingX11::initialize() { xkeysym_map[XK_KP_Equal] = Key::EQUAL; xkeysym_map[XK_KP_Separator] = Key::COMMA; xkeysym_map[XK_KP_Decimal] = Key::KP_PERIOD; - xkeysym_map[XK_KP_Delete] = Key::KP_PERIOD; xkeysym_map[XK_KP_Multiply] = Key::KP_MULTIPLY; xkeysym_map[XK_KP_Divide] = Key::KP_DIVIDE; xkeysym_map[XK_KP_Subtract] = Key::KP_SUBTRACT; @@ -105,6 +104,7 @@ void KeyMappingX11::initialize() { xkeysym_map[XK_KP_9] = Key::KP_9; // Same keys but with numlock off. xkeysym_map[XK_KP_Insert] = Key::INSERT; + xkeysym_map[XK_KP_Delete] = Key::KEY_DELETE; xkeysym_map[XK_KP_End] = Key::END; xkeysym_map[XK_KP_Down] = Key::DOWN; xkeysym_map[XK_KP_Page_Down] = Key::PAGEDOWN; diff --git a/platform/macos/detect.py b/platform/macos/detect.py index b41d2141fb..bc14d233bb 100644 --- a/platform/macos/detect.py +++ b/platform/macos/detect.py @@ -67,21 +67,30 @@ def get_mvk_sdk_path(): if not os.path.exists(dirname): return "" - ver_file = "0.0.0.0" - ver_num = ver_parse(ver_file) - + ver_num = ver_parse("0.0.0.0") files = os.listdir(dirname) + lib_name_out = dirname for file in files: if os.path.isdir(os.path.join(dirname, file)): ver_comp = ver_parse(file) - lib_name = os.path.join( - os.path.join(dirname, file), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a" - ) - if os.path.isfile(lib_name) and ver_comp > ver_num: - ver_num = ver_comp - ver_file = file + if ver_comp > ver_num: + # Try new SDK location. + lib_name = os.path.join( + os.path.join(dirname, file), "macOS/lib/MoltenVK.xcframework/macos-arm64_x86_64/" + ) + if os.path.isfile(os.path.join(lib_name, "libMoltenVK.a")): + ver_num = ver_comp + lib_name_out = lib_name + else: + # Try old SDK location. + lib_name = os.path.join( + os.path.join(dirname, file), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/" + ) + if os.path.isfile(os.path.join(lib_name, "libMoltenVK.a")): + ver_num = ver_comp + lib_name_out = lib_name - return os.path.join(os.path.join(dirname, ver_file), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/") + return lib_name_out def configure(env: "Environment"): @@ -260,7 +269,7 @@ def configure(env: "Environment"): env.Append(LINKFLAGS=["-rpath", "@executable_path/../Frameworks", "-rpath", "@executable_path"]) if env["vulkan"]: - env.Append(CPPDEFINES=["VULKAN_ENABLED"]) + env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"]) env.Append(LINKFLAGS=["-framework", "Metal", "-framework", "IOSurface"]) if not env["use_volk"]: env.Append(LINKFLAGS=["-lMoltenVK"]) @@ -272,6 +281,12 @@ def configure(env: "Environment"): mvk_list.insert( 0, os.path.join( + os.path.expanduser(env["vulkan_sdk_path"]), "macOS/lib/MoltenVK.xcframework/macos-arm64_x86_64/" + ), + ) + mvk_list.insert( + 0, + os.path.join( os.path.expanduser(env["vulkan_sdk_path"]), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/" ), ) diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index f8fd0f93ef..cc343a6d64 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -428,6 +428,8 @@ public: virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override; virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual WindowID get_focused_window() const override; + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override; virtual bool can_any_window_draw() const override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index bd92b7d472..378688f78a 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -3723,6 +3723,10 @@ bool DisplayServerMacOS::window_is_focused(WindowID p_window) const { return wd.focused; } +DisplayServerMacOS::WindowID DisplayServerMacOS::get_focused_window() const { + return last_focused_window; +} + bool DisplayServerMacOS::window_can_draw(WindowID p_window) const { return windows[p_window].is_visible; } diff --git a/platform/macos/doc_classes/EditorExportPlatformMacOS.xml b/platform/macos/doc_classes/EditorExportPlatformMacOS.xml index 85fefe65c0..506b0dffb8 100644 --- a/platform/macos/doc_classes/EditorExportPlatformMacOS.xml +++ b/platform/macos/doc_classes/EditorExportPlatformMacOS.xml @@ -10,6 +10,13 @@ <link title="Running Godot apps on macOS">$DOCS_URL/tutorials//export/running_on_macos.html</link> </tutorials> <members> + <member name="application/additional_plist_content" type="String" setter="" getter=""> + Additional data added to the root [code]<dict>[/code] section of the [url=https://developer.apple.com/documentation/bundleresources/information_property_list]Info.plist[/url] file. The value should be an XML section with pairs of key-value elements, e.g.: + [codeblock] + <key>key_name</key> + <string>value</string> + [/codeblock] + </member> <member name="application/app_category" type="String" setter="" getter=""> Application category for the App Store. </member> diff --git a/platform/macos/export/codesign.cpp b/platform/macos/export/codesign.cpp index 2b8898e6a1..082c0abea7 100644 --- a/platform/macos/export/codesign.cpp +++ b/platform/macos/export/codesign.cpp @@ -32,8 +32,8 @@ #include "lipo.h" #include "macho.h" -#include "plist.h" +#include "core/io/plist.h" #include "core/os/os.h" #include "editor/editor_paths.h" #include "editor/editor_settings.h" diff --git a/platform/macos/export/codesign.h b/platform/macos/export/codesign.h index 3e61751a96..49d53b376e 100644 --- a/platform/macos/export/codesign.h +++ b/platform/macos/export/codesign.h @@ -41,11 +41,10 @@ // - Requirements code generator is not implemented (only hard-coded requirements for the ad-hoc signing is supported). // - RFC5652/CMS blob generation is not implemented, supports ad-hoc signing only. -#include "plist.h" - #include "core/crypto/crypto_core.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" +#include "core/io/plist.h" #include "core/object/ref_counted.h" #include "modules/modules_enabled.gen.h" // For regex. diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp index 6f9db1427b..7ed78db6f8 100644 --- a/platform/macos/export/export_plugin.cpp +++ b/platform/macos/export/export_plugin.cpp @@ -37,13 +37,14 @@ #include "run_icon_svg.gen.h" #include "core/io/image_loader.h" +#include "core/io/plist.h" #include "core/string/translation.h" #include "drivers/png/png_driver_common.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/import/resource_importer_texture_settings.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/image_texture.h" #include "modules/modules_enabled.gen.h" // For svg and regex. @@ -388,6 +389,8 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_angle", PROPERTY_HINT_ENUM, "Auto,Yes,No"), 0, true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/additional_plist_content", PROPERTY_HINT_MULTILINE_TEXT), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/platform_build"), "14C18")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/sdk_version"), "13.1")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/sdk_build"), "22C55")); @@ -672,6 +675,8 @@ void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_pres strnew += lines[i].replace("$min_version", p_preset->get("application/min_macos_version")) + "\n"; } else if (lines[i].find("$highres") != -1) { strnew += lines[i].replace("$highres", p_preset->get("display/high_res") ? "\t<true/>" : "\t<false/>") + "\n"; + } else if (lines[i].find("$additional_plist_content") != -1) { + strnew += lines[i].replace("$additional_plist_content", p_preset->get("application/additional_plist_content")) + "\n"; } else if (lines[i].find("$platfbuild") != -1) { strnew += lines[i].replace("$platfbuild", p_preset->get("xcode/platform_build")) + "\n"; } else if (lines[i].find("$sdkver") != -1) { @@ -2051,13 +2056,17 @@ bool EditorExportPlatformMacOS::has_valid_export_configuration(const Ref<EditorE String architecture = p_preset->get("binary_format/architecture"); if (architecture == "universal" || architecture == "x86_64") { if (!ResourceImporterTextureSettings::should_import_s3tc_bptc()) { + err += TTR("Cannot export for universal or x86_64 if S3TC BPTC texture format is disabled. Enable it in the Project Settings (Rendering > Textures > VRAM Compression > Import S3TC BPTC).") + "\n"; valid = false; } - } else if (architecture == "arm64") { + } + if (architecture == "universal" || architecture == "arm64") { if (!ResourceImporterTextureSettings::should_import_etc2_astc()) { + err += TTR("Cannot export for universal or arm64 if ETC2 ASTC texture format is disabled. Enable it in the Project Settings (Rendering > Textures > VRAM Compression > Import ETC2 ASTC).") + "\n"; valid = false; } - } else { + } + if (architecture != "universal" && architecture != "x86_64" && architecture != "arm64") { ERR_PRINT("Invalid architecture"); } @@ -2091,6 +2100,26 @@ bool EditorExportPlatformMacOS::has_valid_project_configuration(const Ref<Editor }; } + const String &additional_plist_content = p_preset->get("application/additional_plist_content"); + if (!additional_plist_content.is_empty()) { + const String &plist = vformat("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" + "<plist version=\"1.0\">" + "<dict>\n" + "%s\n" + "</dict>\n" + "</plist>\n", + additional_plist_content); + + String plist_err; + Ref<PList> plist_parser; + plist_parser.instantiate(); + if (!plist_parser->load_string(plist, plist_err)) { + err += TTR("Invalid additional PList content: ") + plist_err + "\n"; + valid = false; + } + } + List<ExportOption> options; get_export_options(&options); for (const EditorExportPlatform::ExportOption &E : options) { diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm index 29dff683d5..b8496d72fb 100644 --- a/platform/macos/os_macos.mm +++ b/platform/macos/os_macos.mm @@ -230,6 +230,8 @@ Error OS_MacOS::open_dynamic_library(const String p_path, void *&p_library_handl path = get_framework_executable(get_executable_path().get_base_dir().path_join("../Frameworks").path_join(p_path.get_file())); } + ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND); + p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW); ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror())); diff --git a/platform/web/.eslintrc.html.js b/platform/web/.eslintrc.html.js index 5cb8de360a..8c9a3d83da 100644 --- a/platform/web/.eslintrc.html.js +++ b/platform/web/.eslintrc.html.js @@ -15,5 +15,7 @@ module.exports = { "Godot": true, "Engine": true, "$GODOT_CONFIG": true, + "$GODOT_THREADS_ENABLED": true, + "___GODOT_THREADS_ENABLED___": true, }, }; diff --git a/platform/web/SCsub b/platform/web/SCsub index 1af0642554..3e0cc9ac4a 100644 --- a/platform/web/SCsub +++ b/platform/web/SCsub @@ -13,7 +13,7 @@ if "serve" in COMMAND_LINE_TARGETS or "run" in COMMAND_LINE_TARGETS: except Exception: print("GODOT_WEB_TEST_PORT must be a valid integer") sys.exit(255) - serve(env.Dir("#bin/.web_zip").abspath, port, "run" in COMMAND_LINE_TARGETS) + serve(env.Dir(env.GetTemplateZipPath()).abspath, port, "run" in COMMAND_LINE_TARGETS) sys.exit(0) web_files = [ @@ -95,7 +95,7 @@ engine = [ "js/engine/engine.js", ] externs = [env.File("#platform/web/js/engine/engine.externs.js")] -js_engine = env.CreateEngineFile("#bin/godot${PROGSUFFIX}.engine.js", engine, externs) +js_engine = env.CreateEngineFile("#bin/godot${PROGSUFFIX}.engine.js", engine, externs, env["threads"]) env.Depends(js_engine, externs) wrap_list = [ diff --git a/platform/web/audio_driver_web.cpp b/platform/web/audio_driver_web.cpp index 1298d28ebf..ec3c22bf7c 100644 --- a/platform/web/audio_driver_web.cpp +++ b/platform/web/audio_driver_web.cpp @@ -30,6 +30,8 @@ #include "audio_driver_web.h" +#include "godot_audio.h" + #include "core/config/project_settings.h" #include <emscripten.h> @@ -184,6 +186,8 @@ Error AudioDriverWeb::input_stop() { return OK; } +#ifdef THREADS_ENABLED + /// AudioWorkletNode implementation (threads) void AudioDriverWorklet::_audio_thread_func(void *p_data) { AudioDriverWorklet *driver = static_cast<AudioDriverWorklet *>(p_data); @@ -245,3 +249,51 @@ void AudioDriverWorklet::finish_driver() { quit = true; // Ask thread to quit. thread.wait_to_finish(); } + +#else // No threads. + +/// AudioWorkletNode implementation (no threads) +AudioDriverWorklet *AudioDriverWorklet::singleton = nullptr; + +Error AudioDriverWorklet::create(int &p_buffer_size, int p_channels) { + if (!godot_audio_has_worklet()) { + return ERR_UNAVAILABLE; + } + return (Error)godot_audio_worklet_create(p_channels); +} + +void AudioDriverWorklet::start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) { + _audio_driver_process(); + godot_audio_worklet_start_no_threads(p_out_buf, p_out_buf_size, &_process_callback, p_in_buf, p_in_buf_size, &_capture_callback); +} + +void AudioDriverWorklet::_process_callback(int p_pos, int p_samples) { + AudioDriverWorklet *driver = AudioDriverWorklet::get_singleton(); + driver->_audio_driver_process(p_pos, p_samples); +} + +void AudioDriverWorklet::_capture_callback(int p_pos, int p_samples) { + AudioDriverWorklet *driver = AudioDriverWorklet::get_singleton(); + driver->_audio_driver_capture(p_pos, p_samples); +} + +/// ScriptProcessorNode implementation +AudioDriverScriptProcessor *AudioDriverScriptProcessor::singleton = nullptr; + +void AudioDriverScriptProcessor::_process_callback() { + AudioDriverScriptProcessor::get_singleton()->_audio_driver_capture(); + AudioDriverScriptProcessor::get_singleton()->_audio_driver_process(); +} + +Error AudioDriverScriptProcessor::create(int &p_buffer_samples, int p_channels) { + if (!godot_audio_has_script_processor()) { + return ERR_UNAVAILABLE; + } + return (Error)godot_audio_script_create(&p_buffer_samples, p_channels); +} + +void AudioDriverScriptProcessor::start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) { + godot_audio_script_start(p_in_buf, p_in_buf_size, p_out_buf, p_out_buf_size, &_process_callback); +} + +#endif // THREADS_ENABLED diff --git a/platform/web/audio_driver_web.h b/platform/web/audio_driver_web.h index 12a61746c3..df88d0a94c 100644 --- a/platform/web/audio_driver_web.h +++ b/platform/web/audio_driver_web.h @@ -90,6 +90,7 @@ public: AudioDriverWeb() {} }; +#ifdef THREADS_ENABLED class AudioDriverWorklet : public AudioDriverWeb { private: enum { @@ -120,4 +121,54 @@ public: virtual void unlock() override; }; +#else + +class AudioDriverWorklet : public AudioDriverWeb { +private: + static void _process_callback(int p_pos, int p_samples); + static void _capture_callback(int p_pos, int p_samples); + + static AudioDriverWorklet *singleton; + +protected: + virtual Error create(int &p_buffer_size, int p_output_channels) override; + virtual void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) override; + +public: + virtual const char *get_name() const override { + return "AudioWorklet"; + } + + virtual void lock() override {} + virtual void unlock() override {} + + static AudioDriverWorklet *get_singleton() { return singleton; } + + AudioDriverWorklet() { singleton = this; } +}; + +class AudioDriverScriptProcessor : public AudioDriverWeb { +private: + static void _process_callback(); + + static AudioDriverScriptProcessor *singleton; + +protected: + virtual Error create(int &p_buffer_size, int p_output_channels) override; + virtual void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) override; + virtual void finish_driver() override; + +public: + virtual const char *get_name() const override { return "ScriptProcessor"; } + + virtual void lock() override {} + virtual void unlock() override {} + + static AudioDriverScriptProcessor *get_singleton() { return singleton; } + + AudioDriverScriptProcessor() { singleton = this; } +}; + +#endif // THREADS_ENABLED + #endif // AUDIO_DRIVER_WEB_H diff --git a/platform/web/detect.py b/platform/web/detect.py index 579eaaff03..bce03eb79e 100644 --- a/platform/web/detect.py +++ b/platform/web/detect.py @@ -8,6 +8,7 @@ from emscripten_helpers import ( add_js_pre, add_js_externs, create_template_zip, + get_template_zip_path, ) from methods import get_compiler_version from SCons.Util import WhereIs @@ -30,6 +31,9 @@ def get_opts(): return [ ("initial_memory", "Initial WASM memory (in MiB)", 32), + # Matches default values from before Emscripten 3.1.27. New defaults are too low for Godot. + ("stack_size", "WASM stack size (in KiB)", 5120), + ("default_pthread_stack_size", "WASM pthread default stack size (in KiB)", 2048), BoolVariable("use_assertions", "Use Emscripten runtime assertions", False), BoolVariable("use_ubsan", "Use Emscripten undefined behavior sanitizer (UBSAN)", False), BoolVariable("use_asan", "Use Emscripten address sanitizer (ASAN)", False), @@ -158,6 +162,9 @@ def configure(env: "Environment"): # Add method that joins/compiles our Engine files. env.AddMethod(create_engine_file, "CreateEngineFile") + # Add method for getting the final zip path + env.AddMethod(get_template_zip_path, "GetTemplateZipPath") + # Add method for creating the final zip file env.AddMethod(create_template_zip, "CreateTemplateZip") @@ -193,11 +200,6 @@ def configure(env: "Environment"): env.Prepend(CPPPATH=["#platform/web"]) env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"]) - if cc_semver >= (3, 1, 25): - env.Append(LINKFLAGS=["-s", "STACK_SIZE=5MB"]) - else: - env.Append(LINKFLAGS=["-s", "TOTAL_STACK=5MB"]) - if env["opengl3"]: env.AppendUnique(CPPDEFINES=["GLES3_ENABLED"]) # This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1. @@ -208,13 +210,20 @@ def configure(env: "Environment"): if env["javascript_eval"]: env.Append(CPPDEFINES=["JAVASCRIPT_EVAL_ENABLED"]) - # Thread support (via SharedArrayBuffer). - env.Append(CPPDEFINES=["PTHREAD_NO_RENAME"]) - env.Append(CCFLAGS=["-s", "USE_PTHREADS=1"]) - env.Append(LINKFLAGS=["-s", "USE_PTHREADS=1"]) - env.Append(LINKFLAGS=["-s", "DEFAULT_PTHREAD_STACK_SIZE=2MB"]) - env.Append(LINKFLAGS=["-s", "PTHREAD_POOL_SIZE=8"]) - env.Append(LINKFLAGS=["-s", "WASM_MEM_MAX=2048MB"]) + stack_size_opt = "STACK_SIZE" if cc_semver >= (3, 1, 25) else "TOTAL_STACK" + env.Append(LINKFLAGS=["-s", "%s=%sKB" % (stack_size_opt, env["stack_size"])]) + + if env["threads"]: + # Thread support (via SharedArrayBuffer). + env.Append(CPPDEFINES=["PTHREAD_NO_RENAME"]) + env.Append(CCFLAGS=["-s", "USE_PTHREADS=1"]) + env.Append(LINKFLAGS=["-s", "USE_PTHREADS=1"]) + env.Append(LINKFLAGS=["-s", "DEFAULT_PTHREAD_STACK_SIZE=%sKB" % env["default_pthread_stack_size"]]) + env.Append(LINKFLAGS=["-s", "PTHREAD_POOL_SIZE=8"]) + env.Append(LINKFLAGS=["-s", "WASM_MEM_MAX=2048MB"]) + elif env["proxy_to_pthread"]: + print('"threads=no" support requires "proxy_to_pthread=no", disabling proxy to pthread.') + env["proxy_to_pthread"] = False if env["lto"] != "none": # Workaround https://github.com/emscripten-core/emscripten/issues/19781. @@ -223,7 +232,7 @@ def configure(env: "Environment"): if env["dlink_enabled"]: if env["proxy_to_pthread"]: - print("GDExtension support requires proxy_to_pthread=no, disabling") + print("GDExtension support requires proxy_to_pthread=no, disabling proxy to pthread.") env["proxy_to_pthread"] = False if cc_semver < (3, 1, 14): diff --git a/platform/web/doc_classes/EditorExportPlatformWeb.xml b/platform/web/doc_classes/EditorExportPlatformWeb.xml index c4c4fd870b..f07f265b0d 100644 --- a/platform/web/doc_classes/EditorExportPlatformWeb.xml +++ b/platform/web/doc_classes/EditorExportPlatformWeb.xml @@ -47,6 +47,10 @@ </member> <member name="variant/extensions_support" type="bool" setter="" getter=""> </member> + <member name="variant/thread_support" type="bool" setter="" getter=""> + If enabled, the exported game will support threads. It requires [url=https://web.dev/articles/coop-coep]a "cross-origin isolated" website[/url], which can be difficult to setup and brings some limitations (e.g. not being able to communicate with third-party websites). + If disabled, the exported game will not support threads. As a result, it is more prone to performance and audio issues, but will only require to be run on a HTTPS website. + </member> <member name="vram_texture_compression/for_desktop" type="bool" setter="" getter=""> </member> <member name="vram_texture_compression/for_mobile" type="bool" setter="" getter=""> diff --git a/platform/web/emscripten_helpers.py b/platform/web/emscripten_helpers.py index ec33397842..3ba133c9a1 100644 --- a/platform/web/emscripten_helpers.py +++ b/platform/web/emscripten_helpers.py @@ -4,7 +4,12 @@ from SCons.Util import WhereIs def run_closure_compiler(target, source, env, for_signature): - closure_bin = os.path.join(os.path.dirname(WhereIs("emcc")), "node_modules", ".bin", "google-closure-compiler") + closure_bin = os.path.join( + os.path.dirname(WhereIs("emcc")), + "node_modules", + ".bin", + "google-closure-compiler", + ) cmd = [WhereIs("node"), closure_bin] cmd.extend(["--compilation_level", "ADVANCED_OPTIMIZATIONS"]) for f in env["JSEXTERNS"]: @@ -31,27 +36,29 @@ def get_build_version(): return v -def create_engine_file(env, target, source, externs): +def create_engine_file(env, target, source, externs, threads_enabled): if env["use_closure_compiler"]: return env.BuildJS(target, source, JSEXTERNS=externs) - return env.Textfile(target, [env.File(s) for s in source]) + subst_dict = {"___GODOT_THREADS_ENABLED": "true" if threads_enabled else "false"} + return env.Substfile(target=target, source=[env.File(s) for s in source], SUBST_DICT=subst_dict) def create_template_zip(env, js, wasm, worker, side): binary_name = "godot.editor" if env.editor_build else "godot" - zip_dir = env.Dir("#bin/.web_zip") + zip_dir = env.Dir(env.GetTemplateZipPath()) in_files = [ js, wasm, - worker, "#platform/web/js/libs/audio.worklet.js", ] out_files = [ zip_dir.File(binary_name + ".js"), zip_dir.File(binary_name + ".wasm"), - zip_dir.File(binary_name + ".worker.js"), zip_dir.File(binary_name + ".audio.worklet.js"), ] + if env["threads"]: + in_files.append(worker) + out_files.append(zip_dir.File(binary_name + ".worker.js")) # Dynamic linking (extensions) specific. if env["dlink_enabled"]: in_files.append(side) # Side wasm (contains the actual Godot code). @@ -65,18 +72,20 @@ def create_template_zip(env, js, wasm, worker, side): "godot.editor.html", "offline.html", "godot.editor.js", - "godot.editor.worker.js", "godot.editor.audio.worklet.js", "logo.svg", "favicon.png", ] + if env["threads"]: + cache.append("godot.editor.worker.js") opt_cache = ["godot.editor.wasm"] subst_dict = { - "@GODOT_VERSION@": get_build_version(), - "@GODOT_NAME@": "GodotEngine", - "@GODOT_CACHE@": json.dumps(cache), - "@GODOT_OPT_CACHE@": json.dumps(opt_cache), - "@GODOT_OFFLINE_PAGE@": "offline.html", + "___GODOT_VERSION___": get_build_version(), + "___GODOT_NAME___": "GodotEngine", + "___GODOT_CACHE___": json.dumps(cache), + "___GODOT_OPT_CACHE___": json.dumps(opt_cache), + "___GODOT_OFFLINE_PAGE___": "offline.html", + "___GODOT_THREADS_ENABLED___": "true" if env["threads"] else "false", } html = env.Substfile(target="#bin/godot${PROGSUFFIX}.html", source=html, SUBST_DICT=subst_dict) in_files.append(html) @@ -88,7 +97,9 @@ def create_template_zip(env, js, wasm, worker, side): out_files.append(zip_dir.File("favicon.png")) # PWA service_worker = env.Substfile( - target="#bin/godot${PROGSUFFIX}.service.worker.js", source=service_worker, SUBST_DICT=subst_dict + target="#bin/godot${PROGSUFFIX}.service.worker.js", + source=service_worker, + SUBST_DICT=subst_dict, ) in_files.append(service_worker) out_files.append(zip_dir.File("service.worker.js")) @@ -115,6 +126,10 @@ def create_template_zip(env, js, wasm, worker, side): ) +def get_template_zip_path(env): + return "#bin/.web_zip" + + def add_js_libraries(env, libraries): env.Append(JS_LIBS=env.File(libraries)) diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp index a70812cf5b..d7e72612b4 100644 --- a/platform/web/export/export_plugin.cpp +++ b/platform/web/export/export_plugin.cpp @@ -34,11 +34,11 @@ #include "run_icon_svg.gen.h" #include "core/config/project_settings.h" -#include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/export/editor_export.h" #include "editor/import/resource_importer_texture_settings.h" +#include "editor/themes/editor_scale.h" #include "scene/resources/image_texture.h" #include "modules/modules_enabled.gen.h" // For mono and svg. @@ -112,7 +112,7 @@ Error EditorExportPlatformWeb::_write_or_error(const uint8_t *p_content, int p_s return OK; } -void EditorExportPlatformWeb::_replace_strings(HashMap<String, String> p_replaces, Vector<uint8_t> &r_template) { +void EditorExportPlatformWeb::_replace_strings(const HashMap<String, String> &p_replaces, Vector<uint8_t> &r_template) { String str_template = String::utf8(reinterpret_cast<const char *>(r_template.ptr()), r_template.size()); String out; Vector<String> lines = str_template.split("\n"); @@ -169,6 +169,13 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito replaces["$GODOT_PROJECT_NAME"] = GLOBAL_GET("application/config/name"); replaces["$GODOT_HEAD_INCLUDE"] = head_include + custom_head_include; replaces["$GODOT_CONFIG"] = str_config; + + if (p_preset->get("variant/thread_support")) { + replaces["$GODOT_THREADS_ENABLED"] = "true"; + } else { + replaces["$GODOT_THREADS_ENABLED"] = "false"; + } + _replace_strings(replaces, p_html); } @@ -216,9 +223,9 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_prese const String name = p_path.get_file().get_basename(); bool extensions = (bool)p_preset->get("variant/extensions_support"); HashMap<String, String> replaces; - replaces["@GODOT_VERSION@"] = String::num_int64(OS::get_singleton()->get_unix_time()) + "|" + String::num_int64(OS::get_singleton()->get_ticks_usec()); - replaces["@GODOT_NAME@"] = proj_name.substr(0, 16); - replaces["@GODOT_OFFLINE_PAGE@"] = name + ".offline.html"; + replaces["___GODOT_VERSION___"] = String::num_int64(OS::get_singleton()->get_unix_time()) + "|" + String::num_int64(OS::get_singleton()->get_ticks_usec()); + replaces["___GODOT_NAME___"] = proj_name.substr(0, 16); + replaces["___GODOT_OFFLINE_PAGE___"] = name + ".offline.html"; // Files cached during worker install. Array cache_files; @@ -231,7 +238,7 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_prese } cache_files.push_back(name + ".worker.js"); cache_files.push_back(name + ".audio.worklet.js"); - replaces["@GODOT_CACHE@"] = Variant(cache_files).to_json_string(); + replaces["___GODOT_CACHE___"] = Variant(cache_files).to_json_string(); // Heavy files that are cached on demand. Array opt_cache_files; @@ -243,7 +250,7 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_prese opt_cache_files.push_back(p_shared_objects[i].path.get_file()); } } - replaces["@GODOT_OPT_CACHE@"] = Variant(opt_cache_files).to_json_string(); + replaces["___GODOT_OPT_CACHE___"] = Variant(opt_cache_files).to_json_string(); const String sw_path = dir.path_join(name + ".service.worker.js"); Vector<uint8_t> sw; @@ -335,6 +342,7 @@ void EditorExportPlatformWeb::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "variant/extensions_support"), false)); // Export type. + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "variant/thread_support"), true)); // Thread support (i.e. run with or without COEP/COOP headers). r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_desktop"), true)); // S3TC r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_mobile"), false)); // ETC or ETC2, depending on renderer @@ -377,10 +385,11 @@ bool EditorExportPlatformWeb::has_valid_export_configuration(const Ref<EditorExp String err; bool valid = false; bool extensions = (bool)p_preset->get("variant/extensions_support"); + bool thread_support = (bool)p_preset->get("variant/thread_support"); // Look for export templates (first official, and if defined custom templates). - bool dvalid = exists_export_template(_get_template_name(extensions, true), &err); - bool rvalid = exists_export_template(_get_template_name(extensions, false), &err); + bool dvalid = exists_export_template(_get_template_name(extensions, thread_support, true), &err); + bool rvalid = exists_export_template(_get_template_name(extensions, thread_support, false), &err); if (p_preset->get("custom_template/debug") != "") { dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); @@ -454,7 +463,8 @@ Error EditorExportPlatformWeb::export_project(const Ref<EditorExportPreset> &p_p template_path = template_path.strip_edges(); if (template_path.is_empty()) { bool extensions = (bool)p_preset->get("variant/extensions_support"); - template_path = find_export_template(_get_template_name(extensions, p_debug)); + bool thread_support = (bool)p_preset->get("variant/thread_support"); + template_path = find_export_template(_get_template_name(extensions, thread_support, p_debug)); } if (!template_path.is_empty() && !FileAccess::exists(template_path)) { diff --git a/platform/web/export/export_plugin.h b/platform/web/export/export_plugin.h index 887000ac45..98e3fe729e 100644 --- a/platform/web/export/export_plugin.h +++ b/platform/web/export/export_plugin.h @@ -56,11 +56,14 @@ class EditorExportPlatformWeb : public EditorExportPlatform { Mutex server_lock; Thread server_thread; - String _get_template_name(bool p_extension, bool p_debug) const { + String _get_template_name(bool p_extension, bool p_thread_support, bool p_debug) const { String name = "web"; if (p_extension) { name += "_dlink"; } + if (!p_thread_support) { + name += "_nothreads"; + } if (p_debug) { name += "_debug.zip"; } else { @@ -90,7 +93,7 @@ class EditorExportPlatformWeb : public EditorExportPlatform { } Error _extract_template(const String &p_template, const String &p_dir, const String &p_name, bool pwa); - void _replace_strings(HashMap<String, String> p_replaces, Vector<uint8_t> &r_template); + void _replace_strings(const HashMap<String, String> &p_replaces, Vector<uint8_t> &r_template); void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags, const Vector<SharedObject> p_shared_objects, const Dictionary &p_file_sizes); Error _add_manifest_icon(const String &p_path, const String &p_icon, int p_size, Array &r_arr); Error _build_pwa(const Ref<EditorExportPreset> &p_preset, const String p_path, const Vector<SharedObject> &p_shared_objects); diff --git a/platform/web/js/engine/features.js b/platform/web/js/engine/features.js index b7c6c9d445..81bc82f3c6 100644 --- a/platform/web/js/engine/features.js +++ b/platform/web/js/engine/features.js @@ -72,8 +72,14 @@ const Features = { // eslint-disable-line no-unused-vars * * @returns {Array<string>} A list of human-readable missing features. * @function Engine.getMissingFeatures + * @typedef {{ threads: boolean }} SupportedFeatures + * @param {SupportedFeatures} supportedFeatures */ - getMissingFeatures: function () { + getMissingFeatures: function (supportedFeatures = {}) { + const { + threads: supportsThreads = true, + } = supportedFeatures; + const missing = []; if (!Features.isWebGLAvailable(2)) { missing.push('WebGL2 - Check web browser configuration and hardware support'); @@ -84,12 +90,16 @@ const Features = { // eslint-disable-line no-unused-vars if (!Features.isSecureContext()) { missing.push('Secure Context - Check web server configuration (use HTTPS)'); } - if (!Features.isCrossOriginIsolated()) { - missing.push('Cross Origin Isolation - Check web server configuration (send correct headers)'); - } - if (!Features.isSharedArrayBufferAvailable()) { - missing.push('SharedArrayBuffer - Check web server configuration (send correct headers)'); + + if (supportsThreads) { + if (!Features.isCrossOriginIsolated()) { + missing.push('Cross-Origin Isolation - Check that the web server configuration sends the correct headers.'); + } + if (!Features.isSharedArrayBufferAvailable()) { + missing.push('SharedArrayBuffer - Check that the web server configuration sends the correct headers.'); + } } + // Audio is normally optional since we have a dummy fallback. return missing; }, diff --git a/platform/web/js/libs/audio.worklet.js b/platform/web/js/libs/audio.worklet.js index 89b581b3d6..3b94cab85c 100644 --- a/platform/web/js/libs/audio.worklet.js +++ b/platform/web/js/libs/audio.worklet.js @@ -167,7 +167,7 @@ class GodotProcessor extends AudioWorkletProcessor { GodotProcessor.write_input(this.input_buffer, input); this.input.write(this.input_buffer); } else { - this.port.postMessage('Input buffer is full! Skipping input frame.'); + // this.port.postMessage('Input buffer is full! Skipping input frame.'); // Uncomment this line to debug input buffer. } } const process_output = GodotProcessor.array_has_data(outputs); @@ -184,7 +184,7 @@ class GodotProcessor extends AudioWorkletProcessor { this.port.postMessage({ 'cmd': 'read', 'data': chunk }); } } else { - this.port.postMessage('Output buffer has not enough frames! Skipping output frame.'); + // this.port.postMessage('Output buffer has not enough frames! Skipping output frame.'); // Uncomment this line to debug output buffer. } } this.process_notify(); diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 0549e408a7..1cfbc33ef8 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -3,6 +3,7 @@ Import("env") import os +from pathlib import Path from platform_methods import run_in_subprocess import platform_windows_builders @@ -25,6 +26,19 @@ common_win_wrap = [ "console_wrapper_windows.cpp", ] + +def arrange_program_clean(prog): + """ + Given an SCons program, arrange for output files SCons doesn't know about + to be cleaned when SCons is called with --clean + """ + extensions_to_clean = [".ilk", ".exp", ".pdb", ".lib"] + for program in prog: + executable_stem = Path(program.name).stem + extra_files_to_clean = [f"#bin/{executable_stem}{extension}" for extension in extensions_to_clean] + Clean(prog, extra_files_to_clean) + + res_file = "godot_res.rc" res_target = "godot_res" + env["OBJSUFFIX"] res_obj = env.RES(res_target, res_file) @@ -32,6 +46,7 @@ res_obj = env.RES(res_target, res_file) sources = common_win + res_obj prog = env.add_program("#bin/godot", sources, PROGSUFFIX=env["PROGSUFFIX"]) +arrange_program_clean(prog) # Build console wrapper app. if env["windows_subsystem"] == "gui": @@ -48,6 +63,7 @@ if env["windows_subsystem"] == "gui": env_wrap.Append(LIBS=["version"]) prog_wrap = env_wrap.add_program("#bin/godot", common_win_wrap + res_wrap_obj, PROGSUFFIX=env["PROGSUFFIX_WRAP"]) + arrange_program_clean(prog_wrap) env_wrap.Depends(prog_wrap, prog) # Microsoft Visual Studio Project Generation diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 801b32140a..79698f5bd7 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -436,16 +436,12 @@ def configure_msvc(env, vcvars_msvc_config): LIBS += ["psapi", "dbghelp"] if env["vulkan"]: - env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED"]) + env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"]) if not env["use_volk"]: LIBS += ["vulkan"] if env["d3d12"]: - if env["dxc_path"] == "": - print("The Direct3D 12 rendering driver requires dxc_path to be set.") - sys.exit(255) - - env.AppendUnique(CPPDEFINES=["D3D12_ENABLED"]) + env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"]) LIBS += ["d3d12", "dxgi", "dxguid"] LIBS += ["version"] # Mesa dependency. @@ -657,12 +653,12 @@ def configure_mingw(env): env.Append(LIBS=["psapi", "dbghelp"]) if env["vulkan"]: - env.Append(CPPDEFINES=["VULKAN_ENABLED"]) + env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"]) if not env["use_volk"]: env.Append(LIBS=["vulkan"]) if env["d3d12"]: - env.AppendUnique(CPPDEFINES=["D3D12_ENABLED"]) + env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"]) env.Append(LIBS=["d3d12", "dxgi", "dxguid"]) arch_subdir = "arm64" if env["arch"] == "arm64" else "x64" diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 2bec804c7c..b56954ae81 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -687,6 +687,8 @@ typedef struct { } EnumRectData; typedef struct { + Vector<DISPLAYCONFIG_PATH_INFO> paths; + Vector<DISPLAYCONFIG_MODE_INFO> modes; int count; int screen; float rate; @@ -738,12 +740,30 @@ static BOOL CALLBACK _MonitorEnumProcRefreshRate(HMONITOR hMonitor, HDC hdcMonit minfo.cbSize = sizeof(minfo); GetMonitorInfoW(hMonitor, &minfo); - DEVMODEW dm; - memset(&dm, 0, sizeof(dm)); - dm.dmSize = sizeof(dm); - EnumDisplaySettingsW(minfo.szDevice, ENUM_CURRENT_SETTINGS, &dm); + bool found = false; + for (const DISPLAYCONFIG_PATH_INFO &path : data->paths) { + DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name; + memset(&source_name, 0, sizeof(source_name)); + source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + source_name.header.size = sizeof(source_name); + source_name.header.adapterId = path.sourceInfo.adapterId; + source_name.header.id = path.sourceInfo.id; + if (DisplayConfigGetDeviceInfo(&source_name.header) == ERROR_SUCCESS) { + if (wcscmp(minfo.szDevice, source_name.viewGdiDeviceName) == 0 && path.targetInfo.refreshRate.Numerator != 0 && path.targetInfo.refreshRate.Denominator != 0) { + data->rate = (double)path.targetInfo.refreshRate.Numerator / (double)path.targetInfo.refreshRate.Denominator; + found = true; + break; + } + } + } + if (!found) { + DEVMODEW dm; + memset(&dm, 0, sizeof(dm)); + dm.dmSize = sizeof(dm); + EnumDisplaySettingsW(minfo.szDevice, ENUM_CURRENT_SETTINGS, &dm); - data->rate = dm.dmDisplayFrequency; + data->rate = dm.dmDisplayFrequency; + } } data->count++; @@ -932,7 +952,19 @@ float DisplayServerWindows::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); - EnumRefreshRateData data = { 0, p_screen, SCREEN_REFRESH_RATE_FALLBACK }; + EnumRefreshRateData data = { Vector<DISPLAYCONFIG_PATH_INFO>(), Vector<DISPLAYCONFIG_MODE_INFO>(), 0, p_screen, SCREEN_REFRESH_RATE_FALLBACK }; + + uint32_t path_count = 0; + uint32_t mode_count = 0; + if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_count, &mode_count) == ERROR_SUCCESS) { + data.paths.resize(path_count); + data.modes.resize(mode_count); + if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_count, data.paths.ptrw(), &mode_count, data.modes.ptrw(), nullptr) != ERROR_SUCCESS) { + data.paths.clear(); + data.modes.clear(); + } + } + EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcRefreshRate, (LPARAM)&data); return data.rate; } @@ -1916,6 +1948,10 @@ bool DisplayServerWindows::window_is_focused(WindowID p_window) const { return wd.window_focused; } +DisplayServerWindows::WindowID DisplayServerWindows::get_focused_window() const { + return last_focused_window; +} + bool DisplayServerWindows::window_can_draw(WindowID p_window) const { _THREAD_SAFE_METHOD_ diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 29c2460c10..2668e14540 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -611,6 +611,8 @@ public: virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override; virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual WindowID get_focused_window() const override; + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override; virtual bool can_any_window_draw() const override; diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 418f38c127..6cdd370bfe 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -37,9 +37,9 @@ #include "core/io/image_loader.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" -#include "editor/editor_scale.h" #include "editor/editor_string_names.h" #include "editor/export/editor_export.h" +#include "editor/themes/editor_scale.h" #include "modules/modules_enabled.gen.h" // For svg. #ifdef MODULE_SVG_ENABLED diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis index 36b0919185..94cc52be98 100644 --- a/platform/windows/godot.natvis +++ b/platform/windows/godot.natvis @@ -5,11 +5,43 @@ <Item Name="[size]">_cowdata._ptr ? (((const unsigned int *)(_cowdata._ptr))[-1]) : 0</Item> <ArrayItems> <Size>_cowdata._ptr ? (((const unsigned int *)(_cowdata._ptr))[-1]) : 0</Size> - <ValuePointer>_cowdata._ptr</ValuePointer> + <ValuePointer>($T1 *) _cowdata._ptr</ValuePointer> </ArrayItems> </Expand> </Type> + <Type Name="Array"> + <Expand> + <Item Name="[size]">_p->array._cowdata._ptr ? (((const unsigned int *)(_p->array._cowdata._ptr))[-1]) : 0</Item> + <ArrayItems> + <Size>_p->array._cowdata._ptr ? (((const unsigned int *)(_p->array._cowdata._ptr))[-1]) : 0</Size> + <ValuePointer>(Variant *) _p->array._cowdata._ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="TypedArray<*>"> + <Expand> + <Item Name="[size]"> _p->array._cowdata._ptr ? (((const unsigned int *)(_p->array._cowdata._ptr))[-1]) : 0</Item> + <ArrayItems> + <Size>_p->array._cowdata._ptr ? (((const unsigned int *)(_p->array._cowdata._ptr))[-1]) : 0</Size> + <ValuePointer >(Variant *) _p->array._cowdata._ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="Dictionary"> + <Expand> + <Item Name="[size]">_p && _p->variant_map.head_element ? _p->variant_map.num_elements : 0</Item> + <LinkedListItems> + <Size>_p && _p->variant_map.head_element ? _p->variant_map.num_elements : 0</Size> + <HeadPointer>_p ? _p->variant_map.head_element : nullptr</HeadPointer> + <NextPointer>next</NextPointer> + <ValueNode Name="[{data.key}]">(*this),view(MapHelper)</ValueNode> + </LinkedListItems> + </Expand> + </Type> + <Type Name="LocalVector<*>"> <Expand> <Item Name="[size]">count</Item> @@ -32,18 +64,80 @@ </Expand> </Type> - <Type Name="HashMap<*,*>"> + <Type Name="NodePath"> + <DisplayString Condition="!data">[empty]</DisplayString> + <DisplayString Condition="!!data">{{[absolute] = {data->absolute} [path] = {data->path,view(NodePathHelper)} [subpath] = {data->subpath,view(NodePathHelper)}}}</DisplayString> <Expand> - <Item Name="[size]">num_elements</Item> + <Item Name="[path]">data->path,view(NodePathHelper)</Item> + <Item Name="[subpath]">data->subpath,view(NodePathHelper)</Item> + <Item Name="[absolute]">data->absolute</Item> + </Expand> + </Type> + + <Type Name="Vector<StringName>" IncludeView="NodePathHelper"> + <Expand> + <ArrayItems> + <Size>_cowdata._ptr ? (((const unsigned int *)(_cowdata._ptr))[-1]) : 0</Size> + <ValuePointer>((StringName *)_cowdata._ptr),view(NodePathHelper)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="StringName" IncludeView="NodePathHelper"> + <DisplayString Condition="_data && _data->cname">{_data->cname,s8b}</DisplayString> + <DisplayString Condition="_data && !_data->cname">{_data->name,s32b}</DisplayString> + <DisplayString Condition="!_data">[empty]</DisplayString> + <StringView Condition="_data && _data->cname">_data->cname,s8b</StringView> + <StringView Condition="_data && !_data->cname">_data->name,s32b</StringView> + </Type> + + <Type Name="HashMapElement<*,*>"> + <DisplayString>{{Key = {($T1 *) &data.key} Value = {($T2 *) &data.value}}}</DisplayString> + <Expand> + <Item Name="[key]">($T1 *) &data.key</Item> + <Item Name="[value]">($T2 *) &data.value</Item> + </Expand> + </Type> + + <!-- elements displayed by index --> + <Type Name="HashMap<*,*,*,*,*>" Priority="Medium"> + <Expand> + <Item Name="[size]">head_element ? num_elements : 0</Item> <LinkedListItems> - <Size>num_elements</Size> + <Size>head_element ? num_elements : 0</Size> <HeadPointer>head_element</HeadPointer> <NextPointer>next</NextPointer> - <ValueNode>data</ValueNode> + <ValueNode>(*this)</ValueNode> </LinkedListItems> </Expand> </Type> + <!-- elements by key:value --> + <!-- show elements by index by specifying "ShowElementsByIndex"--> + <Type Name="HashMap<*,*,*,*,*>" ExcludeView="ShowElementsByIndex" Priority="MediumHigh"> + <Expand> + <Item Name="[size]">head_element ? num_elements : 0</Item> + <LinkedListItems> + <Size>head_element ? num_elements : 0</Size> + <HeadPointer>head_element</HeadPointer> + <NextPointer>next</NextPointer> + <ValueNode Name="[{data.key}]">(*this),view(MapHelper)</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="KeyValue<*,*>" IncludeView="MapHelper"> + <DisplayString>{value}</DisplayString> + </Type> + + <Type Name="HashMapElement<*,*>" IncludeView="MapHelper"> + <DisplayString>{data.value}</DisplayString> + <Expand> + <Item Name="[key]" >($T1 *) &data.key</Item> + <Item Name="[value]">($T2 *) &data.value</Item> + </Expand> + </Type> + <Type Name="VMap<*,*>"> <Expand> <Item Condition="_cowdata._ptr" Name="[size]">*(reinterpret_cast<int*>(_cowdata._ptr) - 1)</Item> @@ -58,11 +152,6 @@ <DisplayString Condition="dynamic_cast<CallableCustomMethodPointerBase*>(key.custom)">{dynamic_cast<CallableCustomMethodPointerBase*>(key.custom)->text}</DisplayString> </Type> - <!-- requires PR 64364 - <Type Name="GDScriptThreadContext"> - <DisplayString Condition="_is_main == true">main thread {_debug_thread_id}</DisplayString> - </Type> - --> <Type Name="Variant"> <DisplayString Condition="type == Variant::NIL">nil</DisplayString> @@ -82,22 +171,22 @@ <DisplayString Condition="type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::QUATERNION">{*(Quaternion *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::STRING_NAME">{*(StringName *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::NODE_PATH">{*(NodePath *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::RID">{*(::RID *)_data._mem}</DisplayString> - <DisplayString Condition="type == Variant::OBJECT">{*(Object *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::OBJECT">{*(*reinterpret_cast<ObjData*>(&_data._mem[0])).obj}</DisplayString> <DisplayString Condition="type == Variant::DICTIONARY">{*(Dictionary *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::PACKED_BYTE_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<unsigned char>*>(_data.packed_array)->array}</DisplayString> <DisplayString Condition="type == Variant::PACKED_INT32_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<int>*>(_data.packed_array)->array}</DisplayString> - <!-- broken, will show incorrect data - <DisplayString Condition="type == Variant::PACKED_INT64_ARRAY">{*(PackedInt64Array *)_data._mem}</DisplayString> - --> + <DisplayString Condition="type == Variant::PACKED_INT64_ARRAY">{*reinterpret_cast<PackedInt64Array *>(&_data.packed_array[1])}</DisplayString> <DisplayString Condition="type == Variant::PACKED_FLOAT32_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<float>*>(_data.packed_array)->array}</DisplayString> <DisplayString Condition="type == Variant::PACKED_FLOAT64_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<double>*>(_data.packed_array)->array}</DisplayString> <DisplayString Condition="type == Variant::PACKED_STRING_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<String>*>(_data.packed_array)->array}</DisplayString> <DisplayString Condition="type == Variant::PACKED_VECTOR2_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<Vector2>*>(_data.packed_array)->array}</DisplayString> <DisplayString Condition="type == Variant::PACKED_VECTOR3_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<Vector3>*>(_data.packed_array)->array}</DisplayString> <DisplayString Condition="type == Variant::PACKED_COLOR_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<Color>*>(_data.packed_array)->array}</DisplayString> + <DisplayString Condition="type < 0 || type >= Variant::VARIANT_MAX">[INVALID]</DisplayString> <StringView Condition="type == Variant::STRING && ((String *)(_data._mem))->_cowdata._ptr">((String *)(_data._mem))->_cowdata._ptr,s32</StringView> @@ -116,20 +205,22 @@ <Item Name="[value]" Condition="type == Variant::PLANE">*(Plane *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::QUATERNION">*(Quaternion *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::COLOR">*(Color *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::STRING_NAME">*(StringName *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::NODE_PATH">*(NodePath *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::RID">*(::RID *)_data._mem</Item> - <Item Name="[value]" Condition="type == Variant::OBJECT">*(Object *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::OBJECT">*(*reinterpret_cast<ObjData*>(&_data._mem[0])).obj</Item> <Item Name="[value]" Condition="type == Variant::DICTIONARY">*(Dictionary *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::ARRAY">*(Array *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::PACKED_BYTE_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<unsigned char>*>(_data.packed_array)->array</Item> - <Item Name="[value]" Condition="type == Variant::PACKED_INT32_ARRAY">*(PackedInt32Array *)_data._mem</Item> - <Item Name="[value]" Condition="type == Variant::PACKED_INT64_ARRAY">*(PackedInt64Array *)_data._mem</Item> - <Item Name="[value]" Condition="type == Variant::PACKED_FLOAT32_ARRAY">*(PackedFloat32Array *)_data._mem</Item> - <Item Name="[value]" Condition="type == Variant::PACKED_FLOAT64_ARRAY">*(PackedFloat64Array *)_data._mem</Item> - <Item Name="[value]" Condition="type == Variant::PACKED_STRING_ARRAY">*(PackedStringArray *)_data._mem</Item> - <Item Name="[value]" Condition="type == Variant::PACKED_VECTOR2_ARRAY">*(PackedVector2Array *)_data._mem</Item> - <Item Name="[value]" Condition="type == Variant::PACKED_VECTOR3_ARRAY">*(PackedVector3Array *)_data._mem</Item> - <Item Name="[value]" Condition="type == Variant::PACKED_COLOR_ARRAY">*(PackedColorArray *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_INT32_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<int>*>(_data.packed_array)->array</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_INT64_ARRAY">*reinterpret_cast<PackedInt64Array *>(&_data.packed_array[1])</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_FLOAT32_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<float>*>(_data.packed_array)->array</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_FLOAT64_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<double>*>(_data.packed_array)->array</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_STRING_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<String>*>(_data.packed_array)->array</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_VECTOR2_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<Vector2>*>(_data.packed_array)->array</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_VECTOR3_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<Vector3>*>(_data.packed_array)->array</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_COLOR_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<Color>*>(_data.packed_array)->array</Item> + </Expand> </Type> @@ -148,10 +239,10 @@ </Type> <Type Name="StringName"> - <DisplayString Condition="_data && _data->cname">{_data->cname}</DisplayString> + <DisplayString Condition="_data && _data->cname">{_data->cname,na}</DisplayString> <DisplayString Condition="_data && !_data->cname">{_data->name,s32}</DisplayString> <DisplayString Condition="!_data">[empty]</DisplayString> - <StringView Condition="_data && _data->cname">_data->cname</StringView> + <StringView Condition="_data && _data->cname">_data->cname,na</StringView> <StringView Condition="_data && !_data->cname">_data->name,s32</StringView> </Type> diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 1d3b80e21e..6ad616da85 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -360,6 +360,8 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han path = get_executable_path().get_base_dir().path_join(p_path.get_file()); } + ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND); + typedef DLL_DIRECTORY_COOKIE(WINAPI * PAddDllDirectory)(PCWSTR); typedef BOOL(WINAPI * PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE); @@ -1183,7 +1185,7 @@ Vector<String> OS_Windows::get_system_font_path_for_text(const String &p_font_na if (FAILED(hr)) { continue; } - String fpath = String::utf16((const char16_t *)&file_path[0]); + String fpath = String::utf16((const char16_t *)&file_path[0]).replace("\\", "/"); WIN32_FIND_DATAW d; HANDLE fnd = FindFirstFileW((LPCWSTR)&file_path[0], &d); @@ -1262,7 +1264,7 @@ String OS_Windows::get_system_font_path(const String &p_font_name, int p_weight, if (FAILED(hr)) { continue; } - String fpath = String::utf16((const char16_t *)&file_path[0]); + String fpath = String::utf16((const char16_t *)&file_path[0]).replace("\\", "/"); WIN32_FIND_DATAW d; HANDLE fnd = FindFirstFileW((LPCWSTR)&file_path[0], &d); diff --git a/platform/windows/vulkan_context_win.h b/platform/windows/vulkan_context_win.h index 29ab1d45c3..770a59de9e 100644 --- a/platform/windows/vulkan_context_win.h +++ b/platform/windows/vulkan_context_win.h @@ -39,7 +39,7 @@ #include <windows.h> class VulkanContextWindows : public VulkanContext { - virtual const char *_get_platform_surface_extension() const; + virtual const char *_get_platform_surface_extension() const override final; public: struct WindowPlatformData { diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index 08b315fa6c..b3a20edea8 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -577,14 +577,16 @@ PackedStringArray AnimatedSprite2D::get_configuration_warnings() const { } void AnimatedSprite2D::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { - if (p_idx == 0 && p_function == "play" && frames.is_valid()) { - List<StringName> al; - frames->get_animation_list(&al); - for (const StringName &name : al) { - r_options->push_back(String(name).quote()); + if (p_idx == 0 && frames.is_valid()) { + if (p_function == "play" || p_function == "play_backwards" || p_function == "set_animation" || p_function == "set_autoplay") { + List<StringName> al; + frames->get_animation_list(&al); + for (const StringName &name : al) { + r_options->push_back(String(name).quote()); + } } } - Node::get_argument_options(p_function, p_idx, r_options); + Node2D::get_argument_options(p_function, p_idx, r_options); } #ifndef DISABLE_DEPRECATED diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index afc5748ac5..a99964c0e0 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -36,6 +36,8 @@ #include "scene/main/window.h" #include "scene/resources/world_2d.h" +#define PARAM_PREFIX "parameters/" + void AudioStreamPlayer2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -222,9 +224,36 @@ void AudioStreamPlayer2D::_update_panning() { last_mix_count = AudioServer::get_singleton()->get_mix_count(); } +void AudioStreamPlayer2D::_update_stream_parameters() { + if (stream.is_null()) { + return; + } + + List<AudioStream::Parameter> parameters; + stream->get_parameter_list(¶meters); + for (const AudioStream::Parameter &K : parameters) { + const PropertyInfo &pi = K.property; + StringName key = PARAM_PREFIX + pi.name; + if (!playback_parameters.has(key)) { + ParameterData pd; + pd.path = pi.name; + pd.value = K.default_value; + playback_parameters.insert(key, pd); + } + } +} + void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) { + if (stream.is_valid()) { + stream->disconnect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer2D::_update_stream_parameters)); + } stop(); stream = p_stream; + _update_stream_parameters(); + if (stream.is_valid()) { + stream->connect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer2D::_update_stream_parameters)); + } + notify_property_list_changed(); } Ref<AudioStream> AudioStreamPlayer2D::get_stream() const { @@ -262,6 +291,10 @@ void AudioStreamPlayer2D::play(float p_from_pos) { Ref<AudioStreamPlayback> stream_playback = stream->instantiate_playback(); ERR_FAIL_COND_MSG(stream_playback.is_null(), "Failed to instantiate playback."); + for (const KeyValue<StringName, ParameterData> &K : playback_parameters) { + stream_playback->set_parameter(K.value.path, K.value.value); + } + stream_playbacks.push_back(stream_playback); setplayback = stream_playback; setplay.set(p_from_pos); @@ -430,6 +463,42 @@ void AudioStreamPlayer2D::_on_bus_renamed(int p_bus_index, const StringName &p_o notify_property_list_changed(); } +bool AudioStreamPlayer2D::_set(const StringName &p_name, const Variant &p_value) { + HashMap<StringName, ParameterData>::Iterator I = playback_parameters.find(p_name); + if (!I) { + return false; + } + ParameterData &pd = I->value; + pd.value = p_value; + for (Ref<AudioStreamPlayback> &playback : stream_playbacks) { + playback->set_parameter(pd.path, pd.value); + } + return true; +} + +bool AudioStreamPlayer2D::_get(const StringName &p_name, Variant &r_ret) const { + HashMap<StringName, ParameterData>::ConstIterator I = playback_parameters.find(p_name); + if (!I) { + return false; + } + + r_ret = I->value.value; + return true; +} + +void AudioStreamPlayer2D::_get_property_list(List<PropertyInfo> *p_list) const { + if (stream.is_null()) { + return; + } + List<AudioStream::Parameter> parameters; + stream->get_parameter_list(¶meters); + for (const AudioStream::Parameter &K : parameters) { + PropertyInfo pi = K.property; + pi.name = PARAM_PREFIX + pi.name; + p_list->push_back(pi); + } +} + void AudioStreamPlayer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer2D::set_stream); ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer2D::get_stream); diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h index 0766f2f77d..267d6a625b 100644 --- a/scene/2d/audio_stream_player_2d.h +++ b/scene/2d/audio_stream_player_2d.h @@ -89,11 +89,23 @@ private: float panning_strength = 1.0f; float cached_global_panning_strength = 0.5f; + struct ParameterData { + StringName path; + Variant value; + }; + + HashMap<StringName, ParameterData> playback_parameters; + void _update_stream_parameters(); + protected: void _validate_property(PropertyInfo &p_property) const; void _notification(int p_what); static void _bind_methods(); + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + public: void set_stream(Ref<AudioStream> p_stream); Ref<AudioStream> get_stream() const; diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 0f5fa6543e..08baa7e387 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -229,7 +229,7 @@ void Camera2D::_notification(int p_what) { } break; case NOTIFICATION_TRANSFORM_CHANGED: { - if (!is_processing_internal() && !is_physics_processing_internal()) { + if (!position_smoothing_enabled || _is_editing_in_editor()) { _update_scroll(); } } break; diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 2fbe4eb409..4e5852984b 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -523,30 +523,22 @@ void CollisionObject2D::_input_event_call(Viewport *p_viewport, const Ref<InputE } void CollisionObject2D::_mouse_enter() { - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter); - } + GDVIRTUAL_CALL(_mouse_enter); emit_signal(SceneStringNames::get_singleton()->mouse_entered); } void CollisionObject2D::_mouse_exit() { - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit); - } + GDVIRTUAL_CALL(_mouse_exit); emit_signal(SceneStringNames::get_singleton()->mouse_exited); } void CollisionObject2D::_mouse_shape_enter(int p_shape) { - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_shape_enter, p_shape); - } + GDVIRTUAL_CALL(_mouse_shape_enter, p_shape); emit_signal(SceneStringNames::get_singleton()->mouse_shape_entered, p_shape); } void CollisionObject2D::_mouse_shape_exit(int p_shape) { - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_shape_exit, p_shape); - } + GDVIRTUAL_CALL(_mouse_shape_exit, p_shape); emit_signal(SceneStringNames::get_singleton()->mouse_shape_exited, p_shape); } diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index ee33ff88d4..71da9cc520 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -712,12 +712,15 @@ void GPUParticles2D::_notification(int p_what) { } break; case NOTIFICATION_INTERNAL_PROCESS: { - RS::get_singleton()->particles_set_emitter_velocity(particles, - Vector3((get_global_position() - previous_position).x, - (get_global_position() - previous_position).y, - 0.0) / - get_process_delta_time()); + const Vector3 velocity = Vector3((get_global_position() - previous_position).x, (get_global_position() - previous_position).y, 0.0) / + get_process_delta_time(); + + if (velocity != previous_velocity) { + RS::get_singleton()->particles_set_emitter_velocity(particles, velocity); + previous_velocity = velocity; + } previous_position = get_global_position(); + if (one_shot) { time += get_process_delta_time(); if (time > emission_time) { diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index 40831cd30e..58996b0327 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -64,6 +64,7 @@ private: bool fractional_delta = false; bool interpolate = true; float interp_to_end_factor = 0; + Vector3 previous_velocity; Vector2 previous_position; #ifdef TOOLS_ENABLED bool show_visibility_rect = false; diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 15b638ed92..c03786caef 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -425,6 +425,17 @@ real_t PointLight2D::get_texture_scale() const { return _scale; } +#ifndef DISABLE_DEPRECATED +bool PointLight2D::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "mode" && p_value.is_num()) { // Compatibility with Godot 3.x. + set_blend_mode((BlendMode)(int)p_value); + return true; + } + + return false; +} +#endif // DISABLE_DEPRECATED + void PointLight2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture", "texture"), &PointLight2D::set_texture); ClassDB::bind_method(D_METHOD("get_texture"), &PointLight2D::get_texture); diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 6a454a421e..3c1171deae 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -146,6 +146,9 @@ private: Vector2 texture_offset; protected: +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); +#endif // DISABLE_DEPRECATED static void _bind_methods(); public: diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 8e4b6bfa19..00c0912690 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -245,7 +245,7 @@ void NavigationRegion2D::bake_navigation_polygon(bool p_on_thread) { void NavigationRegion2D::_bake_finished(Ref<NavigationPolygon> p_navigation_polygon) { if (!Thread::is_main_thread()) { - call_deferred(SNAME("_bake_finished"), p_navigation_polygon); + callable_mp(this, &NavigationRegion2D::_bake_finished).call_deferred(p_navigation_polygon); return; } diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index ee0ccc42ff..282d14da5d 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -34,7 +34,7 @@ #include "scene/main/timer.h" #ifdef TOOLS_ENABLED -#include "editor/editor_scale.h" +#include "editor/themes/editor_scale.h" #endif #ifdef TOOLS_ENABLED @@ -146,8 +146,8 @@ void Path2D::_notification(int p_what) { for (int i = 0; i < sample_count; i++) { const Vector2 p = r[i].get_origin(); - const Vector2 side = r[i].columns[0]; - const Vector2 forward = r[i].columns[1]; + const Vector2 side = r[i].columns[1]; + const Vector2 forward = r[i].columns[0]; // Fish Bone. w[0] = p + (side - forward) * 5; @@ -232,8 +232,8 @@ void PathFollow2D::_update_transform() { if (rotates) { Transform2D xform = c->sample_baked_with_rotation(progress, cubic); - xform.translate_local(v_offset, h_offset); - set_rotation(xform[1].angle()); + xform.translate_local(h_offset, v_offset); + set_rotation(xform[0].angle()); set_position(xform[2]); } else { Vector2 pos = c->sample_baked(progress, cubic); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index ee186de5f1..4266060466 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -375,14 +375,14 @@ void Polygon2D::_notification(int p_what) { // Compute transform between mesh and skeleton for runtime AABB compute. const Transform2D mesh_transform = get_global_transform(); const Transform2D skeleton_transform = skeleton_node->get_global_transform(); - const Transform2D mesh_to_sk2d = mesh_transform * skeleton_transform.affine_inverse(); + const Transform2D mesh_to_sk2d = skeleton_transform.affine_inverse() * mesh_transform; // Convert 2d transform to 3d. sd.mesh_to_skeleton_xform.basis.rows[0][0] = mesh_to_sk2d.columns[0][0]; - sd.mesh_to_skeleton_xform.basis.rows[0][1] = mesh_to_sk2d.columns[0][1]; + sd.mesh_to_skeleton_xform.basis.rows[1][0] = mesh_to_sk2d.columns[0][1]; sd.mesh_to_skeleton_xform.origin.x = mesh_to_sk2d.get_origin().x; - sd.mesh_to_skeleton_xform.basis.rows[1][0] = mesh_to_sk2d.columns[1][0]; + sd.mesh_to_skeleton_xform.basis.rows[0][1] = mesh_to_sk2d.columns[1][0]; sd.mesh_to_skeleton_xform.basis.rows[1][1] = mesh_to_sk2d.columns[1][1]; sd.mesh_to_skeleton_xform.origin.y = mesh_to_sk2d.get_origin().y; } diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 527bbaf956..69e0414855 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -433,29 +433,23 @@ PackedStringArray Bone2D::get_configuration_warnings() const { } void Bone2D::calculate_length_and_rotation() { - // if there is at least a single child Bone2D node, we can calculate + // If there is at least a single child Bone2D node, we can calculate // the length and direction. We will always just use the first Bone2D for this. - bool calculated = false; int child_count = get_child_count(); - if (child_count > 0) { - for (int i = 0; i < child_count; i++) { - Bone2D *child = Object::cast_to<Bone2D>(get_child(i)); - if (child) { - Vector2 child_local_pos = to_local(child->get_global_position()); - length = child_local_pos.length(); - bone_angle = child_local_pos.normalized().angle(); - calculated = true; - break; - } + Transform2D global_inv = get_global_transform().affine_inverse(); + + for (int i = 0; i < child_count; i++) { + Bone2D *child = Object::cast_to<Bone2D>(get_child(i)); + if (child) { + Vector2 child_local_pos = global_inv.xform(child->get_global_position()); + length = child_local_pos.length(); + bone_angle = child_local_pos.angle(); + return; // Finished! } } - if (calculated) { - return; // Finished! - } else { - WARN_PRINT("No Bone2D children of node " + get_name() + ". Cannot calculate bone length or angle reliably.\nUsing transform rotation for bone angle"); - bone_angle = get_transform().get_rotation(); - return; - } + + WARN_PRINT("No Bone2D children of node " + get_name() + ". Cannot calculate bone length or angle reliably.\nUsing transform rotation for bone angle."); + bone_angle = get_transform().get_rotation(); } void Bone2D::set_autocalculate_length_and_angle(bool p_autocalculate) { @@ -555,7 +549,7 @@ void Skeleton2D::_make_bone_setup_dirty() { } bone_setup_dirty = true; if (is_inside_tree()) { - call_deferred(SNAME("_update_bone_setup")); + callable_mp(this, &Skeleton2D::_update_bone_setup).call_deferred(); } } @@ -593,7 +587,7 @@ void Skeleton2D::_make_transform_dirty() { } transform_dirty = true; if (is_inside_tree()) { - call_deferred(SNAME("_update_transform")); + callable_mp(this, &Skeleton2D::_update_transform).call_deferred(); } } @@ -764,9 +758,6 @@ void Skeleton2D::execute_modifications(real_t p_delta, int p_execution_mode) { } void Skeleton2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_bone_setup"), &Skeleton2D::_update_bone_setup); - ClassDB::bind_method(D_METHOD("_update_transform"), &Skeleton2D::_update_transform); - ClassDB::bind_method(D_METHOD("get_bone_count"), &Skeleton2D::get_bone_count); ClassDB::bind_method(D_METHOD("get_bone", "idx"), &Skeleton2D::get_bone); diff --git a/scene/2d/tile_map.compat.inc b/scene/2d/tile_map.compat.inc index ed216173c7..04937bdf7e 100644 --- a/scene/2d/tile_map.compat.inc +++ b/scene/2d/tile_map.compat.inc @@ -42,10 +42,20 @@ int TileMap::_get_quadrant_size_compat_81070() const { return get_rendering_quadrant_size(); } +TileMap::VisibilityMode TileMap::_get_collision_visibility_mode_bind_compat_87115() { + return get_collision_visibility_mode(); +} + +TileMap::VisibilityMode TileMap::_get_navigation_visibility_mode_bind_compat_87115() { + return get_navigation_visibility_mode(); +} + void TileMap::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("get_used_rect"), &TileMap::_get_used_rect_bind_compat_78328); ClassDB::bind_compatibility_method(D_METHOD("set_quadrant_size", "quadrant_size"), &TileMap::_set_quadrant_size_compat_81070); ClassDB::bind_compatibility_method(D_METHOD("get_quadrant_size"), &TileMap::_get_quadrant_size_compat_81070); + ClassDB::bind_compatibility_method(D_METHOD("get_collision_visibility_mode"), &TileMap::_get_collision_visibility_mode_bind_compat_87115); + ClassDB::bind_compatibility_method(D_METHOD("get_navigation_visibility_mode"), &TileMap::_get_navigation_visibility_mode_bind_compat_87115); } #endif diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index f2be91cbf3..24eefce99d 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -32,2858 +32,8 @@ #include "tile_map.compat.inc" #include "core/core_string_names.h" -#include "core/io/marshalls.h" -#include "scene/resources/world_2d.h" -#include "servers/navigation_server_2d.h" - -#ifdef DEBUG_ENABLED -#include "servers/navigation_server_3d.h" -#endif // DEBUG_ENABLED - -#ifdef DEBUG_ENABLED -/////////////////////////////// Debug ////////////////////////////////////////// -constexpr int TILE_MAP_DEBUG_QUADRANT_SIZE = 16; - -Vector2i TileMapLayer::_coords_to_debug_quadrant_coords(const Vector2i &p_coords) const { - return Vector2i( - p_coords.x > 0 ? p_coords.x / TILE_MAP_DEBUG_QUADRANT_SIZE : (p_coords.x - (TILE_MAP_DEBUG_QUADRANT_SIZE - 1)) / TILE_MAP_DEBUG_QUADRANT_SIZE, - p_coords.y > 0 ? p_coords.y / TILE_MAP_DEBUG_QUADRANT_SIZE : (p_coords.y - (TILE_MAP_DEBUG_QUADRANT_SIZE - 1)) / TILE_MAP_DEBUG_QUADRANT_SIZE); -} - -void TileMapLayer::_debug_update() { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - RenderingServer *rs = RenderingServer::get_singleton(); - - // Check if we should cleanup everything. - bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree(); - - if (forced_cleanup) { - for (KeyValue<Vector2i, Ref<DebugQuadrant>> &kv : debug_quadrant_map) { - // Free the quadrant. - Ref<DebugQuadrant> &debug_quadrant = kv.value; - if (debug_quadrant->canvas_item.is_valid()) { - rs->free(debug_quadrant->canvas_item); - } - } - debug_quadrant_map.clear(); - _debug_was_cleaned_up = true; - return; - } - - // Check if anything is dirty, in such a case, redraw debug. - bool anything_changed = false; - for (int i = 0; i < DIRTY_FLAGS_MAX; i++) { - if (dirty.flags[i]) { - anything_changed = true; - break; - } - } - - // List all debug quadrants to update, creating new ones if needed. - SelfList<DebugQuadrant>::List dirty_debug_quadrant_list; - - if (_debug_was_cleaned_up || anything_changed) { - // Update all cells. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - CellData &cell_data = kv.value; - _debug_quadrants_update_cell(cell_data, dirty_debug_quadrant_list); - } - } else { - // Update dirty cells. - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - _debug_quadrants_update_cell(cell_data, dirty_debug_quadrant_list); - } - } - - // Update those quadrants. - for (SelfList<DebugQuadrant> *quadrant_list_element = dirty_debug_quadrant_list.first(); quadrant_list_element;) { - SelfList<DebugQuadrant> *next_quadrant_list_element = quadrant_list_element->next(); // "Hack" to clear the list while iterating. - - DebugQuadrant &debug_quadrant = *quadrant_list_element->self(); - - // Check if the quadrant has a tile. - bool has_a_tile = false; - RID &ci = debug_quadrant.canvas_item; - for (SelfList<CellData> *cell_data_list_element = debug_quadrant.cells.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - if (cell_data.cell.source_id != TileSet::INVALID_SOURCE) { - has_a_tile = true; - break; - } - } - - if (has_a_tile) { - // Update the quadrant. - if (ci.is_valid()) { - rs->canvas_item_clear(ci); - } else { - ci = rs->canvas_item_create(); - rs->canvas_item_set_z_index(ci, RS::CANVAS_ITEM_Z_MAX - 1); - rs->canvas_item_set_parent(ci, tile_map_node->get_canvas_item()); - } - - const Vector2 quadrant_pos = tile_map_node->map_to_local(debug_quadrant.quadrant_coords * TILE_MAP_DEBUG_QUADRANT_SIZE); - Transform2D xform(0, quadrant_pos); - rs->canvas_item_set_transform(ci, xform); - - for (SelfList<CellData> *cell_data_list_element = debug_quadrant.cells.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - if (cell_data.cell.source_id != TileSet::INVALID_SOURCE) { - _rendering_draw_cell_debug(ci, quadrant_pos, cell_data); - _physics_draw_cell_debug(ci, quadrant_pos, cell_data); - _navigation_draw_cell_debug(ci, quadrant_pos, cell_data); - _scenes_draw_cell_debug(ci, quadrant_pos, cell_data); - } - } - } else { - // Free the quadrant. - if (ci.is_valid()) { - rs->free(ci); - } - quadrant_list_element->remove_from_list(); - debug_quadrant_map.erase(debug_quadrant.quadrant_coords); - } - - quadrant_list_element = next_quadrant_list_element; - } - - dirty_debug_quadrant_list.clear(); - - _debug_was_cleaned_up = false; -} - -void TileMapLayer::_debug_quadrants_update_cell(CellData &r_cell_data, SelfList<DebugQuadrant>::List &r_dirty_debug_quadrant_list) { - Vector2i quadrant_coords = _coords_to_debug_quadrant_coords(r_cell_data.coords); - - if (!debug_quadrant_map.has(quadrant_coords)) { - // Create a new quadrant and add it to the quadrant map. - Ref<DebugQuadrant> new_quadrant; - new_quadrant.instantiate(); - new_quadrant->quadrant_coords = quadrant_coords; - debug_quadrant_map[quadrant_coords] = new_quadrant; - } - - // Add the cell to its quadrant, if it is not already in there. - Ref<DebugQuadrant> &debug_quadrant = debug_quadrant_map[quadrant_coords]; - if (!r_cell_data.debug_quadrant_list_element.in_list()) { - debug_quadrant->cells.add(&r_cell_data.debug_quadrant_list_element); - } - - // Mark the quadrant as dirty. - if (!debug_quadrant->dirty_quadrant_list_element.in_list()) { - r_dirty_debug_quadrant_list.add(&debug_quadrant->dirty_quadrant_list_element); - } -} -#endif // DEBUG_ENABLED - -/////////////////////////////// Rendering ////////////////////////////////////// -void TileMapLayer::_rendering_update() { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - RenderingServer *rs = RenderingServer::get_singleton(); - - // Check if we should cleanup everything. - bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree(); - - // ----------- Layer level processing ----------- - if (forced_cleanup) { - // Cleanup. - if (canvas_item.is_valid()) { - rs->free(canvas_item); - canvas_item = RID(); - } - } else { - // Create/Update the layer's CanvasItem. - if (!canvas_item.is_valid()) { - RID ci = rs->canvas_item_create(); - rs->canvas_item_set_parent(ci, tile_map_node->get_canvas_item()); - canvas_item = ci; - } - RID &ci = canvas_item; - rs->canvas_item_set_draw_index(ci, layer_index_in_tile_map_node - (int64_t)0x80000000); - rs->canvas_item_set_sort_children_by_y(ci, y_sort_enabled); - rs->canvas_item_set_use_parent_material(ci, tile_map_node->get_use_parent_material() || tile_map_node->get_material().is_valid()); - rs->canvas_item_set_z_index(ci, z_index); - rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(tile_map_node->get_texture_filter_in_tree())); - rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(tile_map_node->get_texture_repeat_in_tree())); - rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask()); - - // Modulate the layer. - Color layer_modulate = modulate; - int selected_layer = tile_map_node->get_selected_layer(); - if (selected_layer >= 0 && layer_index_in_tile_map_node != selected_layer) { - int z_selected = tile_map_node->get_layer_z_index(selected_layer); - if (z_index < z_selected || (z_index == z_selected && layer_index_in_tile_map_node < selected_layer)) { - layer_modulate = layer_modulate.darkened(0.5); - } else if (z_index > z_selected || (z_index == z_selected && layer_index_in_tile_map_node > selected_layer)) { - layer_modulate = layer_modulate.darkened(0.5); - layer_modulate.a *= 0.3; - } - } - rs->canvas_item_set_modulate(ci, layer_modulate); - } - - // ----------- Quadrants processing ----------- - - // List all rendering quadrants to update, creating new ones if needed. - SelfList<RenderingQuadrant>::List dirty_rendering_quadrant_list; - - // Check if anything changed that might change the quadrant shape. - // If so, recreate everything. - bool quandrant_shape_changed = dirty.flags[DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE] || - (tile_map_node->is_y_sort_enabled() && y_sort_enabled && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM] || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET])); - - // Free all quadrants. - if (forced_cleanup || quandrant_shape_changed) { - for (const KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) { - for (int i = 0; i < kv.value->canvas_items.size(); i++) { - const RID &ci = kv.value->canvas_items[i]; - if (ci.is_valid()) { - rs->free(ci); - } - } - kv.value->cells.clear(); - } - rendering_quadrant_map.clear(); - _rendering_was_cleaned_up = true; - } - - if (!forced_cleanup) { - // List all quadrants to update, recreating them if needed. - if (dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || _rendering_was_cleaned_up) { - // Update all cells. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - CellData &cell_data = kv.value; - _rendering_quadrants_update_cell(cell_data, dirty_rendering_quadrant_list); - } - } else { - // Update dirty cells. - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - _rendering_quadrants_update_cell(cell_data, dirty_rendering_quadrant_list); - } - } - - // Update all dirty quadrants. - for (SelfList<RenderingQuadrant> *quadrant_list_element = dirty_rendering_quadrant_list.first(); quadrant_list_element;) { - SelfList<RenderingQuadrant> *next_quadrant_list_element = quadrant_list_element->next(); // "Hack" to clear the list while iterating. - - const Ref<RenderingQuadrant> &rendering_quadrant = quadrant_list_element->self(); - - // Check if the quadrant has a tile. - bool has_a_tile = false; - for (SelfList<CellData> *cell_data_list_element = rendering_quadrant->cells.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - if (cell_data.cell.source_id != TileSet::INVALID_SOURCE) { - has_a_tile = true; - break; - } - } - - if (has_a_tile) { - // Process the quadrant. - - // First, clear the quadrant's canvas items. - for (RID &ci : rendering_quadrant->canvas_items) { - rs->free(ci); - } - rendering_quadrant->canvas_items.clear(); - - // Sort the quadrant cells. - if (tile_map_node->is_y_sort_enabled() && is_y_sort_enabled()) { - // For compatibility reasons, we use another comparator for Y-sorted layers. - rendering_quadrant->cells.sort_custom<CellDataYSortedComparator>(); - } else { - rendering_quadrant->cells.sort(); - } - - // Those allow to group cell per material or z-index. - Ref<Material> prev_material; - int prev_z_index = 0; - RID prev_ci; - - for (SelfList<CellData> *cell_data_quadrant_list_element = rendering_quadrant->cells.first(); cell_data_quadrant_list_element; cell_data_quadrant_list_element = cell_data_quadrant_list_element->next()) { - CellData &cell_data = *cell_data_quadrant_list_element->self(); - - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(cell_data.cell.source_id)); - - // Get the tile data. - const TileData *tile_data; - if (cell_data.runtime_tile_data_cache) { - tile_data = cell_data.runtime_tile_data_cache; - } else { - tile_data = atlas_source->get_tile_data(cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile); - } - - Ref<Material> mat = tile_data->get_material(); - int tile_z_index = tile_data->get_z_index(); - - // Quandrant pos. - - // --- CanvasItems --- - RID ci; - - // Check if the material or the z_index changed. - if (prev_ci == RID() || prev_material != mat || prev_z_index != tile_z_index) { - // If so, create a new CanvasItem. - ci = rs->canvas_item_create(); - if (mat.is_valid()) { - rs->canvas_item_set_material(ci, mat->get_rid()); - } - rs->canvas_item_set_parent(ci, canvas_item); - rs->canvas_item_set_use_parent_material(ci, tile_map_node->get_use_parent_material() || tile_map_node->get_material().is_valid()); - - Transform2D xform(0, rendering_quadrant->canvas_items_position); - rs->canvas_item_set_transform(ci, xform); - - rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask()); - rs->canvas_item_set_z_as_relative_to_parent(ci, true); - rs->canvas_item_set_z_index(ci, tile_z_index); - - rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(tile_map_node->get_texture_filter_in_tree())); - rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(tile_map_node->get_texture_repeat_in_tree())); - - rendering_quadrant->canvas_items.push_back(ci); - - prev_ci = ci; - prev_material = mat; - prev_z_index = tile_z_index; - - } else { - // Keep the same canvas_item to draw on. - ci = prev_ci; - } - - const Vector2 local_tile_pos = tile_map_node->map_to_local(cell_data.coords); - - // Random animation offset. - real_t random_animation_offset = 0.0; - if (atlas_source->get_tile_animation_mode(cell_data.cell.get_atlas_coords()) != TileSetAtlasSource::TILE_ANIMATION_MODE_DEFAULT) { - Array to_hash; - to_hash.push_back(local_tile_pos); - to_hash.push_back(get_instance_id()); // Use instance id as a random hash - random_animation_offset = RandomPCG(to_hash.hash()).randf(); - } - - // Drawing the tile in the canvas item. - tile_map_node->draw_tile(ci, local_tile_pos - rendering_quadrant->canvas_items_position, tile_set, cell_data.cell.source_id, cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile, -1, tile_map_node->get_self_modulate(), tile_data, random_animation_offset); - } - } else { - // Free the quadrant. - for (int i = 0; i < rendering_quadrant->canvas_items.size(); i++) { - const RID &ci = rendering_quadrant->canvas_items[i]; - if (ci.is_valid()) { - rs->free(ci); - } - } - rendering_quadrant->cells.clear(); - rendering_quadrant_map.erase(rendering_quadrant->quadrant_coords); - } - - quadrant_list_element = next_quadrant_list_element; - } - - dirty_rendering_quadrant_list.clear(); - - // Reset the drawing indices. - { - int index = -(int64_t)0x80000000; // Always must be drawn below children. - - // Sort the quadrants coords per local coordinates. - RBMap<Vector2, Ref<RenderingQuadrant>, RenderingQuadrant::CoordsWorldComparator> local_to_map; - for (KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) { - Ref<RenderingQuadrant> &rendering_quadrant = kv.value; - local_to_map[tile_map_node->map_to_local(rendering_quadrant->quadrant_coords)] = rendering_quadrant; - } - - // Sort the quadrants. - for (const KeyValue<Vector2, Ref<RenderingQuadrant>> &E : local_to_map) { - for (const RID &ci : E.value->canvas_items) { - RS::get_singleton()->canvas_item_set_draw_index(ci, index++); - } - } - } - - // Updates on TileMap changes. - if (dirty.flags[DIRTY_FLAGS_TILE_MAP_LIGHT_MASK] || - dirty.flags[DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL] || - dirty.flags[DIRTY_FLAGS_TILE_MAP_MATERIAL] || - dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER] || - dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT]) { - for (KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) { - Ref<RenderingQuadrant> &rendering_quadrant = kv.value; - for (const RID &ci : rendering_quadrant->canvas_items) { - rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask()); - rs->canvas_item_set_use_parent_material(ci, tile_map_node->get_use_parent_material() || tile_map_node->get_material().is_valid()); - rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(tile_map_node->get_texture_filter_in_tree())); - rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(tile_map_node->get_texture_repeat_in_tree())); - } - } - } - } - - // ----------- Occluders processing ----------- - if (forced_cleanup) { - // Clean everything. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - _rendering_occluders_clear_cell(kv.value); - } - } else { - if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) { - // Update all cells. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - _rendering_occluders_update_cell(kv.value); - } - } else { - // Update dirty cells. - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - _rendering_occluders_update_cell(cell_data); - } - } - - // Updates on TileMap changes. - if (dirty.flags[DIRTY_FLAGS_TILE_MAP_IN_CANVAS] || dirty.flags[DIRTY_FLAGS_TILE_MAP_VISIBILITY]) { - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - CellData &cell_data = kv.value; - for (const RID &occluder : cell_data.occluders) { - if (occluder.is_null()) { - continue; - } - Transform2D xform(0, tile_map_node->map_to_local(kv.key)); - rs->canvas_light_occluder_attach_to_canvas(occluder, tile_map_node->get_canvas()); - rs->canvas_light_occluder_set_transform(occluder, tile_map_node->get_global_transform() * xform); - } - } - } - } - - // ----------- - // Mark the rendering state as up to date. - _rendering_was_cleaned_up = forced_cleanup; -} - -void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - - // Check if the cell is valid and retrieve its y_sort_origin. - bool is_valid = false; - int tile_y_sort_origin = 0; - TileSetSource *source; - if (tile_set->has_source(r_cell_data.cell.source_id)) { - source = *tile_set->get_source(r_cell_data.cell.source_id); - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source && atlas_source->has_tile(r_cell_data.cell.get_atlas_coords()) && atlas_source->has_alternative_tile(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile)) { - is_valid = true; - const TileData *tile_data; - if (r_cell_data.runtime_tile_data_cache) { - tile_data = r_cell_data.runtime_tile_data_cache; - } else { - tile_data = atlas_source->get_tile_data(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile); - } - tile_y_sort_origin = tile_data->get_y_sort_origin(); - } - } - - if (is_valid) { - // Get the quadrant coords. - Vector2 canvas_items_position; - Vector2i quadrant_coords; - if (tile_map_node->is_y_sort_enabled() && is_y_sort_enabled()) { - canvas_items_position = Vector2(0, tile_map_node->map_to_local(r_cell_data.coords).y + tile_y_sort_origin + y_sort_origin); - quadrant_coords = canvas_items_position * 100; - } else { - int quad_size = tile_map_node->get_rendering_quadrant_size(); - const Vector2i &coords = r_cell_data.coords; - - // Rounding down, instead of simply rounding towards zero (truncating). - quadrant_coords = Vector2i( - coords.x > 0 ? coords.x / quad_size : (coords.x - (quad_size - 1)) / quad_size, - coords.y > 0 ? coords.y / quad_size : (coords.y - (quad_size - 1)) / quad_size); - canvas_items_position = quad_size * quadrant_coords; - } - - Ref<RenderingQuadrant> rendering_quadrant; - if (rendering_quadrant_map.has(quadrant_coords)) { - // Reuse existing rendering quadrant. - rendering_quadrant = rendering_quadrant_map[quadrant_coords]; - } else { - // Create a new rendering quadrant. - rendering_quadrant.instantiate(); - rendering_quadrant->quadrant_coords = quadrant_coords; - rendering_quadrant->canvas_items_position = canvas_items_position; - rendering_quadrant_map[quadrant_coords] = rendering_quadrant; - } - - // Mark the old quadrant as dirty (if it exists). - if (r_cell_data.rendering_quadrant.is_valid()) { - if (!r_cell_data.rendering_quadrant->dirty_quadrant_list_element.in_list()) { - r_dirty_rendering_quadrant_list.add(&r_cell_data.rendering_quadrant->dirty_quadrant_list_element); - } - } - - // Remove the cell from that quadrant. - if (r_cell_data.rendering_quadrant_list_element.in_list()) { - r_cell_data.rendering_quadrant_list_element.remove_from_list(); - } - - // Add the cell to its new quadrant. - r_cell_data.rendering_quadrant = rendering_quadrant; - r_cell_data.rendering_quadrant->cells.add(&r_cell_data.rendering_quadrant_list_element); - - // Add the new quadrant to the dirty quadrant list. - if (!rendering_quadrant->dirty_quadrant_list_element.in_list()) { - r_dirty_rendering_quadrant_list.add(&rendering_quadrant->dirty_quadrant_list_element); - } - } else { - Ref<RenderingQuadrant> rendering_quadrant = r_cell_data.rendering_quadrant; - - // Remove the cell from its quadrant. - r_cell_data.rendering_quadrant = Ref<RenderingQuadrant>(); - if (r_cell_data.rendering_quadrant_list_element.in_list()) { - rendering_quadrant->cells.remove(&r_cell_data.rendering_quadrant_list_element); - } - - if (rendering_quadrant.is_valid()) { - // Add the quadrant to the dirty quadrant list. - if (!rendering_quadrant->dirty_quadrant_list_element.in_list()) { - r_dirty_rendering_quadrant_list.add(&rendering_quadrant->dirty_quadrant_list_element); - } - } - } -} - -void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) { - RenderingServer *rs = RenderingServer::get_singleton(); - - // Free the occluders. - for (const RID &rid : r_cell_data.occluders) { - rs->free(rid); - } - r_cell_data.occluders.clear(); -} - -void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) { - bool node_visible = tile_map_node->is_visible_in_tree(); - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - RenderingServer *rs = RenderingServer::get_singleton(); - - // Free unused occluders then resize the occluders array. - for (uint32_t i = tile_set->get_occlusion_layers_count(); i < r_cell_data.occluders.size(); i++) { - RID occluder_id = r_cell_data.occluders[i]; - if (occluder_id.is_valid()) { - rs->free(occluder_id); - } - } - r_cell_data.occluders.resize(tile_set->get_occlusion_layers_count()); - - TileSetSource *source; - if (tile_set->has_source(r_cell_data.cell.source_id)) { - source = *tile_set->get_source(r_cell_data.cell.source_id); - - if (source->has_tile(r_cell_data.cell.get_atlas_coords()) && source->has_alternative_tile(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile)) { - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - // Get the tile data. - const TileData *tile_data; - if (r_cell_data.runtime_tile_data_cache) { - tile_data = r_cell_data.runtime_tile_data_cache; - } else { - tile_data = atlas_source->get_tile_data(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile); - } - - // Transform flags. - bool flip_h = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H); - bool flip_v = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V); - bool transpose = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE); - - // Create, update or clear occluders. - for (uint32_t occlusion_layer_index = 0; occlusion_layer_index < r_cell_data.occluders.size(); occlusion_layer_index++) { - Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder(occlusion_layer_index); - - RID &occluder = r_cell_data.occluders[occlusion_layer_index]; - - if (occluder_polygon.is_valid()) { - // Create or update occluder. - Transform2D xform; - xform.set_origin(tile_map_node->map_to_local(r_cell_data.coords)); - if (!occluder.is_valid()) { - occluder = rs->canvas_light_occluder_create(); - } - rs->canvas_light_occluder_set_enabled(occluder, node_visible); - rs->canvas_light_occluder_set_transform(occluder, tile_map_node->get_global_transform() * xform); - rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder(occlusion_layer_index, flip_h, flip_v, transpose)->get_rid()); - rs->canvas_light_occluder_attach_to_canvas(occluder, tile_map_node->get_canvas()); - rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index)); - } else { - // Clear occluder. - if (occluder.is_valid()) { - rs->free(occluder); - occluder = RID(); - } - } - } - - return; - } - } - } - - // If we did not return earlier, clear the cell. - _rendering_occluders_clear_cell(r_cell_data); -} - -#ifdef DEBUG_ENABLED -void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND(!tile_set.is_valid()); - - if (!Engine::get_singleton()->is_editor_hint()) { - return; - } - - // Draw a placeholder for tiles needing one. - RenderingServer *rs = RenderingServer::get_singleton(); - const TileMapCell &c = r_cell_data.cell; - - TileSetSource *source; - if (tile_set->has_source(c.source_id)) { - source = *tile_set->get_source(c.source_id); - - if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - Vector2i grid_size = atlas_source->get_atlas_grid_size(); - if (!atlas_source->get_runtime_texture().is_valid() || c.get_atlas_coords().x >= grid_size.x || c.get_atlas_coords().y >= grid_size.y) { - // Generate a random color from the hashed values of the tiles. - Array to_hash; - to_hash.push_back(c.source_id); - to_hash.push_back(c.get_atlas_coords()); - to_hash.push_back(c.alternative_tile); - uint32_t hash = RandomPCG(to_hash.hash()).rand(); - - Color color; - color = color.from_hsv( - (float)((hash >> 24) & 0xFF) / 256.0, - Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0), - Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0), - 0.8); - - // Draw a placeholder tile. - Transform2D cell_to_quadrant; - cell_to_quadrant.set_origin(tile_map_node->map_to_local(r_cell_data.coords) - p_quadrant_pos); - rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant); - rs->canvas_item_add_circle(p_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); - } - } - } - } -} -#endif // DEBUG_ENABLED - -/////////////////////////////// Physics ////////////////////////////////////// - -void TileMapLayer::_physics_update() { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - - // Check if we should cleanup everything. - bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid(); - if (forced_cleanup) { - // Clean everything. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - _physics_clear_cell(kv.value); - } - } else { - if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_TILE_MAP_COLLISION_ANIMATABLE]) { - // Update all cells. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - _physics_update_cell(kv.value); - } - } else { - // Update dirty cells. - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - _physics_update_cell(cell_data); - } - } - } - - // ----------- - // Mark the physics state as up to date. - _physics_was_cleaned_up = forced_cleanup; -} - -void TileMapLayer::_physics_notify_tilemap_change(TileMapLayer::DirtyFlags p_what) { - Transform2D gl_transform = tile_map_node->get_global_transform(); - PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); - - bool in_editor = false; -#ifdef TOOLS_ENABLED - in_editor = Engine::get_singleton()->is_editor_hint(); -#endif - - if (p_what == DIRTY_FLAGS_TILE_MAP_XFORM) { - if (tile_map_node->is_inside_tree() && (!tile_map_node->is_collision_animatable() || in_editor)) { - // Move the collisison shapes along with the TileMap. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - const CellData &cell_data = kv.value; - - for (RID body : cell_data.bodies) { - if (body.is_valid()) { - Transform2D xform(0, tile_map_node->map_to_local(bodies_coords[body])); - xform = gl_transform * xform; - ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); - } - } - } - } - } else if (p_what == DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM) { - // With collisions animatable, move the collisison shapes along with the TileMap only on local xform change (they are synchornized on physics tick instead). - if (tile_map_node->is_inside_tree() && tile_map_node->is_collision_animatable() && !in_editor) { - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - const CellData &cell_data = kv.value; - - for (RID body : cell_data.bodies) { - if (body.is_valid()) { - Transform2D xform(0, tile_map_node->map_to_local(bodies_coords[body])); - xform = gl_transform * xform; - ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); - } - } - } - } - } else if (p_what == DIRTY_FLAGS_TILE_MAP_IN_TREE) { - // Changes in the tree may cause the space to change (e.g. when reparenting to a SubViewport). - if (tile_map_node->is_inside_tree()) { - RID space = tile_map_node->get_world_2d()->get_space(); - - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - const CellData &cell_data = kv.value; - - for (RID body : cell_data.bodies) { - if (body.is_valid()) { - ps->body_set_space(body, space); - } - } - } - } - } -} - -void TileMapLayer::_physics_clear_cell(CellData &r_cell_data) { - PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); - - // Clear bodies. - for (RID body : r_cell_data.bodies) { - if (body.is_valid()) { - bodies_coords.erase(body); - ps->free(body); - } - } - r_cell_data.bodies.clear(); -} - -void TileMapLayer::_physics_update_cell(CellData &r_cell_data) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - Transform2D gl_transform = tile_map_node->get_global_transform(); - RID space = tile_map_node->get_world_2d()->get_space(); - PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); - - // Recreate bodies and shapes. - TileMapCell &c = r_cell_data.cell; - - TileSetSource *source; - if (tile_set->has_source(c.source_id)) { - source = *tile_set->get_source(c.source_id); - - if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - const TileData *tile_data; - if (r_cell_data.runtime_tile_data_cache) { - tile_data = r_cell_data.runtime_tile_data_cache; - } else { - tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); - } - - // Transform flags. - bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H); - bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V); - bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE); - - // Free unused bodies then resize the bodies array. - for (uint32_t i = tile_set->get_physics_layers_count(); i < r_cell_data.bodies.size(); i++) { - RID body = r_cell_data.bodies[i]; - if (body.is_valid()) { - bodies_coords.erase(body); - ps->free(body); - } - } - r_cell_data.bodies.resize(tile_set->get_physics_layers_count()); - - for (uint32_t tile_set_physics_layer = 0; tile_set_physics_layer < (uint32_t)tile_set->get_physics_layers_count(); tile_set_physics_layer++) { - Ref<PhysicsMaterial> physics_material = tile_set->get_physics_layer_physics_material(tile_set_physics_layer); - uint32_t physics_layer = tile_set->get_physics_layer_collision_layer(tile_set_physics_layer); - uint32_t physics_mask = tile_set->get_physics_layer_collision_mask(tile_set_physics_layer); - - RID body = r_cell_data.bodies[tile_set_physics_layer]; - if (tile_data->get_collision_polygons_count(tile_set_physics_layer) == 0) { - // No body needed, free it if it exists. - if (body.is_valid()) { - bodies_coords.erase(body); - ps->free(body); - } - body = RID(); - } else { - // Create or update the body. - if (!body.is_valid()) { - body = ps->body_create(); - } - bodies_coords[body] = r_cell_data.coords; - ps->body_set_mode(body, tile_map_node->is_collision_animatable() ? PhysicsServer2D::BODY_MODE_KINEMATIC : PhysicsServer2D::BODY_MODE_STATIC); - ps->body_set_space(body, space); - - Transform2D xform; - xform.set_origin(tile_map_node->map_to_local(r_cell_data.coords)); - xform = gl_transform * xform; - ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); - - ps->body_attach_object_instance_id(body, tile_map_node->get_instance_id()); - ps->body_set_collision_layer(body, physics_layer); - ps->body_set_collision_mask(body, physics_mask); - ps->body_set_pickable(body, false); - ps->body_set_state(body, PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, tile_data->get_constant_linear_velocity(tile_set_physics_layer)); - ps->body_set_state(body, PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, tile_data->get_constant_angular_velocity(tile_set_physics_layer)); - - if (!physics_material.is_valid()) { - ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_BOUNCE, 0); - ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_FRICTION, 1); - } else { - ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material->computed_bounce()); - ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_FRICTION, physics_material->computed_friction()); - } - - // Clear body's shape if needed. - ps->body_clear_shapes(body); - - // Add the shapes to the body. - int body_shape_index = 0; - for (int polygon_index = 0; polygon_index < tile_data->get_collision_polygons_count(tile_set_physics_layer); polygon_index++) { - // Iterate over the polygons. - bool one_way_collision = tile_data->is_collision_polygon_one_way(tile_set_physics_layer, polygon_index); - float one_way_collision_margin = tile_data->get_collision_polygon_one_way_margin(tile_set_physics_layer, polygon_index); - int shapes_count = tile_data->get_collision_polygon_shapes_count(tile_set_physics_layer, polygon_index); - for (int shape_index = 0; shape_index < shapes_count; shape_index++) { - // Add decomposed convex shapes. - Ref<ConvexPolygonShape2D> shape = tile_data->get_collision_polygon_shape(tile_set_physics_layer, polygon_index, shape_index, flip_h, flip_v, transpose); - ps->body_add_shape(body, shape->get_rid()); - ps->body_set_shape_as_one_way_collision(body, body_shape_index, one_way_collision, one_way_collision_margin); - - body_shape_index++; - } - } - } - - // Set the body again. - r_cell_data.bodies[tile_set_physics_layer] = body; - } - - return; - } - } - } - - // If we did not return earlier, clear the cell. - _physics_clear_cell(r_cell_data); -} - -#ifdef DEBUG_ENABLED -void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data) { - // Draw the debug collision shapes. - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND(!tile_set.is_valid()); - - if (!tile_map_node->get_tree()) { - return; - } - - bool show_collision = false; - switch (tile_map_node->get_collision_visibility_mode()) { - case TileMap::VISIBILITY_MODE_DEFAULT: - show_collision = !Engine::get_singleton()->is_editor_hint() && tile_map_node->get_tree()->is_debugging_collisions_hint(); - break; - case TileMap::VISIBILITY_MODE_FORCE_HIDE: - show_collision = false; - break; - case TileMap::VISIBILITY_MODE_FORCE_SHOW: - show_collision = true; - break; - } - if (!show_collision) { - return; - } - - RenderingServer *rs = RenderingServer::get_singleton(); - PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); - - Color debug_collision_color = tile_map_node->get_tree()->get_debug_collisions_color(); - Vector<Color> color; - color.push_back(debug_collision_color); - - Transform2D quadrant_to_local(0, p_quadrant_pos); - Transform2D global_to_quadrant = (tile_map_node->get_global_transform() * quadrant_to_local).affine_inverse(); - - for (RID body : r_cell_data.bodies) { - if (body.is_valid()) { - Transform2D body_to_quadrant = global_to_quadrant * Transform2D(ps->body_get_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM)); - rs->canvas_item_add_set_transform(p_canvas_item, body_to_quadrant); - for (int shape_index = 0; shape_index < ps->body_get_shape_count(body); shape_index++) { - const RID &shape = ps->body_get_shape(body, shape_index); - const PhysicsServer2D::ShapeType &type = ps->shape_get_type(shape); - if (type == PhysicsServer2D::SHAPE_CONVEX_POLYGON) { - rs->canvas_item_add_polygon(p_canvas_item, ps->shape_get_data(shape), color); - } else { - WARN_PRINT("Wrong shape type for a tile, should be SHAPE_CONVEX_POLYGON."); - } - } - rs->canvas_item_add_set_transform(p_canvas_item, Transform2D()); - } - } -}; -#endif // DEBUG_ENABLED - -/////////////////////////////// Navigation ////////////////////////////////////// - -void TileMapLayer::_navigation_update() { - ERR_FAIL_NULL(NavigationServer2D::get_singleton()); - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - NavigationServer2D *ns = NavigationServer2D::get_singleton(); - - // Check if we should cleanup everything. - bool forced_cleanup = in_destructor || !enabled || !navigation_enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid(); - - // ----------- Layer level processing ----------- - if (forced_cleanup) { - if (navigation_map.is_valid() && !uses_world_navigation_map) { - ns->free(navigation_map); - navigation_map = RID(); - } - } else { - // Update navigation maps. - if (!navigation_map.is_valid()) { - if (layer_index_in_tile_map_node == 0) { - // Use the default World2D navigation map for the first layer when empty. - navigation_map = tile_map_node->get_world_2d()->get_navigation_map(); - uses_world_navigation_map = true; - } else { - RID new_layer_map = ns->map_create(); - // Set the default NavigationPolygon cell_size on the new map as a mismatch causes an error. - ns->map_set_cell_size(new_layer_map, 1.0); - ns->map_set_active(new_layer_map, true); - navigation_map = new_layer_map; - uses_world_navigation_map = false; - } - } - } - - // ----------- Navigation regions processing ----------- - if (forced_cleanup) { - // Clean everything. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - _navigation_clear_cell(kv.value); - } - } else { - if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) { - // Update all cells. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - _navigation_update_cell(kv.value); - } - } else { - // Update dirty cells. - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - _navigation_update_cell(cell_data); - } - } - - if (dirty.flags[DIRTY_FLAGS_TILE_MAP_XFORM]) { - Transform2D tilemap_xform = tile_map_node->get_global_transform(); - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - const CellData &cell_data = kv.value; - // Update navigation regions transform. - for (const RID ®ion : cell_data.navigation_regions) { - if (!region.is_valid()) { - continue; - } - Transform2D tile_transform; - tile_transform.set_origin(tile_map_node->map_to_local(kv.key)); - NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform); - } - } - } - } - - // ----------- - // Mark the navigation state as up to date. - _navigation_was_cleaned_up = forced_cleanup; -} - -void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) { - NavigationServer2D *ns = NavigationServer2D::get_singleton(); - // Clear navigation shapes. - for (uint32_t i = 0; i < r_cell_data.navigation_regions.size(); i++) { - const RID ®ion = r_cell_data.navigation_regions[i]; - if (region.is_valid()) { - ns->region_set_map(region, RID()); - ns->free(region); - } - } - r_cell_data.navigation_regions.clear(); -} - -void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - NavigationServer2D *ns = NavigationServer2D::get_singleton(); - Transform2D tilemap_xform = tile_map_node->get_global_transform(); - - // Get the navigation polygons and create regions. - TileMapCell &c = r_cell_data.cell; - - TileSetSource *source; - if (tile_set->has_source(c.source_id)) { - source = *tile_set->get_source(c.source_id); - - if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - const TileData *tile_data; - if (r_cell_data.runtime_tile_data_cache) { - tile_data = r_cell_data.runtime_tile_data_cache; - } else { - tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); - } - - // Transform flags. - bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H); - bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V); - bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE); - - // Free unused regions then resize the regions array. - for (uint32_t i = tile_set->get_navigation_layers_count(); i < r_cell_data.navigation_regions.size(); i++) { - RID ®ion = r_cell_data.navigation_regions[i]; - if (region.is_valid()) { - ns->region_set_map(region, RID()); - ns->free(region); - region = RID(); - } - } - r_cell_data.navigation_regions.resize(tile_set->get_navigation_layers_count()); - - // Create, update or clear regions. - for (uint32_t navigation_layer_index = 0; navigation_layer_index < r_cell_data.navigation_regions.size(); navigation_layer_index++) { - Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(navigation_layer_index, flip_h, flip_v, transpose); - - RID ®ion = r_cell_data.navigation_regions[navigation_layer_index]; - - if (navigation_polygon.is_valid() && (navigation_polygon->get_polygon_count() > 0 || navigation_polygon->get_outline_count() > 0)) { - // Create or update regions. - Transform2D tile_transform; - tile_transform.set_origin(tile_map_node->map_to_local(r_cell_data.coords)); - if (!region.is_valid()) { - region = ns->region_create(); - } - ns->region_set_owner_id(region, tile_map_node->get_instance_id()); - ns->region_set_map(region, navigation_map); - ns->region_set_transform(region, tilemap_xform * tile_transform); - ns->region_set_navigation_layers(region, tile_set->get_navigation_layer_layers(navigation_layer_index)); - ns->region_set_navigation_polygon(region, navigation_polygon); - } else { - // Clear region. - if (region.is_valid()) { - ns->region_set_map(region, RID()); - ns->free(region); - region = RID(); - } - } - } - - return; - } - } - } - - // If we did not return earlier, clear the cell. - _navigation_clear_cell(r_cell_data); -} - -#ifdef DEBUG_ENABLED -void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data) { - // Draw the debug collision shapes. - bool show_navigation = false; - switch (tile_map_node->get_navigation_visibility_mode()) { - case TileMap::VISIBILITY_MODE_DEFAULT: - show_navigation = !Engine::get_singleton()->is_editor_hint() && tile_map_node->get_tree()->is_debugging_navigation_hint(); - break; - case TileMap::VISIBILITY_MODE_FORCE_HIDE: - show_navigation = false; - break; - case TileMap::VISIBILITY_MODE_FORCE_SHOW: - show_navigation = true; - break; - } - if (!show_navigation) { - return; - } - - // Check if the navigation is used. - if (r_cell_data.navigation_regions.is_empty()) { - return; - } - - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - - RenderingServer *rs = RenderingServer::get_singleton(); - const NavigationServer2D *ns2d = NavigationServer2D::get_singleton(); - - bool enabled_geometry_face_random_color = ns2d->get_debug_navigation_enable_geometry_face_random_color(); - bool enabled_edge_lines = ns2d->get_debug_navigation_enable_edge_lines(); - - Color debug_face_color = ns2d->get_debug_navigation_geometry_face_color(); - Color debug_edge_color = ns2d->get_debug_navigation_geometry_edge_color(); - - RandomPCG rand; - - const TileMapCell &c = r_cell_data.cell; - - TileSetSource *source; - if (tile_set->has_source(c.source_id)) { - source = *tile_set->get_source(c.source_id); - - if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - const TileData *tile_data; - if (r_cell_data.runtime_tile_data_cache) { - tile_data = r_cell_data.runtime_tile_data_cache; - } else { - tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); - } - - Transform2D cell_to_quadrant; - cell_to_quadrant.set_origin(tile_map_node->map_to_local(r_cell_data.coords) - p_quadrant_pos); - rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant); - - for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) { - bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H); - bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V); - bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE); - Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(layer_index, flip_h, flip_v, transpose); - if (navigation_polygon.is_valid()) { - Vector<Vector2> navigation_polygon_vertices = navigation_polygon->get_vertices(); - if (navigation_polygon_vertices.size() < 3) { - continue; - } - - for (int i = 0; i < navigation_polygon->get_polygon_count(); i++) { - // An array of vertices for this polygon. - Vector<int> polygon = navigation_polygon->get_polygon(i); - Vector<Vector2> debug_polygon_vertices; - debug_polygon_vertices.resize(polygon.size()); - for (int j = 0; j < polygon.size(); j++) { - ERR_FAIL_INDEX(polygon[j], navigation_polygon_vertices.size()); - debug_polygon_vertices.write[j] = navigation_polygon_vertices[polygon[j]]; - } - - // Generate the polygon color, slightly randomly modified from the settings one. - Color random_variation_color = debug_face_color; - if (enabled_geometry_face_random_color) { - random_variation_color.set_hsv( - debug_face_color.get_h() + rand.random(-1.0, 1.0) * 0.1, - debug_face_color.get_s(), - debug_face_color.get_v() + rand.random(-1.0, 1.0) * 0.2); - } - random_variation_color.a = debug_face_color.a; - - Vector<Color> debug_face_colors; - debug_face_colors.push_back(random_variation_color); - rs->canvas_item_add_polygon(p_canvas_item, debug_polygon_vertices, debug_face_colors); - - if (enabled_edge_lines) { - Vector<Color> debug_edge_colors; - debug_edge_colors.push_back(debug_edge_color); - debug_polygon_vertices.push_back(debug_polygon_vertices[0]); // Add first again for closing polyline. - rs->canvas_item_add_polyline(p_canvas_item, debug_polygon_vertices, debug_edge_colors); - } - } - } - } - } - } - } -} -#endif // DEBUG_ENABLED - -/////////////////////////////// Scenes ////////////////////////////////////// - -void TileMapLayer::_scenes_update() { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - - // Check if we should cleanup everything. - bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid(); - - if (forced_cleanup) { - // Clean everything. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - _scenes_clear_cell(kv.value); - } - } else { - if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) { - // Update all cells. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - _scenes_update_cell(kv.value); - } - } else { - // Update dirty cells. - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - _scenes_update_cell(cell_data); - } - } - } - - // ----------- - // Mark the scenes state as up to date. - _scenes_was_cleaned_up = forced_cleanup; -} - -void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) { - // Cleanup existing scene. - Node *node = tile_map_node->get_node_or_null(r_cell_data.scene); - if (node) { - node->queue_free(); - } - r_cell_data.scene = ""; -} - -void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - - // Clear the scene in any case. - _scenes_clear_cell(r_cell_data); - - // Create the scene. - const TileMapCell &c = r_cell_data.cell; - - TileSetSource *source; - if (tile_set->has_source(c.source_id)) { - source = *tile_set->get_source(c.source_id); - - if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { - TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); - if (scenes_collection_source) { - Ref<PackedScene> packed_scene = scenes_collection_source->get_scene_tile_scene(c.alternative_tile); - if (packed_scene.is_valid()) { - Node *scene = packed_scene->instantiate(); - Control *scene_as_control = Object::cast_to<Control>(scene); - Node2D *scene_as_node2d = Object::cast_to<Node2D>(scene); - if (scene_as_control) { - scene_as_control->set_position(tile_map_node->map_to_local(r_cell_data.coords) + scene_as_control->get_position()); - } else if (scene_as_node2d) { - Transform2D xform; - xform.set_origin(tile_map_node->map_to_local(r_cell_data.coords)); - scene_as_node2d->set_transform(xform * scene_as_node2d->get_transform()); - } - tile_map_node->add_child(scene); - r_cell_data.scene = scene->get_name(); - } - } - } - } -} - -#ifdef DEBUG_ENABLED -void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND(!tile_set.is_valid()); - - if (!Engine::get_singleton()->is_editor_hint()) { - return; - } - - // Draw a placeholder for scenes needing one. - RenderingServer *rs = RenderingServer::get_singleton(); - - const TileMapCell &c = r_cell_data.cell; - - TileSetSource *source; - if (tile_set->has_source(c.source_id)) { - source = *tile_set->get_source(c.source_id); - - if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { - return; - } - - TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); - if (scenes_collection_source) { - if (!scenes_collection_source->get_scene_tile_scene(c.alternative_tile).is_valid() || scenes_collection_source->get_scene_tile_display_placeholder(c.alternative_tile)) { - // Generate a random color from the hashed values of the tiles. - Array to_hash; - to_hash.push_back(c.source_id); - to_hash.push_back(c.alternative_tile); - uint32_t hash = RandomPCG(to_hash.hash()).rand(); - - Color color; - color = color.from_hsv( - (float)((hash >> 24) & 0xFF) / 256.0, - Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0), - Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0), - 0.8); - - // Draw a placeholder tile. - Transform2D cell_to_quadrant; - cell_to_quadrant.set_origin(tile_map_node->map_to_local(r_cell_data.coords) - p_quadrant_pos); - rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant); - rs->canvas_item_add_circle(p_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); - } - } - } -} -#endif // DEBUG_ENABLED - -///////////////////////////////////////////////////////////////////// - -void TileMapLayer::_build_runtime_update_tile_data() { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - - // Check if we should cleanup everything. - bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree(); - if (!forced_cleanup) { - if (tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_use_tile_data_runtime_update) && tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_tile_data_runtime_update)) { - if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) { - for (KeyValue<Vector2i, CellData> &E : tile_map) { - _build_runtime_update_tile_data_for_cell(E.value); - } - } else if (dirty.flags[DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE]) { - for (KeyValue<Vector2i, CellData> &E : tile_map) { - _build_runtime_update_tile_data_for_cell(E.value, true); - } - } else { - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - _build_runtime_update_tile_data_for_cell(cell_data); - } - } - } - } - - // ----------- - // Mark the navigation state as up to date. - _runtime_update_tile_data_was_cleaned_up = forced_cleanup; -} - -void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - - TileMapCell &c = r_cell_data.cell; - TileSetSource *source; - if (tile_set->has_source(c.source_id)) { - source = *tile_set->get_source(c.source_id); - - if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - bool ret = false; - if (tile_map_node->GDVIRTUAL_CALL(_use_tile_data_runtime_update, layer_index_in_tile_map_node, r_cell_data.coords, ret) && ret) { - TileData *tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); - - // Create the runtime TileData. - TileData *tile_data_runtime_use = tile_data->duplicate(); - tile_data_runtime_use->set_allow_transform(true); - r_cell_data.runtime_tile_data_cache = tile_data_runtime_use; - - tile_map_node->GDVIRTUAL_CALL(_tile_data_runtime_update, layer_index_in_tile_map_node, r_cell_data.coords, tile_data_runtime_use); - - if (p_auto_add_to_dirty_list) { - dirty.cell_list.add(&r_cell_data.dirty_list_element); - } - } - } - } - } -} - -void TileMapLayer::_clear_runtime_update_tile_data() { - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - - // Clear the runtime tile data. - if (cell_data.runtime_tile_data_cache) { - memdelete(cell_data.runtime_tile_data_cache); - cell_data.runtime_tile_data_cache = nullptr; - } - } -} - -TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (!tile_set.is_valid()) { - return TileSet::TerrainsPattern(); - } - // Returns all tiles compatible with the given constraints. - RBMap<TileSet::TerrainsPattern, int> terrain_pattern_score; - RBSet<TileSet::TerrainsPattern> pattern_set = tile_set->get_terrains_pattern_set(p_terrain_set); - ERR_FAIL_COND_V(pattern_set.is_empty(), TileSet::TerrainsPattern()); - for (TileSet::TerrainsPattern &terrain_pattern : pattern_set) { - int score = 0; - - // Check the center bit constraint. - TerrainConstraint terrain_constraint = TerrainConstraint(tile_map_node, p_position, terrain_pattern.get_terrain()); - const RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_constraint); - if (in_set_constraint_element) { - if (in_set_constraint_element->get().get_terrain() != terrain_constraint.get_terrain()) { - score += in_set_constraint_element->get().get_priority(); - } - } else if (p_current_pattern.get_terrain() != terrain_pattern.get_terrain()) { - continue; // Ignore a pattern that cannot keep bits without constraints unmodified. - } - - // Check the surrounding bits - bool invalid_pattern = false; - for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { - TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); - if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { - // Check if the bit is compatible with the constraints. - TerrainConstraint terrain_bit_constraint = TerrainConstraint(tile_map_node, p_position, bit, terrain_pattern.get_terrain_peering_bit(bit)); - in_set_constraint_element = p_constraints.find(terrain_bit_constraint); - if (in_set_constraint_element) { - if (in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) { - score += in_set_constraint_element->get().get_priority(); - } - } else if (p_current_pattern.get_terrain_peering_bit(bit) != terrain_pattern.get_terrain_peering_bit(bit)) { - invalid_pattern = true; // Ignore a pattern that cannot keep bits without constraints unmodified. - break; - } - } - } - if (invalid_pattern) { - continue; - } - - terrain_pattern_score[terrain_pattern] = score; - } - - // Compute the minimum score. - TileSet::TerrainsPattern min_score_pattern = p_current_pattern; - int min_score = INT32_MAX; - for (KeyValue<TileSet::TerrainsPattern, int> E : terrain_pattern_score) { - if (E.value < min_score) { - min_score_pattern = E.key; - min_score = E.value; - } - } - - return min_score_pattern; -} - -RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (!tile_set.is_valid()) { - return RBSet<TerrainConstraint>(); - } - - // Compute the constraints needed from the surrounding tiles. - RBSet<TerrainConstraint> output; - output.insert(TerrainConstraint(tile_map_node, p_position, p_terrains_pattern.get_terrain())); - - for (uint32_t i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { - TileSet::CellNeighbor side = TileSet::CellNeighbor(i); - if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, side)) { - TerrainConstraint c = TerrainConstraint(tile_map_node, p_position, side, p_terrains_pattern.get_terrain_peering_bit(side)); - output.insert(c); - } - } - - return output; -} - -RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (!tile_set.is_valid()) { - return RBSet<TerrainConstraint>(); - } - - ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), RBSet<TerrainConstraint>()); - - // Build a set of dummy constraints to get the constrained points. - RBSet<TerrainConstraint> dummy_constraints; - for (const Vector2i &E : p_painted) { - for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { // Iterates over neighbor bits. - TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); - if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { - dummy_constraints.insert(TerrainConstraint(tile_map_node, E, bit, -1)); - } - } - } - - // For each constrained point, we get all overlapping tiles, and select the most adequate terrain for it. - RBSet<TerrainConstraint> constraints; - for (const TerrainConstraint &E_constraint : dummy_constraints) { - HashMap<int, int> terrain_count; - - // Count the number of occurrences per terrain. - HashMap<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = E_constraint.get_overlapping_coords_and_peering_bits(); - for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_overlapping : overlapping_terrain_bits) { - TileData *neighbor_tile_data = nullptr; - TileMapCell neighbor_cell = get_cell(E_overlapping.key); - if (neighbor_cell.source_id != TileSet::INVALID_SOURCE) { - Ref<TileSetSource> source = tile_set->get_source(neighbor_cell.source_id); - Ref<TileSetAtlasSource> atlas_source = source; - if (atlas_source.is_valid()) { - TileData *tile_data = atlas_source->get_tile_data(neighbor_cell.get_atlas_coords(), neighbor_cell.alternative_tile); - if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { - neighbor_tile_data = tile_data; - } - } - } - - int terrain = neighbor_tile_data ? neighbor_tile_data->get_terrain_peering_bit(TileSet::CellNeighbor(E_overlapping.value)) : -1; - if (!p_ignore_empty_terrains || terrain >= 0) { - if (!terrain_count.has(terrain)) { - terrain_count[terrain] = 0; - } - terrain_count[terrain] += 1; - } - } - - // Get the terrain with the max number of occurrences. - int max = 0; - int max_terrain = -1; - for (const KeyValue<int, int> &E_terrain_count : terrain_count) { - if (E_terrain_count.value > max) { - max = E_terrain_count.value; - max_terrain = E_terrain_count.key; - } - } - - // Set the adequate terrain. - if (max > 0) { - TerrainConstraint c = E_constraint; - c.set_terrain(max_terrain); - constraints.insert(c); - } - } - - // Add the centers as constraints. - for (Vector2i E_coords : p_painted) { - TileData *tile_data = nullptr; - TileMapCell cell = get_cell(E_coords); - if (cell.source_id != TileSet::INVALID_SOURCE) { - Ref<TileSetSource> source = tile_set->get_source(cell.source_id); - Ref<TileSetAtlasSource> atlas_source = source; - if (atlas_source.is_valid()) { - tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); - } - } - - int terrain = (tile_data && tile_data->get_terrain_set() == p_terrain_set) ? tile_data->get_terrain() : -1; - if (!p_ignore_empty_terrains || terrain >= 0) { - constraints.insert(TerrainConstraint(tile_map_node, E_coords, terrain)); - } - } - - return constraints; -} - -void TileMapLayer::set_tile_map(TileMap *p_tile_map) { - tile_map_node = p_tile_map; -} - -void TileMapLayer::set_layer_index_in_tile_map_node(int p_index) { - if (p_index == layer_index_in_tile_map_node) { - return; - } - layer_index_in_tile_map_node = p_index; - dirty.flags[DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE] = true; - tile_map_node->queue_internal_update(); -} - -Rect2 TileMapLayer::get_rect(bool &r_changed) const { - // Compute the displayed area of the tilemap. - r_changed = false; -#ifdef DEBUG_ENABLED - - if (rect_cache_dirty) { - Rect2 r_total; - bool first = true; - for (const KeyValue<Vector2i, CellData> &E : tile_map) { - Rect2 r; - r.position = tile_map_node->map_to_local(E.key); - r.size = Size2(); - if (first) { - r_total = r; - first = false; - } else { - r_total = r_total.merge(r); - } - } - - r_changed = rect_cache != r_total; - - rect_cache = r_total; - rect_cache_dirty = false; - } -#endif - return rect_cache; -} - -HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (!tile_set.is_valid()) { - return HashMap<Vector2i, TileSet::TerrainsPattern>(); - } - - // Copy the constraints set. - RBSet<TerrainConstraint> constraints = p_constraints; - - // Output map. - HashMap<Vector2i, TileSet::TerrainsPattern> output; - - // Add all positions to a set. - for (int i = 0; i < p_to_replace.size(); i++) { - const Vector2i &coords = p_to_replace[i]; - - // Select the best pattern for the given constraints. - TileSet::TerrainsPattern current_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); - TileMapCell cell = get_cell(coords); - if (cell.source_id != TileSet::INVALID_SOURCE) { - TileSetSource *source = *tile_set->get_source(cell.source_id); - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - // Get tile data. - TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); - if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { - current_pattern = tile_data->get_terrains_pattern(); - } - } - } - TileSet::TerrainsPattern pattern = _get_best_terrain_pattern_for_constraints(p_terrain_set, coords, constraints, current_pattern); - - // Update the constraint set with the new ones. - RBSet<TerrainConstraint> new_constraints = _get_terrain_constraints_from_added_pattern(coords, p_terrain_set, pattern); - for (const TerrainConstraint &E_constraint : new_constraints) { - if (constraints.has(E_constraint)) { - constraints.erase(E_constraint); - } - TerrainConstraint c = E_constraint; - c.set_priority(5); - constraints.insert(c); - } - - output[coords] = pattern; - } - return output; -} - -HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) { - HashMap<Vector2i, TileSet::TerrainsPattern> output; - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND_V(!tile_set.is_valid(), output); - ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output); - - // Build list and set of tiles that can be modified (painted and their surroundings). - Vector<Vector2i> can_modify_list; - RBSet<Vector2i> can_modify_set; - RBSet<Vector2i> painted_set; - for (int i = p_coords_array.size() - 1; i >= 0; i--) { - const Vector2i &coords = p_coords_array[i]; - can_modify_list.push_back(coords); - can_modify_set.insert(coords); - painted_set.insert(coords); - } - for (Vector2i coords : p_coords_array) { - // Find the adequate neighbor. - for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { - TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); - if (tile_map_node->is_existing_neighbor(bit)) { - Vector2i neighbor = tile_map_node->get_neighbor_cell(coords, bit); - if (!can_modify_set.has(neighbor)) { - can_modify_list.push_back(neighbor); - can_modify_set.insert(neighbor); - } - } - } - } - - // Build a set, out of the possibly modified tiles, of the one with a center bit that is set (or will be) to the painted terrain. - RBSet<Vector2i> cells_with_terrain_center_bit; - for (Vector2i coords : can_modify_set) { - bool connect = false; - if (painted_set.has(coords)) { - connect = true; - } else { - // Get the center bit of the cell. - TileData *tile_data = nullptr; - TileMapCell cell = get_cell(coords); - if (cell.source_id != TileSet::INVALID_SOURCE) { - Ref<TileSetSource> source = tile_set->get_source(cell.source_id); - Ref<TileSetAtlasSource> atlas_source = source; - if (atlas_source.is_valid()) { - tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); - } - } - - if (tile_data && tile_data->get_terrain_set() == p_terrain_set && tile_data->get_terrain() == p_terrain) { - connect = true; - } - } - if (connect) { - cells_with_terrain_center_bit.insert(coords); - } - } - - RBSet<TerrainConstraint> constraints; - - // Add new constraints from the path drawn. - for (Vector2i coords : p_coords_array) { - // Constraints on the center bit. - TerrainConstraint c = TerrainConstraint(tile_map_node, coords, p_terrain); - c.set_priority(10); - constraints.insert(c); - - // Constraints on the connecting bits. - for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { - TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); - if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { - c = TerrainConstraint(tile_map_node, coords, bit, p_terrain); - c.set_priority(10); - if ((int(bit) % 2) == 0) { - // Side peering bits: add the constraint if the center is of the same terrain. - Vector2i neighbor = tile_map_node->get_neighbor_cell(coords, bit); - if (cells_with_terrain_center_bit.has(neighbor)) { - constraints.insert(c); - } - } else { - // Corner peering bits: add the constraint if all tiles on the constraint has the same center bit. - HashMap<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits(); - bool valid = true; - for (KeyValue<Vector2i, TileSet::CellNeighbor> kv : overlapping_terrain_bits) { - if (!cells_with_terrain_center_bit.has(kv.key)) { - valid = false; - break; - } - } - if (valid) { - constraints.insert(c); - } - } - } - } - } - - // Fills in the constraint list from existing tiles. - for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(painted_set, p_terrain_set, p_ignore_empty_terrains)) { - constraints.insert(c); - } - - // Fill the terrains. - output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); - return output; -} - -HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) { - HashMap<Vector2i, TileSet::TerrainsPattern> output; - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND_V(!tile_set.is_valid(), output); - ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output); - - // Make sure the path is correct and build the peering bit list while doing it. - Vector<TileSet::CellNeighbor> neighbor_list; - for (int i = 0; i < p_coords_array.size() - 1; i++) { - // Find the adequate neighbor. - TileSet::CellNeighbor found_bit = TileSet::CELL_NEIGHBOR_MAX; - for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { - TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); - if (tile_map_node->is_existing_neighbor(bit)) { - if (tile_map_node->get_neighbor_cell(p_coords_array[i], bit) == p_coords_array[i + 1]) { - found_bit = bit; - break; - } - } - } - ERR_FAIL_COND_V_MSG(found_bit == TileSet::CELL_NEIGHBOR_MAX, output, vformat("Invalid terrain path, %s is not a neighboring tile of %s", p_coords_array[i + 1], p_coords_array[i])); - neighbor_list.push_back(found_bit); - } - - // Build list and set of tiles that can be modified (painted and their surroundings). - Vector<Vector2i> can_modify_list; - RBSet<Vector2i> can_modify_set; - RBSet<Vector2i> painted_set; - for (int i = p_coords_array.size() - 1; i >= 0; i--) { - const Vector2i &coords = p_coords_array[i]; - can_modify_list.push_back(coords); - can_modify_set.insert(coords); - painted_set.insert(coords); - } - for (Vector2i coords : p_coords_array) { - // Find the adequate neighbor. - for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { - TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); - if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { - Vector2i neighbor = tile_map_node->get_neighbor_cell(coords, bit); - if (!can_modify_set.has(neighbor)) { - can_modify_list.push_back(neighbor); - can_modify_set.insert(neighbor); - } - } - } - } - - RBSet<TerrainConstraint> constraints; - - // Add new constraints from the path drawn. - for (Vector2i coords : p_coords_array) { - // Constraints on the center bit. - TerrainConstraint c = TerrainConstraint(tile_map_node, coords, p_terrain); - c.set_priority(10); - constraints.insert(c); - } - for (int i = 0; i < p_coords_array.size() - 1; i++) { - // Constraints on the peering bits. - TerrainConstraint c = TerrainConstraint(tile_map_node, p_coords_array[i], neighbor_list[i], p_terrain); - c.set_priority(10); - constraints.insert(c); - } - - // Fills in the constraint list from existing tiles. - for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(painted_set, p_terrain_set, p_ignore_empty_terrains)) { - constraints.insert(c); - } - - // Fill the terrains. - output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); - return output; -} - -HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) { - HashMap<Vector2i, TileSet::TerrainsPattern> output; - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND_V(!tile_set.is_valid(), output); - ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output); - - // Build list and set of tiles that can be modified (painted and their surroundings). - Vector<Vector2i> can_modify_list; - RBSet<Vector2i> can_modify_set; - RBSet<Vector2i> painted_set; - for (int i = p_coords_array.size() - 1; i >= 0; i--) { - const Vector2i &coords = p_coords_array[i]; - can_modify_list.push_back(coords); - can_modify_set.insert(coords); - painted_set.insert(coords); - } - for (Vector2i coords : p_coords_array) { - // Find the adequate neighbor. - for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { - TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); - if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { - Vector2i neighbor = tile_map_node->get_neighbor_cell(coords, bit); - if (!can_modify_set.has(neighbor)) { - can_modify_list.push_back(neighbor); - can_modify_set.insert(neighbor); - } - } - } - } - - // Add constraint by the new ones. - RBSet<TerrainConstraint> constraints; - - // Add new constraints from the path drawn. - for (Vector2i coords : p_coords_array) { - // Constraints on the center bit. - RBSet<TerrainConstraint> added_constraints = _get_terrain_constraints_from_added_pattern(coords, p_terrain_set, p_terrains_pattern); - for (TerrainConstraint c : added_constraints) { - c.set_priority(10); - constraints.insert(c); - } - } - - // Fills in the constraint list from modified tiles border. - for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(painted_set, p_terrain_set, p_ignore_empty_terrains)) { - constraints.insert(c); - } - - // Fill the terrains. - output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); - return output; -} - -TileMapCell TileMapLayer::get_cell(const Vector2i &p_coords, bool p_use_proxies) const { - if (!tile_map.has(p_coords)) { - return TileMapCell(); - } else { - TileMapCell c = tile_map.find(p_coords)->value.cell; - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (p_use_proxies && tile_set.is_valid()) { - Array proxyed = tile_set->map_tile_proxy(c.source_id, c.get_atlas_coords(), c.alternative_tile); - c.source_id = proxyed[0]; - c.set_atlas_coords(proxyed[1]); - c.alternative_tile = proxyed[2]; - } - return c; - } -} - -void TileMapLayer::set_tile_data(TileMapLayer::DataFormat p_format, const Vector<int> &p_data) { - ERR_FAIL_COND(p_format > TileMapLayer::FORMAT_3); - - // Set data for a given tile from raw data. - - int c = p_data.size(); - const int *r = p_data.ptr(); - - int offset = (p_format >= TileMapLayer::FORMAT_2) ? 3 : 2; - ERR_FAIL_COND_MSG(c % offset != 0, vformat("Corrupted tile data. Got size: %s. Expected modulo: %s", offset)); - - clear(); - -#ifdef DISABLE_DEPRECATED - ERR_FAIL_COND_MSG(p_format != TileMapLayer::FORMAT_3, vformat("Cannot handle deprecated TileMap data format version %d. This Godot version was compiled with no support for deprecated data.", p_format)); -#endif - - for (int i = 0; i < c; i += offset) { - const uint8_t *ptr = (const uint8_t *)&r[i]; - uint8_t local[12]; - for (int j = 0; j < ((p_format >= TileMapLayer::FORMAT_2) ? 12 : 8); j++) { - local[j] = ptr[j]; - } - -#ifdef BIG_ENDIAN_ENABLED - - SWAP(local[0], local[3]); - SWAP(local[1], local[2]); - SWAP(local[4], local[7]); - SWAP(local[5], local[6]); - //TODO: ask someone to check this... - if (FORMAT >= FORMAT_2) { - SWAP(local[8], local[11]); - SWAP(local[9], local[10]); - } -#endif - // Extracts position in TileMap. - int16_t x = decode_uint16(&local[0]); - int16_t y = decode_uint16(&local[2]); - - if (p_format == TileMapLayer::FORMAT_3) { - uint16_t source_id = decode_uint16(&local[4]); - uint16_t atlas_coords_x = decode_uint16(&local[6]); - uint16_t atlas_coords_y = decode_uint16(&local[8]); - uint16_t alternative_tile = decode_uint16(&local[10]); - set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile); - } else { -#ifndef DISABLE_DEPRECATED - // Previous decated format. - - uint32_t v = decode_uint32(&local[4]); - // Extract the transform flags that used to be in the tilemap. - bool flip_h = v & (1UL << 29); - bool flip_v = v & (1UL << 30); - bool transpose = v & (1UL << 31); - v &= (1UL << 29) - 1; - - // Extract autotile/atlas coords. - int16_t coord_x = 0; - int16_t coord_y = 0; - if (p_format == TileMapLayer::FORMAT_2) { - coord_x = decode_uint16(&local[8]); - coord_y = decode_uint16(&local[10]); - } - - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (tile_set.is_valid()) { - Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose); - if (a.size() == 3) { - set_cell(Vector2i(x, y), a[0], a[1], a[2]); - } else { - ERR_PRINT(vformat("No valid tile in Tileset for: tile:%s coords:%s flip_h:%s flip_v:%s transpose:%s", v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose)); - } - } else { - int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2); - set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile); - } -#endif - } - } -} - -Vector<int> TileMapLayer::get_tile_data() const { - // Export tile data to raw format. - Vector<int> tile_data; - tile_data.resize(tile_map.size() * 3); - int *w = tile_data.ptrw(); - - // Save in highest format. - - int idx = 0; - for (const KeyValue<Vector2i, CellData> &E : tile_map) { - uint8_t *ptr = (uint8_t *)&w[idx]; - encode_uint16((int16_t)(E.key.x), &ptr[0]); - encode_uint16((int16_t)(E.key.y), &ptr[2]); - encode_uint16(E.value.cell.source_id, &ptr[4]); - encode_uint16(E.value.cell.coord_x, &ptr[6]); - encode_uint16(E.value.cell.coord_y, &ptr[8]); - encode_uint16(E.value.cell.alternative_tile, &ptr[10]); - idx += 3; - } - - return tile_data; -} - -void TileMapLayer::notify_tile_map_change(DirtyFlags p_what) { - dirty.flags[p_what] = true; - tile_map_node->queue_internal_update(); - _physics_notify_tilemap_change(p_what); -} - -void TileMapLayer::internal_update() { - // Find TileData that need a runtime modification. - // This may add cells to the dirty list is a runtime modification has been notified. - _build_runtime_update_tile_data(); - - // Update all subsystems. - _rendering_update(); - _physics_update(); - _navigation_update(); - _scenes_update(); -#ifdef DEBUG_ENABLED - _debug_update(); -#endif // DEBUG_ENABLED - - _clear_runtime_update_tile_data(); - - // Clear the "what is dirty" flags. - for (int i = 0; i < DIRTY_FLAGS_MAX; i++) { - dirty.flags[i] = false; - } - - // List the cells to delete definitely. - Vector<Vector2i> to_delete; - for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { - CellData &cell_data = *cell_data_list_element->self(); - // Select the the cell from tile_map if it is invalid. - if (cell_data.cell.source_id == TileSet::INVALID_SOURCE) { - to_delete.push_back(cell_data.coords); - } - } - - // Remove cells that are empty after the cleanup. - for (const Vector2i &coords : to_delete) { - tile_map.erase(coords); - } - - // Clear the dirty cells list. - dirty.cell_list.clear(); -} - -void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) { - // Set the current cell tile (using integer position). - Vector2i pk(p_coords); - HashMap<Vector2i, CellData>::Iterator E = tile_map.find(pk); - - int source_id = p_source_id; - Vector2i atlas_coords = p_atlas_coords; - int alternative_tile = p_alternative_tile; - - if ((source_id == TileSet::INVALID_SOURCE || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) && - (source_id != TileSet::INVALID_SOURCE || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) { - source_id = TileSet::INVALID_SOURCE; - atlas_coords = TileSetSource::INVALID_ATLAS_COORDS; - alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; - } - - if (!E) { - if (source_id == TileSet::INVALID_SOURCE) { - return; // Nothing to do, the tile is already empty. - } - - // Insert a new cell in the tile map. - CellData new_cell_data; - new_cell_data.coords = pk; - E = tile_map.insert(pk, new_cell_data); - } else { - if (E->value.cell.source_id == source_id && E->value.cell.get_atlas_coords() == atlas_coords && E->value.cell.alternative_tile == alternative_tile) { - return; // Nothing changed. - } - } - - TileMapCell &c = E->value.cell; - c.source_id = source_id; - c.set_atlas_coords(atlas_coords); - c.alternative_tile = alternative_tile; - - // Make the given cell dirty. - if (!E->value.dirty_list_element.in_list()) { - dirty.cell_list.add(&(E->value.dirty_list_element)); - } - tile_map_node->queue_internal_update(); - - used_rect_cache_dirty = true; -} - -void TileMapLayer::erase_cell(const Vector2i &p_coords) { - set_cell(p_coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); -} - -int TileMapLayer::get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies) const { - // Get a cell source id from position. - HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords); - - if (!E) { - return TileSet::INVALID_SOURCE; - } - - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (p_use_proxies && tile_set.is_valid()) { - Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile); - return proxyed[0]; - } - - return E->value.cell.source_id; -} - -Vector2i TileMapLayer::get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies) const { - // Get a cell source id from position. - HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords); - - if (!E) { - return TileSetSource::INVALID_ATLAS_COORDS; - } - - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (p_use_proxies && tile_set.is_valid()) { - Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile); - return proxyed[1]; - } - - return E->value.cell.get_atlas_coords(); -} - -int TileMapLayer::get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies) const { - // Get a cell source id from position. - HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords); - - if (!E) { - return TileSetSource::INVALID_TILE_ALTERNATIVE; - } - - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - if (p_use_proxies && tile_set.is_valid()) { - Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile); - return proxyed[2]; - } - - return E->value.cell.alternative_tile; -} - -TileData *TileMapLayer::get_cell_tile_data(const Vector2i &p_coords, bool p_use_proxies) const { - int source_id = get_cell_source_id(p_coords, p_use_proxies); - if (source_id == TileSet::INVALID_SOURCE) { - return nullptr; - } - - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - Ref<TileSetAtlasSource> source = tile_set->get_source(source_id); - if (source.is_valid()) { - return source->get_tile_data(get_cell_atlas_coords(p_coords, p_use_proxies), get_cell_alternative_tile(p_coords, p_use_proxies)); - } - - return nullptr; -} - -void TileMapLayer::clear() { - // Remove all tiles. - for (KeyValue<Vector2i, CellData> &kv : tile_map) { - erase_cell(kv.key); - } - used_rect_cache_dirty = true; -} - -Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_array) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr); - - Ref<TileMapPattern> output; - output.instantiate(); - if (p_coords_array.is_empty()) { - return output; - } - - Vector2i min = Vector2i(p_coords_array[0]); - for (int i = 1; i < p_coords_array.size(); i++) { - min = min.min(p_coords_array[i]); - } - - Vector<Vector2i> coords_in_pattern_array; - coords_in_pattern_array.resize(p_coords_array.size()); - Vector2i ensure_positive_offset; - for (int i = 0; i < p_coords_array.size(); i++) { - Vector2i coords = p_coords_array[i]; - Vector2i coords_in_pattern = coords - min; - if (tile_set->get_tile_shape() != TileSet::TILE_SHAPE_SQUARE) { - if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED) { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(min.y % 2) && bool(coords_in_pattern.y % 2)) { - coords_in_pattern.x -= 1; - if (coords_in_pattern.x < 0) { - ensure_positive_offset.x = 1; - } - } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(min.x % 2) && bool(coords_in_pattern.x % 2)) { - coords_in_pattern.y -= 1; - if (coords_in_pattern.y < 0) { - ensure_positive_offset.y = 1; - } - } - } else if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED_OFFSET) { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(min.y % 2) && bool(coords_in_pattern.y % 2)) { - coords_in_pattern.x += 1; - } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(min.x % 2) && bool(coords_in_pattern.x % 2)) { - coords_in_pattern.y += 1; - } - } - } - coords_in_pattern_array.write[i] = coords_in_pattern; - } - - for (int i = 0; i < coords_in_pattern_array.size(); i++) { - Vector2i coords = p_coords_array[i]; - Vector2i coords_in_pattern = coords_in_pattern_array[i]; - output->set_cell(coords_in_pattern + ensure_positive_offset, get_cell_source_id(coords), get_cell_atlas_coords(coords), get_cell_alternative_tile(coords)); - } - - return output; -} - -void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND(tile_set.is_null()); - ERR_FAIL_COND(p_pattern.is_null()); - - TypedArray<Vector2i> used_cells = p_pattern->get_used_cells(); - for (int i = 0; i < used_cells.size(); i++) { - Vector2i coords = tile_map_node->map_pattern(p_position, used_cells[i], p_pattern); - set_cell(coords, p_pattern->get_cell_source_id(used_cells[i]), p_pattern->get_cell_atlas_coords(used_cells[i]), p_pattern->get_cell_alternative_tile(used_cells[i])); - } -} - -void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND(!tile_set.is_valid()); - ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count()); - - Vector<Vector2i> cells_vector; - HashSet<Vector2i> painted_set; - for (int i = 0; i < p_cells.size(); i++) { - cells_vector.push_back(p_cells[i]); - painted_set.insert(p_cells[i]); - } - HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_connect(cells_vector, p_terrain_set, p_terrain, p_ignore_empty_terrains); - for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : terrain_fill_output) { - if (painted_set.has(kv.key)) { - // Paint a random tile with the correct terrain for the painted path. - TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); - set_cell(kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); - } else { - // Avoids updating the painted path from the output if the new pattern is the same as before. - TileSet::TerrainsPattern in_map_terrain_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); - TileMapCell cell = get_cell(kv.key); - if (cell.source_id != TileSet::INVALID_SOURCE) { - TileSetSource *source = *tile_set->get_source(cell.source_id); - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - // Get tile data. - TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); - if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { - in_map_terrain_pattern = tile_data->get_terrains_pattern(); - } - } - } - if (in_map_terrain_pattern != kv.value) { - TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); - set_cell(kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); - } - } - } -} - -void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) { - const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); - ERR_FAIL_COND(!tile_set.is_valid()); - ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count()); - - Vector<Vector2i> vector_path; - HashSet<Vector2i> painted_set; - for (int i = 0; i < p_path.size(); i++) { - vector_path.push_back(p_path[i]); - painted_set.insert(p_path[i]); - } - - HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_path(vector_path, p_terrain_set, p_terrain, p_ignore_empty_terrains); - for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : terrain_fill_output) { - if (painted_set.has(kv.key)) { - // Paint a random tile with the correct terrain for the painted path. - TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); - set_cell(kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); - } else { - // Avoids updating the painted path from the output if the new pattern is the same as before. - TileSet::TerrainsPattern in_map_terrain_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); - TileMapCell cell = get_cell(kv.key); - if (cell.source_id != TileSet::INVALID_SOURCE) { - TileSetSource *source = *tile_set->get_source(cell.source_id); - TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); - if (atlas_source) { - // Get tile data. - TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); - if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { - in_map_terrain_pattern = tile_data->get_terrains_pattern(); - } - } - } - if (in_map_terrain_pattern != kv.value) { - TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); - set_cell(kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); - } - } - } -} - -TypedArray<Vector2i> TileMapLayer::get_used_cells() const { - // Returns the cells used in the tilemap. - TypedArray<Vector2i> a; - for (const KeyValue<Vector2i, CellData> &E : tile_map) { - const TileMapCell &c = E.value.cell; - if (c.source_id == TileSet::INVALID_SOURCE) { - continue; - } - a.push_back(E.key); - } - - return a; -} - -TypedArray<Vector2i> TileMapLayer::get_used_cells_by_id(int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) const { - // Returns the cells used in the tilemap. - TypedArray<Vector2i> a; - for (const KeyValue<Vector2i, CellData> &E : tile_map) { - const TileMapCell &c = E.value.cell; - if (c.source_id == TileSet::INVALID_SOURCE) { - continue; - } - if ((p_source_id == TileSet::INVALID_SOURCE || p_source_id == c.source_id) && - (p_atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || p_atlas_coords == c.get_atlas_coords()) && - (p_alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE || p_alternative_tile == c.alternative_tile)) { - a.push_back(E.key); - } - } - - return a; -} - -Rect2i TileMapLayer::get_used_rect() const { - // Return the rect of the currently used area. - if (used_rect_cache_dirty) { - used_rect_cache = Rect2i(); - - bool first = true; - for (const KeyValue<Vector2i, CellData> &E : tile_map) { - const TileMapCell &c = E.value.cell; - if (c.source_id == TileSet::INVALID_SOURCE) { - continue; - } - if (first) { - used_rect_cache = Rect2i(E.key.x, E.key.y, 0, 0); - first = false; - } else { - used_rect_cache.expand_to(E.key); - } - } - if (!first) { - // Only if we have at least one cell. - // The cache expands to top-left coordinate, so we add one full tile. - used_rect_cache.size += Vector2i(1, 1); - } - used_rect_cache_dirty = false; - } - - return used_rect_cache; -} - -void TileMapLayer::set_name(String p_name) { - if (name == p_name) { - return; - } - name = p_name; - tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); -} - -String TileMapLayer::get_name() const { - return name; -} - -void TileMapLayer::set_enabled(bool p_enabled) { - if (enabled == p_enabled) { - return; - } - enabled = p_enabled; - dirty.flags[DIRTY_FLAGS_LAYER_ENABLED] = true; - tile_map_node->queue_internal_update(); - tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); - - tile_map_node->update_configuration_warnings(); -} - -bool TileMapLayer::is_enabled() const { - return enabled; -} - -void TileMapLayer::set_modulate(Color p_modulate) { - if (modulate == p_modulate) { - return; - } - modulate = p_modulate; - dirty.flags[DIRTY_FLAGS_LAYER_MODULATE] = true; - tile_map_node->queue_internal_update(); - tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); -} - -Color TileMapLayer::get_modulate() const { - return modulate; -} - -void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) { - if (y_sort_enabled == p_y_sort_enabled) { - return; - } - y_sort_enabled = p_y_sort_enabled; - dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] = true; - tile_map_node->queue_internal_update(); - tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); - - tile_map_node->update_configuration_warnings(); -} - -bool TileMapLayer::is_y_sort_enabled() const { - return y_sort_enabled; -} - -void TileMapLayer::set_y_sort_origin(int p_y_sort_origin) { - if (y_sort_origin == p_y_sort_origin) { - return; - } - y_sort_origin = p_y_sort_origin; - dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] = true; - tile_map_node->queue_internal_update(); - tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); -} - -int TileMapLayer::get_y_sort_origin() const { - return y_sort_origin; -} - -void TileMapLayer::set_z_index(int p_z_index) { - if (z_index == p_z_index) { - return; - } - z_index = p_z_index; - dirty.flags[DIRTY_FLAGS_LAYER_Z_INDEX] = true; - tile_map_node->queue_internal_update(); - tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); - - tile_map_node->update_configuration_warnings(); -} - -int TileMapLayer::get_z_index() const { - return z_index; -} - -void TileMapLayer::set_navigation_enabled(bool p_enabled) { - if (navigation_enabled == p_enabled) { - return; - } - navigation_enabled = p_enabled; - dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED] = true; - tile_map_node->queue_internal_update(); - tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); -} - -bool TileMapLayer::is_navigation_enabled() const { - return navigation_enabled; -} - -void TileMapLayer::set_navigation_map(RID p_map) { - ERR_FAIL_COND_MSG(!tile_map_node->is_inside_tree(), "A TileMap navigation map can only be changed while inside the SceneTree."); - navigation_map = p_map; - uses_world_navigation_map = p_map == tile_map_node->get_world_2d()->get_navigation_map(); -} - -RID TileMapLayer::get_navigation_map() const { - if (navigation_map.is_valid()) { - return navigation_map; - } - return RID(); -} - -void TileMapLayer::fix_invalid_tiles() { - Ref<TileSet> tileset = tile_map_node->get_tileset(); - ERR_FAIL_COND_MSG(tileset.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet."); - - RBSet<Vector2i> coords; - for (const KeyValue<Vector2i, CellData> &E : tile_map) { - TileSetSource *source = *tileset->get_source(E.value.cell.source_id); - if (!source || !source->has_tile(E.value.cell.get_atlas_coords()) || !source->has_alternative_tile(E.value.cell.get_atlas_coords(), E.value.cell.alternative_tile)) { - coords.insert(E.key); - } - } - for (const Vector2i &E : coords) { - set_cell(E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); - } -} - -bool TileMapLayer::has_body_rid(RID p_physics_body) const { - return bodies_coords.has(p_physics_body); -} - -Vector2i TileMapLayer::get_coords_for_body_rid(RID p_physics_body) const { - return bodies_coords[p_physics_body]; -} - -TileMapLayer::~TileMapLayer() { - if (!tile_map_node) { - // Temporary layer. - return; - } - - in_destructor = true; - clear(); - internal_update(); -} - -HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coords_and_peering_bits() const { - HashMap<Vector2i, TileSet::CellNeighbor> output; - - ERR_FAIL_COND_V(is_center_bit(), output); - - Ref<TileSet> ts = tile_map->get_tileset(); - ERR_FAIL_COND_V(!ts.is_valid(), output); - - TileSet::TileShape shape = ts->get_tile_shape(); - if (shape == TileSet::TILE_SHAPE_SQUARE) { - switch (bit) { - case 1: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE; - break; - case 2: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER; - break; - case 3: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE; - break; - default: - ERR_FAIL_V(output); - } - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) { - switch (bit) { - case 1: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE; - break; - case 2: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER; - break; - case 3: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; - break; - default: - ERR_FAIL_V(output); - } - } else { - // Half offset shapes. - TileSet::TileOffsetAxis offset_axis = ts->get_tile_offset_axis(); - if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - switch (bit) { - case 1: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE; - break; - case 2: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_CORNER; - break; - case 3: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE; - break; - case 4: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER; - break; - case 5: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; - break; - default: - ERR_FAIL_V(output); - } - } else { - switch (bit) { - case 1: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER; - break; - case 2: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE; - break; - case 3: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER; - break; - case 4: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE; - break; - case 5: - output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE; - output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; - break; - default: - ERR_FAIL_V(output); - } - } - } - return output; -} - -TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, int p_terrain) { - tile_map = p_tile_map; - - Ref<TileSet> ts = tile_map->get_tileset(); - ERR_FAIL_COND(!ts.is_valid()); - - bit = 0; - base_cell_coords = p_position; - terrain = p_terrain; -} - -TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain) { - // The way we build the constraint make it easy to detect conflicting constraints. - tile_map = p_tile_map; - - Ref<TileSet> ts = tile_map->get_tileset(); - ERR_FAIL_COND(!ts.is_valid()); - - TileSet::TileShape shape = ts->get_tile_shape(); - if (shape == TileSet::TILE_SHAPE_SQUARE) { - switch (p_bit) { - case TileSet::CELL_NEIGHBOR_RIGHT_SIDE: - bit = 1; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: - bit = 2; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE: - bit = 3; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_LEFT_SIDE: - bit = 1; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER); - break; - case TileSet::CELL_NEIGHBOR_TOP_SIDE: - bit = 3; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE); - break; - default: - ERR_FAIL(); - break; - } - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) { - switch (p_bit) { - case TileSet::CELL_NEIGHBOR_RIGHT_CORNER: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE: - bit = 1; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER: - bit = 2; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE: - bit = 3; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_LEFT_CORNER: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE: - bit = 1; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_CORNER: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_CORNER); - break; - case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE: - bit = 3; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); - break; - default: - ERR_FAIL(); - break; - } - } else { - // Half-offset shapes. - TileSet::TileOffsetAxis offset_axis = ts->get_tile_offset_axis(); - if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - switch (p_bit) { - case TileSet::CELL_NEIGHBOR_RIGHT_SIDE: - bit = 1; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: - bit = 2; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE: - bit = 3; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER: - bit = 4; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE: - bit = 5; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_LEFT_SIDE: - bit = 1; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER: - bit = 4; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE: - bit = 3; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_CORNER: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE: - bit = 5; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER: - bit = 4; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); - break; - default: - ERR_FAIL(); - break; - } - } else { - switch (p_bit) { - case TileSet::CELL_NEIGHBOR_RIGHT_CORNER: - bit = 1; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE: - bit = 2; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: - bit = 3; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE: - bit = 4; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER: - bit = 1; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE: - bit = 5; - base_cell_coords = p_position; - break; - case TileSet::CELL_NEIGHBOR_LEFT_CORNER: - bit = 3; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE: - bit = 2; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER: - bit = 1; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_SIDE: - bit = 4; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER: - bit = 3; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE); - break; - case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE: - bit = 5; - base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); - break; - default: - ERR_FAIL(); - break; - } - } - } - terrain = p_terrain; -} +#include "scene/2d/tile_map_layer.h" +#include "scene/gui/control.h" #define TILEMAP_CALL_FOR_LAYER(layer, function, ...) \ if (layer < 0) { \ @@ -3017,7 +167,7 @@ void TileMap::set_selected_layer(int p_layer_id) { emit_signal(CoreStringNames::get_singleton()->changed); // Update the layers modulation. - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER); } } @@ -3028,45 +178,9 @@ int TileMap::get_selected_layer() const { void TileMap::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - for (Ref<TileMapLayer> &layer : layers) { - layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_TREE); - } - } break; - - case NOTIFICATION_EXIT_TREE: { - for (Ref<TileMapLayer> &layer : layers) { - layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_TREE); - } - } break; - - case TileMap::NOTIFICATION_ENTER_CANVAS: { - for (Ref<TileMapLayer> &layer : layers) { - layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_CANVAS); - } - } break; - - case TileMap::NOTIFICATION_EXIT_CANVAS: { - for (Ref<TileMapLayer> &layer : layers) { - layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_CANVAS); - } - } break; - - case NOTIFICATION_DRAW: { - // Rendering. - if (tile_set.is_valid()) { - RenderingServer::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), is_y_sort_enabled()); - } - } break; - - case TileMap::NOTIFICATION_VISIBILITY_CHANGED: { - for (Ref<TileMapLayer> &layer : layers) { - layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_VISIBILITY); - } - } break; - case TileMap::NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - // Physics. + // This is only executed when collision_animatable is enabled. + bool in_editor = false; #ifdef TOOLS_ENABLED in_editor = Engine::get_singleton()->is_editor_hint(); @@ -3074,39 +188,30 @@ void TileMap::_notification(int p_what) { if (is_inside_tree() && collision_animatable && !in_editor) { // Update transform on the physics tick when in animatable mode. last_valid_transform = new_transform; + print_line("Physics: ", new_transform); set_notify_local_transform(false); set_global_transform(new_transform); - _update_notify_local_transform(); - } - } break; - - case NOTIFICATION_TRANSFORM_CHANGED: { - // Physics. - for (Ref<TileMapLayer> &layer : layers) { - layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_XFORM); + set_notify_local_transform(true); } } break; case TileMap::NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - for (Ref<TileMapLayer> &layer : layers) { - layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM); - } + // This is only executed when collision_animatable is enabled. - // Physics. bool in_editor = false; #ifdef TOOLS_ENABLED in_editor = Engine::get_singleton()->is_editor_hint(); #endif - // Only active when animatable. Send the new transform to the physics... if (is_inside_tree() && collision_animatable && !in_editor) { // Store last valid transform. new_transform = get_global_transform(); + print_line("local XFORM: ", last_valid_transform); // ... but then revert changes. set_notify_local_transform(false); set_global_transform(last_valid_transform); - _update_notify_local_transform(); + set_notify_local_transform(true); } } break; } @@ -3135,7 +240,7 @@ void TileMap::_internal_update() { } // Update dirty quadrants on layers. - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->internal_update(); } @@ -3158,7 +263,7 @@ void TileMap::set_tileset(const Ref<TileSet> &p_tileset) { tile_set->connect_changed(callable_mp(this, &TileMap::_tile_set_changed)); } - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TILE_SET); } @@ -3173,7 +278,7 @@ void TileMap::set_rendering_quadrant_size(int p_size) { ERR_FAIL_COND_MSG(p_size < 1, "TileMapQuadrant size cannot be smaller than 1."); rendering_quadrant_size = p_size; - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE); } emit_signal(CoreStringNames::get_singleton()->changed); @@ -3279,10 +384,11 @@ void TileMap::add_layer(int p_to_pos) { ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1); // Must clear before adding the layer. - Ref<TileMapLayer> new_layer; - new_layer.instantiate(); - new_layer->set_tile_map(this); + TileMapLayer *new_layer = memnew(TileMapLayer); layers.insert(p_to_pos, new_layer); + add_child(new_layer); + new_layer->set_name(vformat("Layer%d", p_to_pos)); + move_child(new_layer, p_to_pos); for (uint32_t i = 0; i < layers.size(); i++) { layers[i]->set_layer_index_in_tile_map_node(i); } @@ -3299,10 +405,11 @@ void TileMap::move_layer(int p_layer, int p_to_pos) { ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1); // Clear before shuffling layers. - Ref<TileMapLayer> layer = layers[p_layer]; + TileMapLayer *layer = layers[p_layer]; layers.insert(p_to_pos, layer); layers.remove_at(p_to_pos < p_layer ? p_layer + 1 : p_layer); for (uint32_t i = 0; i < layers.size(); i++) { + move_child(layer, i); layers[i]->set_layer_index_in_tile_map_node(i); } queue_internal_update(); @@ -3321,6 +428,7 @@ void TileMap::remove_layer(int p_layer) { ERR_FAIL_INDEX(p_layer, (int)layers.size()); // Clear before removing the layer. + layers[p_layer]->queue_free(); layers.remove_at(p_layer); for (uint32_t i = 0; i < layers.size(); i++) { layers[i]->set_layer_index_in_tile_map_node(i); @@ -3363,7 +471,6 @@ Color TileMap::get_layer_modulate(int p_layer) const { void TileMap::set_layer_y_sort_enabled(int p_layer, bool p_y_sort_enabled) { TILEMAP_CALL_FOR_LAYER(p_layer, set_y_sort_enabled, p_y_sort_enabled); - _update_notify_local_transform(); } bool TileMap::is_layer_y_sort_enabled(int p_layer) const { @@ -3402,17 +509,16 @@ RID TileMap::get_layer_navigation_map(int p_layer) const { TILEMAP_CALL_FOR_LAYER_V(p_layer, RID(), get_navigation_map); } -void TileMap::set_collision_animatable(bool p_enabled) { - if (collision_animatable == p_enabled) { +void TileMap::set_collision_animatable(bool p_collision_animatable) { + if (collision_animatable == p_collision_animatable) { return; } - collision_animatable = p_enabled; - _update_notify_local_transform(); - set_physics_process_internal(p_enabled); - for (Ref<TileMapLayer> &layer : layers) { - layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_COLLISION_ANIMATABLE); + collision_animatable = p_collision_animatable; + set_notify_local_transform(p_collision_animatable); + set_physics_process_internal(p_collision_animatable); + for (TileMapLayer *layer : layers) { + layer->set_use_kinematic_bodies(layer); } - emit_signal(CoreStringNames::get_singleton()->changed); } bool TileMap::is_collision_animatable() const { @@ -3424,13 +530,13 @@ void TileMap::set_collision_visibility_mode(TileMap::VisibilityMode p_show_colli return; } collision_visibility_mode = p_show_collision; - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE); } emit_signal(CoreStringNames::get_singleton()->changed); } -TileMap::VisibilityMode TileMap::get_collision_visibility_mode() { +TileMap::VisibilityMode TileMap::get_collision_visibility_mode() const { return collision_visibility_mode; } @@ -3439,13 +545,13 @@ void TileMap::set_navigation_visibility_mode(TileMap::VisibilityMode p_show_navi return; } navigation_visibility_mode = p_show_navigation; - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE); } emit_signal(CoreStringNames::get_singleton()->changed); } -TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() { +TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() const { return navigation_visibility_mode; } @@ -3454,7 +560,7 @@ void TileMap::set_y_sort_enabled(bool p_enable) { return; } Node2D::set_y_sort_enabled(p_enable); - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED); } emit_signal(CoreStringNames::get_singleton()->changed); @@ -3490,27 +596,8 @@ Ref<TileMapPattern> TileMap::get_pattern(int p_layer, TypedArray<Vector2i> p_coo } Vector2i TileMap::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) { - ERR_FAIL_COND_V(p_pattern.is_null(), Vector2i()); - ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i()); - - Vector2i output = p_position_in_tilemap + p_coords_in_pattern; - if (tile_set->get_tile_shape() != TileSet::TILE_SHAPE_SQUARE) { - if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED) { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) { - output.x += 1; - } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) { - output.y += 1; - } - } else if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED_OFFSET) { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) { - output.x -= 1; - } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) { - output.y -= 1; - } - } - } - - return output; + ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2i()); + return tile_set->map_pattern(p_position_in_tilemap, p_coords_in_pattern, p_pattern); } void TileMap::set_pattern(int p_layer, const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) { @@ -3550,7 +637,7 @@ TileMapCell TileMap::get_cell(int p_layer, const Vector2i &p_coords, bool p_use_ } Vector2i TileMap::get_coords_for_body_rid(RID p_physics_body) { - for (const Ref<TileMapLayer> &layer : layers) { + for (const TileMapLayer *layer : layers) { if (layer->has_body_rid(p_physics_body)) { return layer->get_coords_for_body_rid(p_physics_body); } @@ -3568,7 +655,7 @@ int TileMap::get_layer_for_body_rid(RID p_physics_body) { } void TileMap::fix_invalid_tiles() { - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->fix_invalid_tiles(); } } @@ -3578,7 +665,7 @@ void TileMap::clear_layer(int p_layer) { } void TileMap::clear() { - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->clear(); } } @@ -3592,7 +679,7 @@ void TileMap::notify_runtime_tile_data_update(int p_layer) { if (p_layer >= 0) { TILEMAP_CALL_FOR_LAYER(p_layer, notify_tile_map_change, TileMapLayer::DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE); } else { - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE); } } @@ -3622,7 +709,7 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (p_name == "format") { if (p_value.get_type() == Variant::INT) { - format = (TileMapLayer::DataFormat)(p_value.operator int64_t()); // Set format used for loading. + format = (TileMapDataFormat)(p_value.operator int64_t()); // Set format used for loading. return true; } } @@ -3630,9 +717,9 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) { else if (p_name == "tile_data") { // Kept for compatibility reasons. if (p_value.is_array()) { if (layers.size() == 0) { - Ref<TileMapLayer> new_layer; - new_layer.instantiate(); - new_layer->set_tile_map(this); + TileMapLayer *new_layer = memnew(TileMapLayer); + add_child(new_layer); + new_layer->set_name("Layer0"); new_layer->set_layer_index_in_tile_map_node(0); layers.push_back(new_layer); } @@ -3654,9 +741,9 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) { if (index >= (int)layers.size()) { while (index >= (int)layers.size()) { - Ref<TileMapLayer> new_layer; - new_layer.instantiate(); - new_layer->set_tile_map(this); + TileMapLayer *new_layer = memnew(TileMapLayer); + add_child(new_layer); + new_layer->set_name(vformat("Layer%d", index)); new_layer->set_layer_index_in_tile_map_node(index); layers.push_back(new_layer); } @@ -3701,7 +788,7 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) { bool TileMap::_get(const StringName &p_name, Variant &r_ret) const { Vector<String> components = String(p_name).split("/", true, 2); if (p_name == "format") { - r_ret = TileMapLayer::FORMAT_MAX - 1; // When saving, always save highest format. + r_ret = TileMapDataFormat::FORMAT_MAX - 1; // When saving, always save highest format. return true; } #ifndef DISABLE_DEPRECATED @@ -3835,623 +922,23 @@ bool TileMap::_property_get_revert(const StringName &p_name, Variant &r_property } Vector2 TileMap::map_to_local(const Vector2i &p_pos) const { - // SHOULD RETURN THE CENTER OF THE CELL. ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2()); - - Vector2 ret = p_pos; - TileSet::TileShape tile_shape = tile_set->get_tile_shape(); - TileSet::TileOffsetAxis tile_offset_axis = tile_set->get_tile_offset_axis(); - - if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { - // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap. - // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap. - if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - switch (tile_set->get_tile_layout()) { - case TileSet::TILE_LAYOUT_STACKED: - ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 0 ? 0.0 : 0.5), ret.y); - break; - case TileSet::TILE_LAYOUT_STACKED_OFFSET: - ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 1 ? 0.0 : 0.5), ret.y); - break; - case TileSet::TILE_LAYOUT_STAIRS_RIGHT: - ret = Vector2(ret.x + ret.y / 2, ret.y); - break; - case TileSet::TILE_LAYOUT_STAIRS_DOWN: - ret = Vector2(ret.x / 2, ret.y * 2 + ret.x); - break; - case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: - ret = Vector2((ret.x + ret.y) / 2, ret.y - ret.x); - break; - case TileSet::TILE_LAYOUT_DIAMOND_DOWN: - ret = Vector2((ret.x - ret.y) / 2, ret.y + ret.x); - break; - } - } else { // TILE_OFFSET_AXIS_VERTICAL. - switch (tile_set->get_tile_layout()) { - case TileSet::TILE_LAYOUT_STACKED: - ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 0 ? 0.0 : 0.5)); - break; - case TileSet::TILE_LAYOUT_STACKED_OFFSET: - ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 1 ? 0.0 : 0.5)); - break; - case TileSet::TILE_LAYOUT_STAIRS_RIGHT: - ret = Vector2(ret.x * 2 + ret.y, ret.y / 2); - break; - case TileSet::TILE_LAYOUT_STAIRS_DOWN: - ret = Vector2(ret.x, ret.y + ret.x / 2); - break; - case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: - ret = Vector2(ret.x + ret.y, (ret.y - ret.x) / 2); - break; - case TileSet::TILE_LAYOUT_DIAMOND_DOWN: - ret = Vector2(ret.x - ret.y, (ret.y + ret.x) / 2); - break; - } - } - } - - // Multiply by the overlapping ratio. - double overlapping_ratio = 1.0; - if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { - overlapping_ratio = 0.5; - } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) { - overlapping_ratio = 0.75; - } - ret.y *= overlapping_ratio; - } else { // TILE_OFFSET_AXIS_VERTICAL. - if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { - overlapping_ratio = 0.5; - } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) { - overlapping_ratio = 0.75; - } - ret.x *= overlapping_ratio; - } - - return (ret + Vector2(0.5, 0.5)) * tile_set->get_tile_size(); + return tile_set->map_to_local(p_pos); } -Vector2i TileMap::local_to_map(const Vector2 &p_local_position) const { +Vector2i TileMap::local_to_map(const Vector2 &p_pos) const { ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2i()); - - Vector2 ret = p_local_position; - ret /= tile_set->get_tile_size(); - - TileSet::TileShape tile_shape = tile_set->get_tile_shape(); - TileSet::TileOffsetAxis tile_offset_axis = tile_set->get_tile_offset_axis(); - TileSet::TileLayout tile_layout = tile_set->get_tile_layout(); - - // Divide by the overlapping ratio. - double overlapping_ratio = 1.0; - if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { - overlapping_ratio = 0.5; - } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) { - overlapping_ratio = 0.75; - } - ret.y /= overlapping_ratio; - } else { // TILE_OFFSET_AXIS_VERTICAL. - if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { - overlapping_ratio = 0.5; - } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) { - overlapping_ratio = 0.75; - } - ret.x /= overlapping_ratio; - } - - // For each half-offset shape, we check if we are in the corner of the tile, and thus should correct the local position accordingly. - if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { - // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap. - // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap. - if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - // Smart floor of the position - Vector2 raw_pos = ret; - if (Math::posmod(Math::floor(ret.y), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) { - ret = Vector2(Math::floor(ret.x + 0.5) - 0.5, Math::floor(ret.y)); - } else { - ret = ret.floor(); - } - - // Compute the tile offset, and if we might the output for a neighbor top tile. - Vector2 in_tile_pos = raw_pos - ret; - bool in_top_left_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(-0.5, 1.0 / overlapping_ratio - 1)) <= 0; - bool in_top_right_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(0.5, 1.0 / overlapping_ratio - 1)) > 0; - - switch (tile_layout) { - case TileSet::TILE_LAYOUT_STACKED: - ret = ret.floor(); - if (in_top_left_triangle) { - ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : -1, -1); - } else if (in_top_right_triangle) { - ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 1 : 0, -1); - } - break; - case TileSet::TILE_LAYOUT_STACKED_OFFSET: - ret = ret.floor(); - if (in_top_left_triangle) { - ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? -1 : 0, -1); - } else if (in_top_right_triangle) { - ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : 1, -1); - } - break; - case TileSet::TILE_LAYOUT_STAIRS_RIGHT: - ret = Vector2(ret.x - ret.y / 2, ret.y).floor(); - if (in_top_left_triangle) { - ret += Vector2i(0, -1); - } else if (in_top_right_triangle) { - ret += Vector2i(1, -1); - } - break; - case TileSet::TILE_LAYOUT_STAIRS_DOWN: - ret = Vector2(ret.x * 2, ret.y / 2 - ret.x).floor(); - if (in_top_left_triangle) { - ret += Vector2i(-1, 0); - } else if (in_top_right_triangle) { - ret += Vector2i(1, -1); - } - break; - case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: - ret = Vector2(ret.x - ret.y / 2, ret.y / 2 + ret.x).floor(); - if (in_top_left_triangle) { - ret += Vector2i(0, -1); - } else if (in_top_right_triangle) { - ret += Vector2i(1, 0); - } - break; - case TileSet::TILE_LAYOUT_DIAMOND_DOWN: - ret = Vector2(ret.x + ret.y / 2, ret.y / 2 - ret.x).floor(); - if (in_top_left_triangle) { - ret += Vector2i(-1, 0); - } else if (in_top_right_triangle) { - ret += Vector2i(0, -1); - } - break; - } - } else { // TILE_OFFSET_AXIS_VERTICAL. - // Smart floor of the position. - Vector2 raw_pos = ret; - if (Math::posmod(Math::floor(ret.x), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) { - ret = Vector2(Math::floor(ret.x), Math::floor(ret.y + 0.5) - 0.5); - } else { - ret = ret.floor(); - } - - // Compute the tile offset, and if we might the output for a neighbor top tile. - Vector2 in_tile_pos = raw_pos - ret; - bool in_top_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, -0.5)) > 0; - bool in_bottom_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, 0.5)) <= 0; - - switch (tile_layout) { - case TileSet::TILE_LAYOUT_STACKED: - ret = ret.floor(); - if (in_top_left_triangle) { - ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : -1); - } else if (in_bottom_left_triangle) { - ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 1 : 0); - } - break; - case TileSet::TILE_LAYOUT_STACKED_OFFSET: - ret = ret.floor(); - if (in_top_left_triangle) { - ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? -1 : 0); - } else if (in_bottom_left_triangle) { - ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : 1); - } - break; - case TileSet::TILE_LAYOUT_STAIRS_RIGHT: - ret = Vector2(ret.x / 2 - ret.y, ret.y * 2).floor(); - if (in_top_left_triangle) { - ret += Vector2i(0, -1); - } else if (in_bottom_left_triangle) { - ret += Vector2i(-1, 1); - } - break; - case TileSet::TILE_LAYOUT_STAIRS_DOWN: - ret = Vector2(ret.x, ret.y - ret.x / 2).floor(); - if (in_top_left_triangle) { - ret += Vector2i(-1, 0); - } else if (in_bottom_left_triangle) { - ret += Vector2i(-1, 1); - } - break; - case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: - ret = Vector2(ret.x / 2 - ret.y, ret.y + ret.x / 2).floor(); - if (in_top_left_triangle) { - ret += Vector2i(0, -1); - } else if (in_bottom_left_triangle) { - ret += Vector2i(-1, 0); - } - break; - case TileSet::TILE_LAYOUT_DIAMOND_DOWN: - ret = Vector2(ret.x / 2 + ret.y, ret.y - ret.x / 2).floor(); - if (in_top_left_triangle) { - ret += Vector2i(-1, 0); - } else if (in_bottom_left_triangle) { - ret += Vector2i(0, 1); - } - break; - } - } - } else { - ret = (ret + Vector2(0.00005, 0.00005)).floor(); - } - return Vector2i(ret); + return tile_set->local_to_map(p_pos); } bool TileMap::is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const { ERR_FAIL_COND_V(!tile_set.is_valid(), false); - - TileSet::TileShape shape = tile_set->get_tile_shape(); - if (shape == TileSet::TILE_SHAPE_SQUARE) { - return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER; - - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) { - return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; - } else { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; - } else { - return p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE || - p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; - } - } + return tile_set->is_existing_neighbor(p_cell_neighbor); } Vector2i TileMap::get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const { - ERR_FAIL_COND_V(!tile_set.is_valid(), p_coords); - - TileSet::TileShape shape = tile_set->get_tile_shape(); - if (shape == TileSet::TILE_SHAPE_SQUARE) { - switch (p_cell_neighbor) { - case TileSet::CELL_NEIGHBOR_RIGHT_SIDE: - return p_coords + Vector2i(1, 0); - case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: - return p_coords + Vector2i(1, 1); - case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE: - return p_coords + Vector2i(0, 1); - case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER: - return p_coords + Vector2i(-1, 1); - case TileSet::CELL_NEIGHBOR_LEFT_SIDE: - return p_coords + Vector2i(-1, 0); - case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER: - return p_coords + Vector2i(-1, -1); - case TileSet::CELL_NEIGHBOR_TOP_SIDE: - return p_coords + Vector2i(0, -1); - case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER: - return p_coords + Vector2i(1, -1); - default: - ERR_FAIL_V(p_coords); - } - } else { // Half-offset shapes (square and hexagon). - switch (tile_set->get_tile_layout()) { - case TileSet::TILE_LAYOUT_STACKED: { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - bool is_offset = p_coords.y % 2; - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { - return p_coords + Vector2i(1, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(is_offset ? 1 : 0, 1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { - return p_coords + Vector2i(0, 2); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(is_offset ? 0 : -1, 1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { - return p_coords + Vector2i(-1, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(is_offset ? 0 : -1, -1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { - return p_coords + Vector2i(0, -2); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(is_offset ? 1 : 0, -1); - } else { - ERR_FAIL_V(p_coords); - } - } else { - bool is_offset = p_coords.x % 2; - - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { - return p_coords + Vector2i(0, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(1, is_offset ? 1 : 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { - return p_coords + Vector2i(2, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(1, is_offset ? 0 : -1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { - return p_coords + Vector2i(0, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(-1, is_offset ? 0 : -1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { - return p_coords + Vector2i(-2, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(-1, is_offset ? 1 : 0); - } else { - ERR_FAIL_V(p_coords); - } - } - } break; - case TileSet::TILE_LAYOUT_STACKED_OFFSET: { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - bool is_offset = p_coords.y % 2; - - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { - return p_coords + Vector2i(1, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(is_offset ? 0 : 1, 1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { - return p_coords + Vector2i(0, 2); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(is_offset ? -1 : 0, 1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { - return p_coords + Vector2i(-1, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(is_offset ? -1 : 0, -1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { - return p_coords + Vector2i(0, -2); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(is_offset ? 0 : 1, -1); - } else { - ERR_FAIL_V(p_coords); - } - } else { - bool is_offset = p_coords.x % 2; - - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { - return p_coords + Vector2i(0, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(1, is_offset ? 0 : 1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { - return p_coords + Vector2i(2, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(1, is_offset ? -1 : 0); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { - return p_coords + Vector2i(0, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(-1, is_offset ? -1 : 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { - return p_coords + Vector2i(-2, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(-1, is_offset ? 0 : 1); - } else { - ERR_FAIL_V(p_coords); - } - } - } break; - case TileSet::TILE_LAYOUT_STAIRS_RIGHT: - case TileSet::TILE_LAYOUT_STAIRS_DOWN: { - if ((tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL)) { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { - return p_coords + Vector2i(1, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(0, 1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { - return p_coords + Vector2i(-1, 2); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(-1, 1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { - return p_coords + Vector2i(-1, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(0, -1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { - return p_coords + Vector2i(1, -2); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(1, -1); - } else { - ERR_FAIL_V(p_coords); - } - - } else { - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { - return p_coords + Vector2i(0, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(1, 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { - return p_coords + Vector2i(2, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(1, -1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { - return p_coords + Vector2i(0, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(-1, 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { - return p_coords + Vector2i(-2, 1); - - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(-1, 1); - } else { - ERR_FAIL_V(p_coords); - } - } - } else { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { - return p_coords + Vector2i(2, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(1, 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { - return p_coords + Vector2i(0, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(-1, 1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { - return p_coords + Vector2i(-2, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(-1, 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { - return p_coords + Vector2i(0, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(1, -1); - } else { - ERR_FAIL_V(p_coords); - } - - } else { - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { - return p_coords + Vector2i(-1, 2); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(0, 1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { - return p_coords + Vector2i(1, 0); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(1, -1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { - return p_coords + Vector2i(1, -2); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(0, -1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { - return p_coords + Vector2i(-1, 0); - - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(-1, 1); - } else { - ERR_FAIL_V(p_coords); - } - } - } - } break; - case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: - case TileSet::TILE_LAYOUT_DIAMOND_DOWN: { - if ((tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL)) { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { - return p_coords + Vector2i(1, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(0, 1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { - return p_coords + Vector2i(-1, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(-1, 0); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { - return p_coords + Vector2i(-1, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(0, -1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { - return p_coords + Vector2i(1, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(1, 0); - } else { - ERR_FAIL_V(p_coords); - } - - } else { - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { - return p_coords + Vector2i(1, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(1, 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { - return p_coords + Vector2i(1, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(0, -1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { - return p_coords + Vector2i(-1, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(-1, 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { - return p_coords + Vector2i(-1, 1); - - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(0, 1); - } else { - ERR_FAIL_V(p_coords); - } - } - } else { - if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { - return p_coords + Vector2i(1, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(1, 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { - return p_coords + Vector2i(1, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(0, 1); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { - return p_coords + Vector2i(-1, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(-1, 0); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { - return p_coords + Vector2i(-1, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(0, -1); - } else { - ERR_FAIL_V(p_coords); - } - - } else { - if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { - return p_coords + Vector2i(-1, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { - return p_coords + Vector2i(0, 1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { - return p_coords + Vector2i(1, 1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { - return p_coords + Vector2i(1, 0); - } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || - (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { - return p_coords + Vector2i(1, -1); - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { - return p_coords + Vector2i(0, -1); - } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { - return p_coords + Vector2i(-1, -1); - - } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { - return p_coords + Vector2i(-1, 0); - } else { - ERR_FAIL_V(p_coords); - } - } - } - } break; - default: - ERR_FAIL_V(p_coords); - } - } + ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2i()); + return tile_set->get_neighbor_cell(p_coords, p_cell_neighbor); } TypedArray<Vector2i> TileMap::get_used_cells(int p_layer) const { @@ -4466,7 +953,7 @@ Rect2i TileMap::get_used_rect() const { // Return the visible rect of the tilemap. bool first = true; Rect2i rect = Rect2i(); - for (const Ref<TileMapLayer> &layer : layers) { + for (const TileMapLayer *layer : layers) { Rect2i layer_rect = layer->get_used_rect(); if (layer_rect == Rect2i()) { continue; @@ -4486,7 +973,7 @@ Rect2i TileMap::get_used_rect() const { void TileMap::set_light_mask(int p_light_mask) { // Occlusion: set light mask. CanvasItem::set_light_mask(p_light_mask); - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_LIGHT_MASK); } } @@ -4496,7 +983,7 @@ void TileMap::set_material(const Ref<Material> &p_material) { CanvasItem::set_material(p_material); // Update material for the whole tilemap. - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_MATERIAL); } } @@ -4506,7 +993,7 @@ void TileMap::set_use_parent_material(bool p_use_parent_material) { CanvasItem::set_use_parent_material(p_use_parent_material); // Update use_parent_material for the whole tilemap. - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL); } } @@ -4514,7 +1001,7 @@ void TileMap::set_use_parent_material(bool p_use_parent_material) { void TileMap::set_texture_filter(TextureFilter p_texture_filter) { // Set a default texture filter for the whole tilemap. CanvasItem::set_texture_filter(p_texture_filter); - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER); } } @@ -4522,7 +1009,7 @@ void TileMap::set_texture_filter(TextureFilter p_texture_filter) { void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) { // Set a default texture repeat for the whole tilemap. CanvasItem::set_texture_repeat(p_texture_repeat); - for (Ref<TileMapLayer> &layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT); } } @@ -4621,14 +1108,14 @@ PackedStringArray TileMap::get_configuration_warnings() const { // Retrieve the set of Z index values with a Y-sorted layer. RBSet<int> y_sorted_z_index; - for (const Ref<TileMapLayer> &layer : layers) { + for (const TileMapLayer *layer : layers) { if (layer->is_y_sort_enabled()) { y_sorted_z_index.insert(layer->get_z_index()); } } // Check if we have a non-sorted layer in a Z-index with a Y-sorted layer. - for (const Ref<TileMapLayer> &layer : layers) { + for (const TileMapLayer *layer : layers) { if (!layer->is_y_sort_enabled() && y_sorted_z_index.has(layer->get_z_index())) { warnings.push_back(RTR("A Y-sorted layer has the same Z-index value as a not Y-sorted layer.\nThis may lead to unwanted behaviors, as a layer that is not Y-sorted will be Y-sorted as a whole with tiles from Y-sorted layers.")); break; @@ -4637,7 +1124,7 @@ PackedStringArray TileMap::get_configuration_warnings() const { if (!is_y_sort_enabled()) { // Check if Y-sort is enabled on a layer but not on the node. - for (const Ref<TileMapLayer> &layer : layers) { + for (const TileMapLayer *layer : layers) { if (layer->is_y_sort_enabled()) { warnings.push_back(RTR("A TileMap layer is set as Y-sorted, but Y-sort is not enabled on the TileMap node itself.")); break; @@ -4646,7 +1133,7 @@ PackedStringArray TileMap::get_configuration_warnings() const { } else { // Check if Y-sort is enabled on the node, but not on any of the layers. bool need_warning = true; - for (const Ref<TileMapLayer> &layer : layers) { + for (const TileMapLayer *layer : layers) { if (layer->is_y_sort_enabled()) { need_warning = false; break; @@ -4661,7 +1148,7 @@ PackedStringArray TileMap::get_configuration_warnings() const { if (tile_set.is_valid() && tile_set->get_tile_shape() == TileSet::TILE_SHAPE_ISOMETRIC) { bool warn = !is_y_sort_enabled(); if (!warn) { - for (const Ref<TileMapLayer> &layer : layers) { + for (const TileMapLayer *layer : layers) { if (!layer->is_y_sort_enabled()) { warn = true; break; @@ -4765,7 +1252,7 @@ void TileMap::_bind_methods() { ADD_ARRAY("layers", "layer_"); - ADD_PROPERTY_DEFAULT("format", TileMapLayer::FORMAT_1); + ADD_PROPERTY_DEFAULT("format", TileMapDataFormat::FORMAT_1); ADD_SIGNAL(MethodInfo(CoreStringNames::get_singleton()->changed)); @@ -4776,42 +1263,27 @@ void TileMap::_bind_methods() { void TileMap::_tile_set_changed() { emit_signal(CoreStringNames::get_singleton()->changed); - for (Ref<TileMapLayer> layer : layers) { + for (TileMapLayer *layer : layers) { layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TILE_SET); } update_configuration_warnings(); } -void TileMap::_update_notify_local_transform() { - bool notify = collision_animatable || is_y_sort_enabled(); - if (!notify) { - for (const Ref<TileMapLayer> &layer : layers) { - if (layer->is_y_sort_enabled()) { - notify = true; - break; - } - } - } - set_notify_local_transform(notify); -} - TileMap::TileMap() { - set_notify_transform(true); - _update_notify_local_transform(); - - Ref<TileMapLayer> new_layer; - new_layer.instantiate(); - new_layer->set_tile_map(this); + TileMapLayer *new_layer = memnew(TileMapLayer); + add_child(new_layer); + new_layer->set_name("Layer0"); new_layer->set_layer_index_in_tile_map_node(0); layers.push_back(new_layer); - default_layer.instantiate(); + default_layer = memnew(TileMapLayer); } TileMap::~TileMap() { if (tile_set.is_valid()) { tile_set->disconnect_changed(callable_mp(this, &TileMap::_tile_set_changed)); } + memdelete(default_layer); } #undef TILEMAP_CALL_FOR_LAYER diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 1e4c6d0e66..f2b481cdd1 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -32,406 +32,17 @@ #define TILE_MAP_H #include "scene/2d/node_2d.h" -#include "scene/gui/control.h" #include "scene/resources/tile_set.h" -class TileSetAtlasSource; +class Control; +class TileMapLayer; +class TerrainConstraint; -class TerrainConstraint { -private: - const TileMap *tile_map = nullptr; - Vector2i base_cell_coords; - int bit = -1; - int terrain = -1; - - int priority = 1; - -public: - bool operator<(const TerrainConstraint &p_other) const { - if (base_cell_coords == p_other.base_cell_coords) { - return bit < p_other.bit; - } - return base_cell_coords < p_other.base_cell_coords; - } - - String to_string() const { - return vformat("Constraint {pos:%s, bit:%d, terrain:%d, priority:%d}", base_cell_coords, bit, terrain, priority); - } - - Vector2i get_base_cell_coords() const { - return base_cell_coords; - } - - bool is_center_bit() const { - return bit == 0; - } - - HashMap<Vector2i, TileSet::CellNeighbor> get_overlapping_coords_and_peering_bits() const; - - void set_terrain(int p_terrain) { - terrain = p_terrain; - } - - int get_terrain() const { - return terrain; - } - - void set_priority(int p_priority) { - priority = p_priority; - } - - int get_priority() const { - return priority; - } - - TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, int p_terrain); // For the center terrain bit - TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain); // For peering bits - TerrainConstraint(){}; -}; - -#ifdef DEBUG_ENABLED -class DebugQuadrant; -#endif // DEBUG_ENABLED -class RenderingQuadrant; - -struct CellData { - Vector2i coords; - TileMapCell cell; - - // Debug. - SelfList<CellData> debug_quadrant_list_element; - - // Rendering. - Ref<RenderingQuadrant> rendering_quadrant; - SelfList<CellData> rendering_quadrant_list_element; - LocalVector<RID> occluders; - - // Physics. - LocalVector<RID> bodies; - - // Navigation. - LocalVector<RID> navigation_regions; - - // Scenes. - String scene; - - // Runtime TileData cache. - TileData *runtime_tile_data_cache = nullptr; - - // List elements. - SelfList<CellData> dirty_list_element; - - bool operator<(const CellData &p_other) const { - return coords < p_other.coords; - } - - // For those, copy everything but SelfList elements. - void operator=(const CellData &p_other) { - coords = p_other.coords; - cell = p_other.cell; - occluders = p_other.occluders; - bodies = p_other.bodies; - navigation_regions = p_other.navigation_regions; - scene = p_other.scene; - runtime_tile_data_cache = p_other.runtime_tile_data_cache; - } - - CellData(const CellData &p_other) : - debug_quadrant_list_element(this), - rendering_quadrant_list_element(this), - dirty_list_element(this) { - coords = p_other.coords; - cell = p_other.cell; - occluders = p_other.occluders; - bodies = p_other.bodies; - navigation_regions = p_other.navigation_regions; - scene = p_other.scene; - runtime_tile_data_cache = p_other.runtime_tile_data_cache; - } - - CellData() : - debug_quadrant_list_element(this), - rendering_quadrant_list_element(this), - dirty_list_element(this) { - } -}; - -// For compatibility reasons, we use another comparator for Y-sorted layers. -struct CellDataYSortedComparator { - _FORCE_INLINE_ bool operator()(const CellData &p_a, const CellData &p_b) const { - return p_a.coords.x == p_b.coords.x ? (p_a.coords.y < p_b.coords.y) : (p_a.coords.x > p_b.coords.x); - } -}; - -#ifdef DEBUG_ENABLED -class DebugQuadrant : public RefCounted { - GDCLASS(DebugQuadrant, RefCounted); - -public: - Vector2i quadrant_coords; - SelfList<CellData>::List cells; - RID canvas_item; - - SelfList<DebugQuadrant> dirty_quadrant_list_element; - - // For those, copy everything but SelfList elements. - DebugQuadrant(const DebugQuadrant &p_other) : - dirty_quadrant_list_element(this) { - quadrant_coords = p_other.quadrant_coords; - cells = p_other.cells; - canvas_item = p_other.canvas_item; - } - - DebugQuadrant() : - dirty_quadrant_list_element(this) { - } - - ~DebugQuadrant() { - cells.clear(); - } -}; -#endif // DEBUG_ENABLED - -class RenderingQuadrant : public RefCounted { - GDCLASS(RenderingQuadrant, RefCounted); - -public: - struct CoordsWorldComparator { - _ALWAYS_INLINE_ bool operator()(const Vector2 &p_a, const Vector2 &p_b) const { - // We sort the cells by their local coords, as it is needed by rendering. - if (p_a.y == p_b.y) { - return p_a.x > p_b.x; - } else { - return p_a.y < p_b.y; - } - } - }; - - Vector2i quadrant_coords; - SelfList<CellData>::List cells; - List<RID> canvas_items; - Vector2 canvas_items_position; - - SelfList<RenderingQuadrant> dirty_quadrant_list_element; - - // For those, copy everything but SelfList elements. - RenderingQuadrant(const RenderingQuadrant &p_other) : - dirty_quadrant_list_element(this) { - quadrant_coords = p_other.quadrant_coords; - cells = p_other.cells; - canvas_items = p_other.canvas_items; - } - - RenderingQuadrant() : - dirty_quadrant_list_element(this) { - } - - ~RenderingQuadrant() { - cells.clear(); - } -}; - -class TileMapLayer : public RefCounted { - GDCLASS(TileMapLayer, RefCounted); - -public: - enum DataFormat { - FORMAT_1 = 0, - FORMAT_2, - FORMAT_3, - FORMAT_MAX, - }; - - enum DirtyFlags { - DIRTY_FLAGS_LAYER_ENABLED = 0, - DIRTY_FLAGS_LAYER_MODULATE, - DIRTY_FLAGS_LAYER_Y_SORT_ENABLED, - DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN, - DIRTY_FLAGS_LAYER_Z_INDEX, - DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED, - DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE, - DIRTY_FLAGS_TILE_MAP_IN_TREE, - DIRTY_FLAGS_TILE_MAP_IN_CANVAS, - DIRTY_FLAGS_TILE_MAP_VISIBILITY, - DIRTY_FLAGS_TILE_MAP_XFORM, - DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM, - DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER, - DIRTY_FLAGS_TILE_MAP_LIGHT_MASK, - DIRTY_FLAGS_TILE_MAP_MATERIAL, - DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL, - DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER, - DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT, - DIRTY_FLAGS_TILE_MAP_TILE_SET, - DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE, - DIRTY_FLAGS_TILE_MAP_COLLISION_ANIMATABLE, - DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE, - DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE, - DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED, - DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE, - DIRTY_FLAGS_MAX, - }; - -private: - // Exposed properties. - String name; - bool enabled = true; - Color modulate = Color(1, 1, 1, 1); - bool y_sort_enabled = false; - int y_sort_origin = 0; - int z_index = 0; - bool navigation_enabled = true; - RID navigation_map; - bool uses_world_navigation_map = false; - - // Internal. - TileMap *tile_map_node = nullptr; - int layer_index_in_tile_map_node = -1; - RID canvas_item; - HashMap<Vector2i, CellData> tile_map; - - // Dirty flag. Allows knowing what was modified since the last update. - struct { - bool flags[DIRTY_FLAGS_MAX] = { false }; - SelfList<CellData>::List cell_list; - } dirty; - bool in_destructor = false; - - // Rect cache. - mutable Rect2 rect_cache; - mutable bool rect_cache_dirty = true; - mutable Rect2i used_rect_cache; - mutable bool used_rect_cache_dirty = true; - - // Runtime tile data. - bool _runtime_update_tile_data_was_cleaned_up = false; - void _build_runtime_update_tile_data(); - void _build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list = false); - void _clear_runtime_update_tile_data(); - - // Per-system methods. -#ifdef DEBUG_ENABLED - HashMap<Vector2i, Ref<DebugQuadrant>> debug_quadrant_map; - Vector2i _coords_to_debug_quadrant_coords(const Vector2i &p_coords) const; - bool _debug_was_cleaned_up = false; - void _debug_update(); - void _debug_quadrants_update_cell(CellData &r_cell_data, SelfList<DebugQuadrant>::List &r_dirty_debug_quadrant_list); -#endif // DEBUG_ENABLED - - HashMap<Vector2i, Ref<RenderingQuadrant>> rendering_quadrant_map; - bool _rendering_was_cleaned_up = false; - void _rendering_update(); - void _rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list); - void _rendering_occluders_clear_cell(CellData &r_cell_data); - void _rendering_occluders_update_cell(CellData &r_cell_data); -#ifdef DEBUG_ENABLED - void _rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data); -#endif // DEBUG_ENABLED - - HashMap<RID, Vector2i> bodies_coords; // Mapping for RID to coords. - bool _physics_was_cleaned_up = false; - void _physics_update(); - void _physics_notify_tilemap_change(DirtyFlags p_what); - void _physics_clear_cell(CellData &r_cell_data); - void _physics_update_cell(CellData &r_cell_data); -#ifdef DEBUG_ENABLED - void _physics_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data); -#endif // DEBUG_ENABLED - - bool _navigation_was_cleaned_up = false; - void _navigation_update(); - void _navigation_clear_cell(CellData &r_cell_data); - void _navigation_update_cell(CellData &r_cell_data); -#ifdef DEBUG_ENABLED - void _navigation_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data); -#endif // DEBUG_ENABLED - - bool _scenes_was_cleaned_up = false; - void _scenes_update(); - void _scenes_clear_cell(CellData &r_cell_data); - void _scenes_update_cell(CellData &r_cell_data); -#ifdef DEBUG_ENABLED - void _scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data); -#endif // DEBUG_ENABLED - - // Terrains. - TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern); - RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const; - RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const; - -public: - // TileMap node. - void set_tile_map(TileMap *p_tile_map); - void set_layer_index_in_tile_map_node(int p_index); - - // Rect caching. - Rect2 get_rect(bool &r_changed) const; - - // Terrains. - HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints); // Not exposed. - HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed. - HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed. - HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true); // Not exposed. - - // Not exposed to users. - TileMapCell get_cell(const Vector2i &p_coords, bool p_use_proxies = false) const; - - // For TileMap node's use. - void set_tile_data(DataFormat p_format, const Vector<int> &p_data); - Vector<int> get_tile_data() const; - void notify_tile_map_change(DirtyFlags p_what); - void internal_update(); - - // --- Exposed in TileMap --- - - // Cells manipulation. - void set_cell(const Vector2i &p_coords, int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = 0); - void erase_cell(const Vector2i &p_coords); - - int get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies = false) const; - Vector2i get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies = false) const; - int get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies = false) const; - TileData *get_cell_tile_data(const Vector2i &p_coords, bool p_use_proxies = false) const; // Helper method to make accessing the data easier. - void clear(); - - // Patterns. - Ref<TileMapPattern> get_pattern(TypedArray<Vector2i> p_coords_array); - void set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern); - - // Terrains. - void set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); - void set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); - - // Cells usage. - TypedArray<Vector2i> get_used_cells() const; - TypedArray<Vector2i> get_used_cells_by_id(int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE) const; - Rect2i get_used_rect() const; - - // Layer properties. - void set_name(String p_name); - String get_name() const; - void set_enabled(bool p_enabled); - bool is_enabled() const; - void set_modulate(Color p_modulate); - Color get_modulate() const; - void set_y_sort_enabled(bool p_y_sort_enabled); - bool is_y_sort_enabled() const; - void set_y_sort_origin(int p_y_sort_origin); - int get_y_sort_origin() const; - void set_z_index(int p_z_index); - int get_z_index() const; - void set_navigation_enabled(bool p_enabled); - bool is_navigation_enabled() const; - void set_navigation_map(RID p_map); - RID get_navigation_map() const; - - // Fixing and clearing methods. - void fix_invalid_tiles(); - - // Find coords for body. - bool has_body_rid(RID p_physics_body) const; - Vector2i get_coords_for_body_rid(RID p_physics_body) const; // For finding tiles from collision. - - ~TileMapLayer(); +enum TileMapDataFormat { + FORMAT_1 = 0, + FORMAT_2, + FORMAT_3, + FORMAT_MAX, }; class TileMap : public Node2D { @@ -448,7 +59,7 @@ private: friend class TileSetPlugin; // A compatibility enum to specify how is the data if formatted. - mutable TileMapLayer::DataFormat format = TileMapLayer::FORMAT_3; + mutable TileMapDataFormat format = TileMapDataFormat::FORMAT_3; static constexpr float FP_ADJUST = 0.00001; @@ -460,18 +71,17 @@ private: VisibilityMode navigation_visibility_mode = VISIBILITY_MODE_DEFAULT; // Layers. - LocalVector<Ref<TileMapLayer>> layers; - Ref<TileMapLayer> default_layer; // Dummy layer to fetch default values. + LocalVector<TileMapLayer *> layers; + TileMapLayer *default_layer; // Dummy layer to fetch default values. int selected_layer = -1; bool pending_update = false; + // Transforms for collision_animatable. Transform2D last_valid_transform; Transform2D new_transform; void _tile_set_changed(); - void _update_notify_local_transform(); - protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; @@ -486,6 +96,8 @@ protected: Rect2i _get_used_rect_bind_compat_78328(); void _set_quadrant_size_compat_81070(int p_quadrant_size); int _get_quadrant_size_compat_81070() const; + VisibilityMode _get_collision_visibility_mode_bind_compat_87115(); + VisibilityMode _get_navigation_visibility_mode_bind_compat_87115(); static void _bind_compatibility_methods(); #endif @@ -539,15 +151,15 @@ public: void set_selected_layer(int p_layer_id); // For editor use. int get_selected_layer() const; - void set_collision_animatable(bool p_enabled); + void set_collision_animatable(bool p_collision_animatable); bool is_collision_animatable() const; // Debug visibility modes. void set_collision_visibility_mode(VisibilityMode p_show_collision); - VisibilityMode get_collision_visibility_mode(); + VisibilityMode get_collision_visibility_mode() const; void set_navigation_visibility_mode(VisibilityMode p_show_navigation); - VisibilityMode get_navigation_visibility_mode(); + VisibilityMode get_navigation_visibility_mode() const; // Cells accessors. void set_cell(int p_layer, const Vector2i &p_coords, int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = 0); @@ -581,7 +193,6 @@ public: Vector2 map_to_local(const Vector2i &p_pos) const; Vector2i local_to_map(const Vector2 &p_pos) const; - bool is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const; Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const; diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp new file mode 100644 index 0000000000..df79b3fee6 --- /dev/null +++ b/scene/2d/tile_map_layer.cpp @@ -0,0 +1,2942 @@ +/**************************************************************************/ +/* tile_map_layer.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "tile_map_layer.h" + +#include "core/core_string_names.h" +#include "core/io/marshalls.h" +#include "scene/gui/control.h" +#include "scene/resources/world_2d.h" +#include "servers/navigation_server_2d.h" + +#ifdef DEBUG_ENABLED +#include "servers/navigation_server_3d.h" +#endif // DEBUG_ENABLED + +TileMap *TileMapLayer::_fetch_tilemap() const { + return TileMap::cast_to<TileMap>(get_parent()); +} + +Ref<TileSet> TileMapLayer::_fetch_tileset() const { + TileMap *tile_map_node = _fetch_tilemap(); + if (!tile_map_node) { + return Ref<TileSet>(); + } + return tile_map_node->get_tileset(); +} + +#ifdef DEBUG_ENABLED +/////////////////////////////// Debug ////////////////////////////////////////// +constexpr int TILE_MAP_DEBUG_QUADRANT_SIZE = 16; + +Vector2i TileMapLayer::_coords_to_debug_quadrant_coords(const Vector2i &p_coords) const { + return Vector2i( + p_coords.x > 0 ? p_coords.x / TILE_MAP_DEBUG_QUADRANT_SIZE : (p_coords.x - (TILE_MAP_DEBUG_QUADRANT_SIZE - 1)) / TILE_MAP_DEBUG_QUADRANT_SIZE, + p_coords.y > 0 ? p_coords.y / TILE_MAP_DEBUG_QUADRANT_SIZE : (p_coords.y - (TILE_MAP_DEBUG_QUADRANT_SIZE - 1)) / TILE_MAP_DEBUG_QUADRANT_SIZE); +} + +void TileMapLayer::_debug_update() { + const Ref<TileSet> &tile_set = _fetch_tileset(); + RenderingServer *rs = RenderingServer::get_singleton(); + + // Check if we should cleanup everything. + bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree(); + + if (forced_cleanup) { + for (KeyValue<Vector2i, Ref<DebugQuadrant>> &kv : debug_quadrant_map) { + // Free the quadrant. + Ref<DebugQuadrant> &debug_quadrant = kv.value; + if (debug_quadrant->canvas_item.is_valid()) { + rs->free(debug_quadrant->canvas_item); + } + } + debug_quadrant_map.clear(); + _debug_was_cleaned_up = true; + return; + } + + // Check if anything is dirty, in such a case, redraw debug. + bool anything_changed = false; + for (int i = 0; i < DIRTY_FLAGS_MAX; i++) { + if (dirty.flags[i]) { + anything_changed = true; + break; + } + } + + // List all debug quadrants to update, creating new ones if needed. + SelfList<DebugQuadrant>::List dirty_debug_quadrant_list; + + if (_debug_was_cleaned_up || anything_changed) { + // Update all cells. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + CellData &cell_data = kv.value; + _debug_quadrants_update_cell(cell_data, dirty_debug_quadrant_list); + } + } else { + // Update dirty cells. + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + _debug_quadrants_update_cell(cell_data, dirty_debug_quadrant_list); + } + } + + // Update those quadrants. + for (SelfList<DebugQuadrant> *quadrant_list_element = dirty_debug_quadrant_list.first(); quadrant_list_element;) { + SelfList<DebugQuadrant> *next_quadrant_list_element = quadrant_list_element->next(); // "Hack" to clear the list while iterating. + + DebugQuadrant &debug_quadrant = *quadrant_list_element->self(); + + // Check if the quadrant has a tile. + bool has_a_tile = false; + RID &ci = debug_quadrant.canvas_item; + for (SelfList<CellData> *cell_data_list_element = debug_quadrant.cells.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + if (cell_data.cell.source_id != TileSet::INVALID_SOURCE) { + has_a_tile = true; + break; + } + } + + if (has_a_tile) { + // Update the quadrant. + if (ci.is_valid()) { + rs->canvas_item_clear(ci); + } else { + ci = rs->canvas_item_create(); + rs->canvas_item_set_z_index(ci, RS::CANVAS_ITEM_Z_MAX - 1); + rs->canvas_item_set_parent(ci, get_canvas_item()); + } + + const Vector2 quadrant_pos = tile_set->map_to_local(debug_quadrant.quadrant_coords * TILE_MAP_DEBUG_QUADRANT_SIZE); + Transform2D xform(0, quadrant_pos); + rs->canvas_item_set_transform(ci, xform); + + for (SelfList<CellData> *cell_data_list_element = debug_quadrant.cells.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + if (cell_data.cell.source_id != TileSet::INVALID_SOURCE) { + _rendering_draw_cell_debug(ci, quadrant_pos, cell_data); + _physics_draw_cell_debug(ci, quadrant_pos, cell_data); + _navigation_draw_cell_debug(ci, quadrant_pos, cell_data); + _scenes_draw_cell_debug(ci, quadrant_pos, cell_data); + } + } + } else { + // Free the quadrant. + if (ci.is_valid()) { + rs->free(ci); + } + quadrant_list_element->remove_from_list(); + debug_quadrant_map.erase(debug_quadrant.quadrant_coords); + } + + quadrant_list_element = next_quadrant_list_element; + } + + dirty_debug_quadrant_list.clear(); + + _debug_was_cleaned_up = false; +} + +void TileMapLayer::_debug_quadrants_update_cell(CellData &r_cell_data, SelfList<DebugQuadrant>::List &r_dirty_debug_quadrant_list) { + Vector2i quadrant_coords = _coords_to_debug_quadrant_coords(r_cell_data.coords); + + if (!debug_quadrant_map.has(quadrant_coords)) { + // Create a new quadrant and add it to the quadrant map. + Ref<DebugQuadrant> new_quadrant; + new_quadrant.instantiate(); + new_quadrant->quadrant_coords = quadrant_coords; + debug_quadrant_map[quadrant_coords] = new_quadrant; + } + + // Add the cell to its quadrant, if it is not already in there. + Ref<DebugQuadrant> &debug_quadrant = debug_quadrant_map[quadrant_coords]; + if (!r_cell_data.debug_quadrant_list_element.in_list()) { + debug_quadrant->cells.add(&r_cell_data.debug_quadrant_list_element); + } + + // Mark the quadrant as dirty. + if (!debug_quadrant->dirty_quadrant_list_element.in_list()) { + r_dirty_debug_quadrant_list.add(&debug_quadrant->dirty_quadrant_list_element); + } +} +#endif // DEBUG_ENABLED + +/////////////////////////////// Rendering ////////////////////////////////////// +void TileMapLayer::_rendering_update() { + const TileMap *tile_map_node = _fetch_tilemap(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + RenderingServer *rs = RenderingServer::get_singleton(); + + // Check if we should cleanup everything. + bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree(); + + // ----------- Layer level processing ----------- + if (!forced_cleanup) { + // Update the layer's CanvasItem. + set_use_parent_material(true); + set_light_mask(tile_map_node->get_light_mask()); + + // Modulate the layer. + Color layer_modulate = get_modulate(); + int selected_layer = tile_map_node->get_selected_layer(); + if (selected_layer >= 0 && layer_index_in_tile_map_node != selected_layer) { + int z_selected = tile_map_node->get_layer_z_index(selected_layer); + int layer_z_index = get_z_index(); + if (layer_z_index < z_selected || (layer_z_index == z_selected && layer_index_in_tile_map_node < selected_layer)) { + layer_modulate = layer_modulate.darkened(0.5); + } else if (layer_z_index > z_selected || (layer_z_index == z_selected && layer_index_in_tile_map_node > selected_layer)) { + layer_modulate = layer_modulate.darkened(0.5); + layer_modulate.a *= 0.3; + } + } + rs->canvas_item_set_modulate(get_canvas_item(), layer_modulate); + } + + // ----------- Quadrants processing ----------- + + // List all rendering quadrants to update, creating new ones if needed. + SelfList<RenderingQuadrant>::List dirty_rendering_quadrant_list; + + // Check if anything changed that might change the quadrant shape. + // If so, recreate everything. + bool quandrant_shape_changed = dirty.flags[DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE] || + (is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET])); + + // Free all quadrants. + if (forced_cleanup || quandrant_shape_changed) { + for (const KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) { + for (int i = 0; i < kv.value->canvas_items.size(); i++) { + const RID &ci = kv.value->canvas_items[i]; + if (ci.is_valid()) { + rs->free(ci); + } + } + kv.value->cells.clear(); + } + rendering_quadrant_map.clear(); + _rendering_was_cleaned_up = true; + } + + if (!forced_cleanup) { + // List all quadrants to update, recreating them if needed. + if (dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || _rendering_was_cleaned_up) { + // Update all cells. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + CellData &cell_data = kv.value; + _rendering_quadrants_update_cell(cell_data, dirty_rendering_quadrant_list); + } + } else { + // Update dirty cells. + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + _rendering_quadrants_update_cell(cell_data, dirty_rendering_quadrant_list); + } + } + + // Update all dirty quadrants. + for (SelfList<RenderingQuadrant> *quadrant_list_element = dirty_rendering_quadrant_list.first(); quadrant_list_element;) { + SelfList<RenderingQuadrant> *next_quadrant_list_element = quadrant_list_element->next(); // "Hack" to clear the list while iterating. + + const Ref<RenderingQuadrant> &rendering_quadrant = quadrant_list_element->self(); + + // Check if the quadrant has a tile. + bool has_a_tile = false; + for (SelfList<CellData> *cell_data_list_element = rendering_quadrant->cells.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + if (cell_data.cell.source_id != TileSet::INVALID_SOURCE) { + has_a_tile = true; + break; + } + } + + if (has_a_tile) { + // Process the quadrant. + + // First, clear the quadrant's canvas items. + for (RID &ci : rendering_quadrant->canvas_items) { + rs->free(ci); + } + rendering_quadrant->canvas_items.clear(); + + // Sort the quadrant cells. + if (is_y_sort_enabled()) { + // For compatibility reasons, we use another comparator for Y-sorted layers. + rendering_quadrant->cells.sort_custom<CellDataYSortedComparator>(); + } else { + rendering_quadrant->cells.sort(); + } + + // Those allow to group cell per material or z-index. + Ref<Material> prev_material; + int prev_z_index = 0; + RID prev_ci; + + for (SelfList<CellData> *cell_data_quadrant_list_element = rendering_quadrant->cells.first(); cell_data_quadrant_list_element; cell_data_quadrant_list_element = cell_data_quadrant_list_element->next()) { + CellData &cell_data = *cell_data_quadrant_list_element->self(); + + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(cell_data.cell.source_id)); + + // Get the tile data. + const TileData *tile_data; + if (cell_data.runtime_tile_data_cache) { + tile_data = cell_data.runtime_tile_data_cache; + } else { + tile_data = atlas_source->get_tile_data(cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile); + } + + Ref<Material> mat = tile_data->get_material(); + int tile_z_index = tile_data->get_z_index(); + + // Quandrant pos. + + // --- CanvasItems --- + RID ci; + + // Check if the material or the z_index changed. + if (prev_ci == RID() || prev_material != mat || prev_z_index != tile_z_index) { + // If so, create a new CanvasItem. + ci = rs->canvas_item_create(); + if (mat.is_valid()) { + rs->canvas_item_set_material(ci, mat->get_rid()); + } + rs->canvas_item_set_parent(ci, get_canvas_item()); + rs->canvas_item_set_use_parent_material(ci, true); + + Transform2D xform(0, rendering_quadrant->canvas_items_position); + rs->canvas_item_set_transform(ci, xform); + + rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask()); + rs->canvas_item_set_z_as_relative_to_parent(ci, true); + rs->canvas_item_set_z_index(ci, tile_z_index); + + rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree())); + rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree())); + + rendering_quadrant->canvas_items.push_back(ci); + + prev_ci = ci; + prev_material = mat; + prev_z_index = tile_z_index; + + } else { + // Keep the same canvas_item to draw on. + ci = prev_ci; + } + + const Vector2 local_tile_pos = tile_set->map_to_local(cell_data.coords); + + // Random animation offset. + real_t random_animation_offset = 0.0; + if (atlas_source->get_tile_animation_mode(cell_data.cell.get_atlas_coords()) != TileSetAtlasSource::TILE_ANIMATION_MODE_DEFAULT) { + Array to_hash; + to_hash.push_back(local_tile_pos); + to_hash.push_back(get_instance_id()); // Use instance id as a random hash + random_animation_offset = RandomPCG(to_hash.hash()).randf(); + } + + // Drawing the tile in the canvas item. + TileMap::draw_tile(ci, local_tile_pos - rendering_quadrant->canvas_items_position, tile_set, cell_data.cell.source_id, cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile, -1, get_self_modulate(), tile_data, random_animation_offset); + } + } else { + // Free the quadrant. + for (int i = 0; i < rendering_quadrant->canvas_items.size(); i++) { + const RID &ci = rendering_quadrant->canvas_items[i]; + if (ci.is_valid()) { + rs->free(ci); + } + } + rendering_quadrant->cells.clear(); + rendering_quadrant_map.erase(rendering_quadrant->quadrant_coords); + } + + quadrant_list_element = next_quadrant_list_element; + } + + dirty_rendering_quadrant_list.clear(); + + // Reset the drawing indices. + { + int index = -(int64_t)0x80000000; // Always must be drawn below children. + + // Sort the quadrants coords per local coordinates. + RBMap<Vector2, Ref<RenderingQuadrant>, RenderingQuadrant::CoordsWorldComparator> local_to_map; + for (KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) { + Ref<RenderingQuadrant> &rendering_quadrant = kv.value; + local_to_map[tile_set->map_to_local(rendering_quadrant->quadrant_coords)] = rendering_quadrant; + } + + // Sort the quadrants. + for (const KeyValue<Vector2, Ref<RenderingQuadrant>> &E : local_to_map) { + for (const RID &ci : E.value->canvas_items) { + RS::get_singleton()->canvas_item_set_draw_index(ci, index++); + } + } + } + + // Updates on TileMap changes. + if (dirty.flags[DIRTY_FLAGS_TILE_MAP_LIGHT_MASK] || + dirty.flags[DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL] || + dirty.flags[DIRTY_FLAGS_TILE_MAP_MATERIAL] || + dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER] || + dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT] || + dirty.flags[DIRTY_FLAGS_LAYER_SELF_MODULATE]) { + for (KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) { + Ref<RenderingQuadrant> &rendering_quadrant = kv.value; + for (const RID &ci : rendering_quadrant->canvas_items) { + rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask()); + rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree())); + rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree())); + rs->canvas_item_set_self_modulate(ci, get_self_modulate()); + } + } + } + } + + // ----------- Occluders processing ----------- + if (forced_cleanup) { + // Clean everything. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + _rendering_occluders_clear_cell(kv.value); + } + } else { + if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) { + // Update all cells. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + _rendering_occluders_update_cell(kv.value); + } + } else { + // Update dirty cells. + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + _rendering_occluders_update_cell(cell_data); + } + } + } + + // ----------- + // Mark the rendering state as up to date. + _rendering_was_cleaned_up = forced_cleanup; +} + +void TileMapLayer::_rendering_notification(int p_what) { + RenderingServer *rs = RenderingServer::get_singleton(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (p_what == NOTIFICATION_TRANSFORM_CHANGED || p_what == NOTIFICATION_ENTER_CANVAS || p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (tile_set.is_valid()) { + Transform2D tilemap_xform = get_global_transform(); + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + const CellData &cell_data = kv.value; + for (const RID &occluder : cell_data.occluders) { + if (occluder.is_null()) { + continue; + } + Transform2D xform(0, tile_set->map_to_local(kv.key)); + rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas()); + rs->canvas_light_occluder_set_transform(occluder, tilemap_xform * xform); + } + } + } + } +} + +void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list) { + const TileMap *tile_map_node = _fetch_tilemap(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + + // Check if the cell is valid and retrieve its y_sort_origin. + bool is_valid = false; + int tile_y_sort_origin = 0; + TileSetSource *source; + if (tile_set->has_source(r_cell_data.cell.source_id)) { + source = *tile_set->get_source(r_cell_data.cell.source_id); + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source && atlas_source->has_tile(r_cell_data.cell.get_atlas_coords()) && atlas_source->has_alternative_tile(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile)) { + is_valid = true; + const TileData *tile_data; + if (r_cell_data.runtime_tile_data_cache) { + tile_data = r_cell_data.runtime_tile_data_cache; + } else { + tile_data = atlas_source->get_tile_data(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile); + } + tile_y_sort_origin = tile_data->get_y_sort_origin(); + } + } + + if (is_valid) { + // Get the quadrant coords. + Vector2 canvas_items_position; + Vector2i quadrant_coords; + if (is_y_sort_enabled()) { + canvas_items_position = Vector2(0, tile_set->map_to_local(r_cell_data.coords).y + tile_y_sort_origin + y_sort_origin); + quadrant_coords = canvas_items_position * 100; + } else { + int quad_size = tile_map_node->get_rendering_quadrant_size(); + const Vector2i &coords = r_cell_data.coords; + + // Rounding down, instead of simply rounding towards zero (truncating). + quadrant_coords = Vector2i( + coords.x > 0 ? coords.x / quad_size : (coords.x - (quad_size - 1)) / quad_size, + coords.y > 0 ? coords.y / quad_size : (coords.y - (quad_size - 1)) / quad_size); + canvas_items_position = tile_set->map_to_local(quad_size * quadrant_coords); + } + + Ref<RenderingQuadrant> rendering_quadrant; + if (rendering_quadrant_map.has(quadrant_coords)) { + // Reuse existing rendering quadrant. + rendering_quadrant = rendering_quadrant_map[quadrant_coords]; + } else { + // Create a new rendering quadrant. + rendering_quadrant.instantiate(); + rendering_quadrant->quadrant_coords = quadrant_coords; + rendering_quadrant->canvas_items_position = canvas_items_position; + rendering_quadrant_map[quadrant_coords] = rendering_quadrant; + } + + // Mark the old quadrant as dirty (if it exists). + if (r_cell_data.rendering_quadrant.is_valid()) { + if (!r_cell_data.rendering_quadrant->dirty_quadrant_list_element.in_list()) { + r_dirty_rendering_quadrant_list.add(&r_cell_data.rendering_quadrant->dirty_quadrant_list_element); + } + } + + // Remove the cell from that quadrant. + if (r_cell_data.rendering_quadrant_list_element.in_list()) { + r_cell_data.rendering_quadrant_list_element.remove_from_list(); + } + + // Add the cell to its new quadrant. + r_cell_data.rendering_quadrant = rendering_quadrant; + r_cell_data.rendering_quadrant->cells.add(&r_cell_data.rendering_quadrant_list_element); + + // Add the new quadrant to the dirty quadrant list. + if (!rendering_quadrant->dirty_quadrant_list_element.in_list()) { + r_dirty_rendering_quadrant_list.add(&rendering_quadrant->dirty_quadrant_list_element); + } + } else { + Ref<RenderingQuadrant> rendering_quadrant = r_cell_data.rendering_quadrant; + + // Remove the cell from its quadrant. + r_cell_data.rendering_quadrant = Ref<RenderingQuadrant>(); + if (r_cell_data.rendering_quadrant_list_element.in_list()) { + rendering_quadrant->cells.remove(&r_cell_data.rendering_quadrant_list_element); + } + + if (rendering_quadrant.is_valid()) { + // Add the quadrant to the dirty quadrant list. + if (!rendering_quadrant->dirty_quadrant_list_element.in_list()) { + r_dirty_rendering_quadrant_list.add(&rendering_quadrant->dirty_quadrant_list_element); + } + } + } +} + +void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) { + RenderingServer *rs = RenderingServer::get_singleton(); + + // Free the occluders. + for (const RID &rid : r_cell_data.occluders) { + rs->free(rid); + } + r_cell_data.occluders.clear(); +} + +void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + RenderingServer *rs = RenderingServer::get_singleton(); + + // Free unused occluders then resize the occluders array. + for (uint32_t i = tile_set->get_occlusion_layers_count(); i < r_cell_data.occluders.size(); i++) { + RID occluder_id = r_cell_data.occluders[i]; + if (occluder_id.is_valid()) { + rs->free(occluder_id); + } + } + r_cell_data.occluders.resize(tile_set->get_occlusion_layers_count()); + + TileSetSource *source; + if (tile_set->has_source(r_cell_data.cell.source_id)) { + source = *tile_set->get_source(r_cell_data.cell.source_id); + + if (source->has_tile(r_cell_data.cell.get_atlas_coords()) && source->has_alternative_tile(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile)) { + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + // Get the tile data. + const TileData *tile_data; + if (r_cell_data.runtime_tile_data_cache) { + tile_data = r_cell_data.runtime_tile_data_cache; + } else { + tile_data = atlas_source->get_tile_data(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile); + } + + // Transform flags. + bool flip_h = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H); + bool flip_v = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V); + bool transpose = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE); + + // Create, update or clear occluders. + for (uint32_t occlusion_layer_index = 0; occlusion_layer_index < r_cell_data.occluders.size(); occlusion_layer_index++) { + Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder(occlusion_layer_index); + + RID &occluder = r_cell_data.occluders[occlusion_layer_index]; + + if (occluder_polygon.is_valid()) { + // Create or update occluder. + Transform2D xform; + xform.set_origin(tile_set->map_to_local(r_cell_data.coords)); + if (!occluder.is_valid()) { + occluder = rs->canvas_light_occluder_create(); + } + rs->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform); + rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder(occlusion_layer_index, flip_h, flip_v, transpose)->get_rid()); + rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas()); + rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index)); + } else { + // Clear occluder. + if (occluder.is_valid()) { + rs->free(occluder); + occluder = RID(); + } + } + } + + return; + } + } + } + + // If we did not return earlier, clear the cell. + _rendering_occluders_clear_cell(r_cell_data); +} + +#ifdef DEBUG_ENABLED +void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND(!tile_set.is_valid()); + + if (!Engine::get_singleton()->is_editor_hint()) { + return; + } + + // Draw a placeholder for tiles needing one. + RenderingServer *rs = RenderingServer::get_singleton(); + const TileMapCell &c = r_cell_data.cell; + + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + Vector2i grid_size = atlas_source->get_atlas_grid_size(); + if (!atlas_source->get_runtime_texture().is_valid() || c.get_atlas_coords().x >= grid_size.x || c.get_atlas_coords().y >= grid_size.y) { + // Generate a random color from the hashed values of the tiles. + Array to_hash; + to_hash.push_back(c.source_id); + to_hash.push_back(c.get_atlas_coords()); + to_hash.push_back(c.alternative_tile); + uint32_t hash = RandomPCG(to_hash.hash()).rand(); + + Color color; + color = color.from_hsv( + (float)((hash >> 24) & 0xFF) / 256.0, + Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0), + Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0), + 0.8); + + // Draw a placeholder tile. + Transform2D cell_to_quadrant; + cell_to_quadrant.set_origin(tile_set->map_to_local(r_cell_data.coords) - p_quadrant_pos); + rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant); + rs->canvas_item_add_circle(p_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); + } + } + } + } +} +#endif // DEBUG_ENABLED + +/////////////////////////////// Physics ////////////////////////////////////// + +void TileMapLayer::_physics_update() { + const Ref<TileSet> &tile_set = _fetch_tileset(); + + // Check if we should cleanup everything. + bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid(); + if (forced_cleanup) { + // Clean everything. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + _physics_clear_cell(kv.value); + } + } else { + if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) { + // Update all cells. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + _physics_update_cell(kv.value); + } + } else { + // Update dirty cells. + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + _physics_update_cell(cell_data); + } + } + } + + // ----------- + // Mark the physics state as up to date. + _physics_was_cleaned_up = forced_cleanup; +} + +void TileMapLayer::_physics_notification(int p_what) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + Transform2D gl_transform = get_global_transform(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); + + switch (p_what) { + case NOTIFICATION_TRANSFORM_CHANGED: + // Move the collisison shapes along with the TileMap. + if (is_inside_tree() && tile_set.is_valid()) { + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + const CellData &cell_data = kv.value; + + for (RID body : cell_data.bodies) { + if (body.is_valid()) { + Transform2D xform(0, tile_set->map_to_local(kv.key)); + xform = gl_transform * xform; + ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); + } + } + } + } + break; + case NOTIFICATION_ENTER_TREE: + // Changes in the tree may cause the space to change (e.g. when reparenting to a SubViewport). + if (is_inside_tree()) { + RID space = get_world_2d()->get_space(); + + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + const CellData &cell_data = kv.value; + + for (RID body : cell_data.bodies) { + if (body.is_valid()) { + ps->body_set_space(body, space); + } + } + } + } + } +} + +void TileMapLayer::_physics_clear_cell(CellData &r_cell_data) { + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); + + // Clear bodies. + for (RID body : r_cell_data.bodies) { + if (body.is_valid()) { + bodies_coords.erase(body); + ps->free(body); + } + } + r_cell_data.bodies.clear(); +} + +void TileMapLayer::_physics_update_cell(CellData &r_cell_data) { + const TileMap *tile_map_node = _fetch_tilemap(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + Transform2D gl_transform = get_global_transform(); + RID space = get_world_2d()->get_space(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); + + // Recreate bodies and shapes. + TileMapCell &c = r_cell_data.cell; + + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + const TileData *tile_data; + if (r_cell_data.runtime_tile_data_cache) { + tile_data = r_cell_data.runtime_tile_data_cache; + } else { + tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); + } + + // Transform flags. + bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H); + bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V); + bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE); + + // Free unused bodies then resize the bodies array. + for (uint32_t i = tile_set->get_physics_layers_count(); i < r_cell_data.bodies.size(); i++) { + RID &body = r_cell_data.bodies[i]; + if (body.is_valid()) { + bodies_coords.erase(body); + ps->free(body); + body = RID(); + } + } + r_cell_data.bodies.resize(tile_set->get_physics_layers_count()); + + for (uint32_t tile_set_physics_layer = 0; tile_set_physics_layer < (uint32_t)tile_set->get_physics_layers_count(); tile_set_physics_layer++) { + Ref<PhysicsMaterial> physics_material = tile_set->get_physics_layer_physics_material(tile_set_physics_layer); + uint32_t physics_layer = tile_set->get_physics_layer_collision_layer(tile_set_physics_layer); + uint32_t physics_mask = tile_set->get_physics_layer_collision_mask(tile_set_physics_layer); + + RID body = r_cell_data.bodies[tile_set_physics_layer]; + if (tile_data->get_collision_polygons_count(tile_set_physics_layer) == 0) { + // No body needed, free it if it exists. + if (body.is_valid()) { + bodies_coords.erase(body); + ps->free(body); + } + body = RID(); + } else { + // Create or update the body. + if (!body.is_valid()) { + body = ps->body_create(); + } + bodies_coords[body] = r_cell_data.coords; + ps->body_set_mode(body, tile_map_node->is_collision_animatable() ? PhysicsServer2D::BODY_MODE_KINEMATIC : PhysicsServer2D::BODY_MODE_STATIC); + ps->body_set_space(body, space); + + Transform2D xform; + xform.set_origin(tile_set->map_to_local(r_cell_data.coords)); + xform = gl_transform * xform; + ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); + + ps->body_attach_object_instance_id(body, tile_map_node->get_instance_id()); + ps->body_set_collision_layer(body, physics_layer); + ps->body_set_collision_mask(body, physics_mask); + ps->body_set_pickable(body, false); + ps->body_set_state(body, PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, tile_data->get_constant_linear_velocity(tile_set_physics_layer)); + ps->body_set_state(body, PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, tile_data->get_constant_angular_velocity(tile_set_physics_layer)); + + if (!physics_material.is_valid()) { + ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_BOUNCE, 0); + ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_FRICTION, 1); + } else { + ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material->computed_bounce()); + ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_FRICTION, physics_material->computed_friction()); + } + + // Clear body's shape if needed. + ps->body_clear_shapes(body); + + // Add the shapes to the body. + int body_shape_index = 0; + for (int polygon_index = 0; polygon_index < tile_data->get_collision_polygons_count(tile_set_physics_layer); polygon_index++) { + // Iterate over the polygons. + bool one_way_collision = tile_data->is_collision_polygon_one_way(tile_set_physics_layer, polygon_index); + float one_way_collision_margin = tile_data->get_collision_polygon_one_way_margin(tile_set_physics_layer, polygon_index); + int shapes_count = tile_data->get_collision_polygon_shapes_count(tile_set_physics_layer, polygon_index); + for (int shape_index = 0; shape_index < shapes_count; shape_index++) { + // Add decomposed convex shapes. + Ref<ConvexPolygonShape2D> shape = tile_data->get_collision_polygon_shape(tile_set_physics_layer, polygon_index, shape_index, flip_h, flip_v, transpose); + ps->body_add_shape(body, shape->get_rid()); + ps->body_set_shape_as_one_way_collision(body, body_shape_index, one_way_collision, one_way_collision_margin); + + body_shape_index++; + } + } + } + + // Set the body again. + r_cell_data.bodies[tile_set_physics_layer] = body; + } + + return; + } + } + } + + // If we did not return earlier, clear the cell. + _physics_clear_cell(r_cell_data); +} + +#ifdef DEBUG_ENABLED +void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) { + // Draw the debug collision shapes. + TileMap *tile_map_node = _fetch_tilemap(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND(!tile_set.is_valid()); + + if (!get_tree()) { + return; + } + + bool show_collision = false; + switch (tile_map_node->get_collision_visibility_mode()) { + case TileMap::VISIBILITY_MODE_DEFAULT: + show_collision = !Engine::get_singleton()->is_editor_hint() && get_tree()->is_debugging_collisions_hint(); + break; + case TileMap::VISIBILITY_MODE_FORCE_HIDE: + show_collision = false; + break; + case TileMap::VISIBILITY_MODE_FORCE_SHOW: + show_collision = true; + break; + } + if (!show_collision) { + return; + } + + RenderingServer *rs = RenderingServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); + + Color debug_collision_color = get_tree()->get_debug_collisions_color(); + Vector<Color> color; + color.push_back(debug_collision_color); + + Transform2D quadrant_to_local(0, p_quadrant_pos); + Transform2D global_to_quadrant = (get_global_transform() * quadrant_to_local).affine_inverse(); + + for (RID body : r_cell_data.bodies) { + if (body.is_valid()) { + Transform2D body_to_quadrant = global_to_quadrant * Transform2D(ps->body_get_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM)); + rs->canvas_item_add_set_transform(p_canvas_item, body_to_quadrant); + for (int shape_index = 0; shape_index < ps->body_get_shape_count(body); shape_index++) { + const RID &shape = ps->body_get_shape(body, shape_index); + const PhysicsServer2D::ShapeType &type = ps->shape_get_type(shape); + if (type == PhysicsServer2D::SHAPE_CONVEX_POLYGON) { + rs->canvas_item_add_polygon(p_canvas_item, ps->shape_get_data(shape), color); + } else { + WARN_PRINT("Wrong shape type for a tile, should be SHAPE_CONVEX_POLYGON."); + } + } + rs->canvas_item_add_set_transform(p_canvas_item, Transform2D()); + } + } +}; +#endif // DEBUG_ENABLED + +/////////////////////////////// Navigation ////////////////////////////////////// + +void TileMapLayer::_navigation_update() { + ERR_FAIL_NULL(NavigationServer2D::get_singleton()); + const Ref<TileSet> &tile_set = _fetch_tileset(); + NavigationServer2D *ns = NavigationServer2D::get_singleton(); + + // Check if we should cleanup everything. + bool forced_cleanup = in_destructor || !enabled || !navigation_enabled || !is_inside_tree() || !tile_set.is_valid(); + + // ----------- Layer level processing ----------- + if (forced_cleanup) { + if (navigation_map.is_valid() && !uses_world_navigation_map) { + ns->free(navigation_map); + navigation_map = RID(); + } + } else { + // Update navigation maps. + if (!navigation_map.is_valid()) { + if (layer_index_in_tile_map_node == 0) { + // Use the default World2D navigation map for the first layer when empty. + navigation_map = get_world_2d()->get_navigation_map(); + uses_world_navigation_map = true; + } else { + RID new_layer_map = ns->map_create(); + // Set the default NavigationPolygon cell_size on the new map as a mismatch causes an error. + ns->map_set_cell_size(new_layer_map, 1.0); + ns->map_set_active(new_layer_map, true); + navigation_map = new_layer_map; + uses_world_navigation_map = false; + } + } + } + + // ----------- Navigation regions processing ----------- + if (forced_cleanup) { + // Clean everything. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + _navigation_clear_cell(kv.value); + } + } else { + if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) { + // Update all cells. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + _navigation_update_cell(kv.value); + } + } else { + // Update dirty cells. + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + _navigation_update_cell(cell_data); + } + } + } + + // ----------- + // Mark the navigation state as up to date. + _navigation_was_cleaned_up = forced_cleanup; +} + +void TileMapLayer::_navigation_notification(int p_what) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + if (tile_set.is_valid()) { + Transform2D tilemap_xform = get_global_transform(); + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + const CellData &cell_data = kv.value; + // Update navigation regions transform. + for (const RID ®ion : cell_data.navigation_regions) { + if (!region.is_valid()) { + continue; + } + Transform2D tile_transform; + tile_transform.set_origin(tile_set->map_to_local(kv.key)); + NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform); + } + } + } + } +} + +void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) { + NavigationServer2D *ns = NavigationServer2D::get_singleton(); + // Clear navigation shapes. + for (uint32_t i = 0; i < r_cell_data.navigation_regions.size(); i++) { + const RID ®ion = r_cell_data.navigation_regions[i]; + if (region.is_valid()) { + ns->region_set_map(region, RID()); + ns->free(region); + } + } + r_cell_data.navigation_regions.clear(); +} + +void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) { + const TileMap *tile_map_node = _fetch_tilemap(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + NavigationServer2D *ns = NavigationServer2D::get_singleton(); + Transform2D gl_xform = get_global_transform(); + + // Get the navigation polygons and create regions. + TileMapCell &c = r_cell_data.cell; + + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + const TileData *tile_data; + if (r_cell_data.runtime_tile_data_cache) { + tile_data = r_cell_data.runtime_tile_data_cache; + } else { + tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); + } + + // Transform flags. + bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H); + bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V); + bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE); + + // Free unused regions then resize the regions array. + for (uint32_t i = tile_set->get_navigation_layers_count(); i < r_cell_data.navigation_regions.size(); i++) { + RID ®ion = r_cell_data.navigation_regions[i]; + if (region.is_valid()) { + ns->region_set_map(region, RID()); + ns->free(region); + region = RID(); + } + } + r_cell_data.navigation_regions.resize(tile_set->get_navigation_layers_count()); + + // Create, update or clear regions. + for (uint32_t navigation_layer_index = 0; navigation_layer_index < r_cell_data.navigation_regions.size(); navigation_layer_index++) { + Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(navigation_layer_index, flip_h, flip_v, transpose); + + RID ®ion = r_cell_data.navigation_regions[navigation_layer_index]; + + if (navigation_polygon.is_valid() && (navigation_polygon->get_polygon_count() > 0 || navigation_polygon->get_outline_count() > 0)) { + // Create or update regions. + Transform2D tile_transform; + tile_transform.set_origin(tile_set->map_to_local(r_cell_data.coords)); + if (!region.is_valid()) { + region = ns->region_create(); + } + ns->region_set_owner_id(region, tile_map_node->get_instance_id()); + ns->region_set_map(region, navigation_map); + ns->region_set_transform(region, gl_xform * tile_transform); + ns->region_set_navigation_layers(region, tile_set->get_navigation_layer_layers(navigation_layer_index)); + ns->region_set_navigation_polygon(region, navigation_polygon); + } else { + // Clear region. + if (region.is_valid()) { + ns->region_set_map(region, RID()); + ns->free(region); + region = RID(); + } + } + } + + return; + } + } + } + + // If we did not return earlier, clear the cell. + _navigation_clear_cell(r_cell_data); +} + +#ifdef DEBUG_ENABLED +void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) { + // Draw the debug collision shapes. + const TileMap *tile_map_node = _fetch_tilemap(); + bool show_navigation = false; + switch (tile_map_node->get_navigation_visibility_mode()) { + case TileMap::VISIBILITY_MODE_DEFAULT: + show_navigation = !Engine::get_singleton()->is_editor_hint() && get_tree()->is_debugging_navigation_hint(); + break; + case TileMap::VISIBILITY_MODE_FORCE_HIDE: + show_navigation = false; + break; + case TileMap::VISIBILITY_MODE_FORCE_SHOW: + show_navigation = true; + break; + } + if (!show_navigation) { + return; + } + + // Check if the navigation is used. + if (r_cell_data.navigation_regions.is_empty()) { + return; + } + + const Ref<TileSet> &tile_set = _fetch_tileset(); + + RenderingServer *rs = RenderingServer::get_singleton(); + const NavigationServer2D *ns2d = NavigationServer2D::get_singleton(); + + bool enabled_geometry_face_random_color = ns2d->get_debug_navigation_enable_geometry_face_random_color(); + bool enabled_edge_lines = ns2d->get_debug_navigation_enable_edge_lines(); + + Color debug_face_color = ns2d->get_debug_navigation_geometry_face_color(); + Color debug_edge_color = ns2d->get_debug_navigation_geometry_edge_color(); + + RandomPCG rand; + + const TileMapCell &c = r_cell_data.cell; + + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + const TileData *tile_data; + if (r_cell_data.runtime_tile_data_cache) { + tile_data = r_cell_data.runtime_tile_data_cache; + } else { + tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); + } + + Transform2D cell_to_quadrant; + cell_to_quadrant.set_origin(tile_set->map_to_local(r_cell_data.coords) - p_quadrant_pos); + rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant); + + for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) { + bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H); + bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V); + bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE); + Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(layer_index, flip_h, flip_v, transpose); + if (navigation_polygon.is_valid()) { + Vector<Vector2> navigation_polygon_vertices = navigation_polygon->get_vertices(); + if (navigation_polygon_vertices.size() < 3) { + continue; + } + + for (int i = 0; i < navigation_polygon->get_polygon_count(); i++) { + // An array of vertices for this polygon. + Vector<int> polygon = navigation_polygon->get_polygon(i); + Vector<Vector2> debug_polygon_vertices; + debug_polygon_vertices.resize(polygon.size()); + for (int j = 0; j < polygon.size(); j++) { + ERR_FAIL_INDEX(polygon[j], navigation_polygon_vertices.size()); + debug_polygon_vertices.write[j] = navigation_polygon_vertices[polygon[j]]; + } + + // Generate the polygon color, slightly randomly modified from the settings one. + Color random_variation_color = debug_face_color; + if (enabled_geometry_face_random_color) { + random_variation_color.set_hsv( + debug_face_color.get_h() + rand.random(-1.0, 1.0) * 0.1, + debug_face_color.get_s(), + debug_face_color.get_v() + rand.random(-1.0, 1.0) * 0.2); + } + random_variation_color.a = debug_face_color.a; + + Vector<Color> debug_face_colors; + debug_face_colors.push_back(random_variation_color); + rs->canvas_item_add_polygon(p_canvas_item, debug_polygon_vertices, debug_face_colors); + + if (enabled_edge_lines) { + Vector<Color> debug_edge_colors; + debug_edge_colors.push_back(debug_edge_color); + debug_polygon_vertices.push_back(debug_polygon_vertices[0]); // Add first again for closing polyline. + rs->canvas_item_add_polyline(p_canvas_item, debug_polygon_vertices, debug_edge_colors); + } + } + } + } + } + } + } +} +#endif // DEBUG_ENABLED + +/////////////////////////////// Scenes ////////////////////////////////////// + +void TileMapLayer::_scenes_update() { + const Ref<TileSet> &tile_set = _fetch_tileset(); + + // Check if we should cleanup everything. + bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid(); + + if (forced_cleanup) { + // Clean everything. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + _scenes_clear_cell(kv.value); + } + } else { + if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) { + // Update all cells. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + _scenes_update_cell(kv.value); + } + } else { + // Update dirty cells. + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + _scenes_update_cell(cell_data); + } + } + } + + // ----------- + // Mark the scenes state as up to date. + _scenes_was_cleaned_up = forced_cleanup; +} + +void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) { + const TileMap *tile_map_node = _fetch_tilemap(); + if (!tile_map_node) { + return; + } + + // Cleanup existing scene. + Node *node = tile_map_node->get_node_or_null(r_cell_data.scene); + if (node) { + node->queue_free(); + } + r_cell_data.scene = ""; +} + +void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) { + TileMap *tile_map_node = _fetch_tilemap(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + + // Clear the scene in any case. + _scenes_clear_cell(r_cell_data); + + // Create the scene. + const TileMapCell &c = r_cell_data.cell; + + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + if (scenes_collection_source) { + Ref<PackedScene> packed_scene = scenes_collection_source->get_scene_tile_scene(c.alternative_tile); + if (packed_scene.is_valid()) { + Node *scene = packed_scene->instantiate(); + Control *scene_as_control = Object::cast_to<Control>(scene); + Node2D *scene_as_node2d = Object::cast_to<Node2D>(scene); + if (scene_as_control) { + scene_as_control->set_position(tile_set->map_to_local(r_cell_data.coords) + scene_as_control->get_position()); + } else if (scene_as_node2d) { + Transform2D xform; + xform.set_origin(tile_set->map_to_local(r_cell_data.coords)); + scene_as_node2d->set_transform(xform * scene_as_node2d->get_transform()); + } + tile_map_node->add_child(scene); + r_cell_data.scene = scene->get_name(); + } + } + } + } +} + +#ifdef DEBUG_ENABLED +void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND(!tile_set.is_valid()); + + if (!Engine::get_singleton()->is_editor_hint()) { + return; + } + + // Draw a placeholder for scenes needing one. + RenderingServer *rs = RenderingServer::get_singleton(); + + const TileMapCell &c = r_cell_data.cell; + + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + return; + } + + TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + if (scenes_collection_source) { + if (!scenes_collection_source->get_scene_tile_scene(c.alternative_tile).is_valid() || scenes_collection_source->get_scene_tile_display_placeholder(c.alternative_tile)) { + // Generate a random color from the hashed values of the tiles. + Array to_hash; + to_hash.push_back(c.source_id); + to_hash.push_back(c.alternative_tile); + uint32_t hash = RandomPCG(to_hash.hash()).rand(); + + Color color; + color = color.from_hsv( + (float)((hash >> 24) & 0xFF) / 256.0, + Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0), + Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0), + 0.8); + + // Draw a placeholder tile. + Transform2D cell_to_quadrant; + cell_to_quadrant.set_origin(tile_set->map_to_local(r_cell_data.coords) - p_quadrant_pos); + rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant); + rs->canvas_item_add_circle(p_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); + } + } + } +} +#endif // DEBUG_ENABLED + +///////////////////////////////////////////////////////////////////// + +void TileMapLayer::_build_runtime_update_tile_data() { + const TileMap *tile_map_node = _fetch_tilemap(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + + // Check if we should cleanup everything. + bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree(); + if (!forced_cleanup) { + if (tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_use_tile_data_runtime_update) && tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_tile_data_runtime_update)) { + if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) { + for (KeyValue<Vector2i, CellData> &E : tile_map) { + _build_runtime_update_tile_data_for_cell(E.value); + } + } else if (dirty.flags[DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE]) { + for (KeyValue<Vector2i, CellData> &E : tile_map) { + _build_runtime_update_tile_data_for_cell(E.value, true); + } + } else { + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + _build_runtime_update_tile_data_for_cell(cell_data); + } + } + } + } + + // ----------- + // Mark the navigation state as up to date. + _runtime_update_tile_data_was_cleaned_up = forced_cleanup; +} + +void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list) { + TileMap *tile_map_node = _fetch_tilemap(); + const Ref<TileSet> &tile_set = _fetch_tileset(); + + TileMapCell &c = r_cell_data.cell; + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (source->has_tile(c.get_atlas_coords()) && source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + bool ret = false; + if (tile_map_node->GDVIRTUAL_CALL(_use_tile_data_runtime_update, layer_index_in_tile_map_node, r_cell_data.coords, ret) && ret) { + TileData *tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile); + + // Create the runtime TileData. + TileData *tile_data_runtime_use = tile_data->duplicate(); + tile_data_runtime_use->set_allow_transform(true); + r_cell_data.runtime_tile_data_cache = tile_data_runtime_use; + + tile_map_node->GDVIRTUAL_CALL(_tile_data_runtime_update, layer_index_in_tile_map_node, r_cell_data.coords, tile_data_runtime_use); + + if (p_auto_add_to_dirty_list) { + dirty.cell_list.add(&r_cell_data.dirty_list_element); + } + } + } + } + } +} + +void TileMapLayer::_clear_runtime_update_tile_data() { + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + + // Clear the runtime tile data. + if (cell_data.runtime_tile_data_cache) { + memdelete(cell_data.runtime_tile_data_cache); + cell_data.runtime_tile_data_cache = nullptr; + } + } +} + +TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (!tile_set.is_valid()) { + return TileSet::TerrainsPattern(); + } + // Returns all tiles compatible with the given constraints. + RBMap<TileSet::TerrainsPattern, int> terrain_pattern_score; + RBSet<TileSet::TerrainsPattern> pattern_set = tile_set->get_terrains_pattern_set(p_terrain_set); + ERR_FAIL_COND_V(pattern_set.is_empty(), TileSet::TerrainsPattern()); + for (TileSet::TerrainsPattern &terrain_pattern : pattern_set) { + int score = 0; + + // Check the center bit constraint. + TerrainConstraint terrain_constraint = TerrainConstraint(tile_set, p_position, terrain_pattern.get_terrain()); + const RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_constraint); + if (in_set_constraint_element) { + if (in_set_constraint_element->get().get_terrain() != terrain_constraint.get_terrain()) { + score += in_set_constraint_element->get().get_priority(); + } + } else if (p_current_pattern.get_terrain() != terrain_pattern.get_terrain()) { + continue; // Ignore a pattern that cannot keep bits without constraints unmodified. + } + + // Check the surrounding bits + bool invalid_pattern = false; + for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { + TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); + if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { + // Check if the bit is compatible with the constraints. + TerrainConstraint terrain_bit_constraint = TerrainConstraint(tile_set, p_position, bit, terrain_pattern.get_terrain_peering_bit(bit)); + in_set_constraint_element = p_constraints.find(terrain_bit_constraint); + if (in_set_constraint_element) { + if (in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) { + score += in_set_constraint_element->get().get_priority(); + } + } else if (p_current_pattern.get_terrain_peering_bit(bit) != terrain_pattern.get_terrain_peering_bit(bit)) { + invalid_pattern = true; // Ignore a pattern that cannot keep bits without constraints unmodified. + break; + } + } + } + if (invalid_pattern) { + continue; + } + + terrain_pattern_score[terrain_pattern] = score; + } + + // Compute the minimum score. + TileSet::TerrainsPattern min_score_pattern = p_current_pattern; + int min_score = INT32_MAX; + for (KeyValue<TileSet::TerrainsPattern, int> E : terrain_pattern_score) { + if (E.value < min_score) { + min_score_pattern = E.key; + min_score = E.value; + } + } + + return min_score_pattern; +} + +RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const { + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (!tile_set.is_valid()) { + return RBSet<TerrainConstraint>(); + } + + // Compute the constraints needed from the surrounding tiles. + RBSet<TerrainConstraint> output; + output.insert(TerrainConstraint(tile_set, p_position, p_terrains_pattern.get_terrain())); + + for (uint32_t i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { + TileSet::CellNeighbor side = TileSet::CellNeighbor(i); + if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, side)) { + TerrainConstraint c = TerrainConstraint(tile_set, p_position, side, p_terrains_pattern.get_terrain_peering_bit(side)); + output.insert(c); + } + } + + return output; +} + +RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const { + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (!tile_set.is_valid()) { + return RBSet<TerrainConstraint>(); + } + + ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), RBSet<TerrainConstraint>()); + + // Build a set of dummy constraints to get the constrained points. + RBSet<TerrainConstraint> dummy_constraints; + for (const Vector2i &E : p_painted) { + for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { // Iterates over neighbor bits. + TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); + if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { + dummy_constraints.insert(TerrainConstraint(tile_set, E, bit, -1)); + } + } + } + + // For each constrained point, we get all overlapping tiles, and select the most adequate terrain for it. + RBSet<TerrainConstraint> constraints; + for (const TerrainConstraint &E_constraint : dummy_constraints) { + HashMap<int, int> terrain_count; + + // Count the number of occurrences per terrain. + HashMap<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = E_constraint.get_overlapping_coords_and_peering_bits(); + for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_overlapping : overlapping_terrain_bits) { + TileData *neighbor_tile_data = nullptr; + TileMapCell neighbor_cell = get_cell(E_overlapping.key); + if (neighbor_cell.source_id != TileSet::INVALID_SOURCE) { + Ref<TileSetSource> source = tile_set->get_source(neighbor_cell.source_id); + Ref<TileSetAtlasSource> atlas_source = source; + if (atlas_source.is_valid()) { + TileData *tile_data = atlas_source->get_tile_data(neighbor_cell.get_atlas_coords(), neighbor_cell.alternative_tile); + if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { + neighbor_tile_data = tile_data; + } + } + } + + int terrain = neighbor_tile_data ? neighbor_tile_data->get_terrain_peering_bit(TileSet::CellNeighbor(E_overlapping.value)) : -1; + if (!p_ignore_empty_terrains || terrain >= 0) { + if (!terrain_count.has(terrain)) { + terrain_count[terrain] = 0; + } + terrain_count[terrain] += 1; + } + } + + // Get the terrain with the max number of occurrences. + int max = 0; + int max_terrain = -1; + for (const KeyValue<int, int> &E_terrain_count : terrain_count) { + if (E_terrain_count.value > max) { + max = E_terrain_count.value; + max_terrain = E_terrain_count.key; + } + } + + // Set the adequate terrain. + if (max > 0) { + TerrainConstraint c = E_constraint; + c.set_terrain(max_terrain); + constraints.insert(c); + } + } + + // Add the centers as constraints. + for (Vector2i E_coords : p_painted) { + TileData *tile_data = nullptr; + TileMapCell cell = get_cell(E_coords); + if (cell.source_id != TileSet::INVALID_SOURCE) { + Ref<TileSetSource> source = tile_set->get_source(cell.source_id); + Ref<TileSetAtlasSource> atlas_source = source; + if (atlas_source.is_valid()) { + tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); + } + } + + int terrain = (tile_data && tile_data->get_terrain_set() == p_terrain_set) ? tile_data->get_terrain() : -1; + if (!p_ignore_empty_terrains || terrain >= 0) { + constraints.insert(TerrainConstraint(tile_set, E_coords, terrain)); + } + } + + return constraints; +} + +void TileMapLayer::_renamed() { + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); +} + +void TileMapLayer::_update_notify_local_transform() { + TileMap *tile_map_node = _fetch_tilemap(); + bool notify = tile_map_node->is_collision_animatable() || is_y_sort_enabled(); + if (!notify) { + if (is_y_sort_enabled()) { + notify = true; + } + } + set_notify_local_transform(notify); +} + +void TileMapLayer::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_POSTINITIALIZE: { + connect(SNAME("renamed"), callable_mp(this, &TileMapLayer::_renamed)); + break; + } + case NOTIFICATION_ENTER_TREE: { + _update_notify_local_transform(); + dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + } break; + + case NOTIFICATION_EXIT_TREE: { + dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + } break; + + case TileMap::NOTIFICATION_ENTER_CANVAS: { + dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + } break; + + case TileMap::NOTIFICATION_EXIT_CANVAS: { + dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + } break; + + case TileMap::NOTIFICATION_VISIBILITY_CHANGED: { + dirty.flags[DIRTY_FLAGS_LAYER_VISIBILITY] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + } break; + } + + _rendering_notification(p_what); + _physics_notification(p_what); + _navigation_notification(p_what); +} + +void TileMapLayer::set_layer_index_in_tile_map_node(int p_index) { + if (p_index == layer_index_in_tile_map_node) { + return; + } + TileMap *tile_map_node = _fetch_tilemap(); + layer_index_in_tile_map_node = p_index; + dirty.flags[DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE] = true; + tile_map_node->queue_internal_update(); +} + +Rect2 TileMapLayer::get_rect(bool &r_changed) const { + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (tile_set.is_null()) { + r_changed = rect_cache != Rect2(); + return Rect2(); + } + + // Compute the displayed area of the tilemap. + r_changed = false; +#ifdef DEBUG_ENABLED + + if (rect_cache_dirty) { + Rect2 r_total; + bool first = true; + for (const KeyValue<Vector2i, CellData> &E : tile_map) { + Rect2 r; + r.position = tile_set->map_to_local(E.key); + r.size = Size2(); + if (first) { + r_total = r; + first = false; + } else { + r_total = r_total.merge(r); + } + } + + r_changed = rect_cache != r_total; + + rect_cache = r_total; + rect_cache_dirty = false; + } +#endif + return rect_cache; +} + +HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (!tile_set.is_valid()) { + return HashMap<Vector2i, TileSet::TerrainsPattern>(); + } + + // Copy the constraints set. + RBSet<TerrainConstraint> constraints = p_constraints; + + // Output map. + HashMap<Vector2i, TileSet::TerrainsPattern> output; + + // Add all positions to a set. + for (int i = 0; i < p_to_replace.size(); i++) { + const Vector2i &coords = p_to_replace[i]; + + // Select the best pattern for the given constraints. + TileSet::TerrainsPattern current_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); + TileMapCell cell = get_cell(coords); + if (cell.source_id != TileSet::INVALID_SOURCE) { + TileSetSource *source = *tile_set->get_source(cell.source_id); + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + // Get tile data. + TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); + if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { + current_pattern = tile_data->get_terrains_pattern(); + } + } + } + TileSet::TerrainsPattern pattern = _get_best_terrain_pattern_for_constraints(p_terrain_set, coords, constraints, current_pattern); + + // Update the constraint set with the new ones. + RBSet<TerrainConstraint> new_constraints = _get_terrain_constraints_from_added_pattern(coords, p_terrain_set, pattern); + for (const TerrainConstraint &E_constraint : new_constraints) { + if (constraints.has(E_constraint)) { + constraints.erase(E_constraint); + } + TerrainConstraint c = E_constraint; + c.set_priority(5); + constraints.insert(c); + } + + output[coords] = pattern; + } + return output; +} + +HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) { + HashMap<Vector2i, TileSet::TerrainsPattern> output; + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND_V(!tile_set.is_valid(), output); + ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output); + + // Build list and set of tiles that can be modified (painted and their surroundings). + Vector<Vector2i> can_modify_list; + RBSet<Vector2i> can_modify_set; + RBSet<Vector2i> painted_set; + for (int i = p_coords_array.size() - 1; i >= 0; i--) { + const Vector2i &coords = p_coords_array[i]; + can_modify_list.push_back(coords); + can_modify_set.insert(coords); + painted_set.insert(coords); + } + for (Vector2i coords : p_coords_array) { + // Find the adequate neighbor. + for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { + TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); + if (tile_set->is_existing_neighbor(bit)) { + Vector2i neighbor = tile_set->get_neighbor_cell(coords, bit); + if (!can_modify_set.has(neighbor)) { + can_modify_list.push_back(neighbor); + can_modify_set.insert(neighbor); + } + } + } + } + + // Build a set, out of the possibly modified tiles, of the one with a center bit that is set (or will be) to the painted terrain. + RBSet<Vector2i> cells_with_terrain_center_bit; + for (Vector2i coords : can_modify_set) { + bool connect = false; + if (painted_set.has(coords)) { + connect = true; + } else { + // Get the center bit of the cell. + TileData *tile_data = nullptr; + TileMapCell cell = get_cell(coords); + if (cell.source_id != TileSet::INVALID_SOURCE) { + Ref<TileSetSource> source = tile_set->get_source(cell.source_id); + Ref<TileSetAtlasSource> atlas_source = source; + if (atlas_source.is_valid()) { + tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); + } + } + + if (tile_data && tile_data->get_terrain_set() == p_terrain_set && tile_data->get_terrain() == p_terrain) { + connect = true; + } + } + if (connect) { + cells_with_terrain_center_bit.insert(coords); + } + } + + RBSet<TerrainConstraint> constraints; + + // Add new constraints from the path drawn. + for (Vector2i coords : p_coords_array) { + // Constraints on the center bit. + TerrainConstraint c = TerrainConstraint(tile_set, coords, p_terrain); + c.set_priority(10); + constraints.insert(c); + + // Constraints on the connecting bits. + for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { + TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); + if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { + c = TerrainConstraint(tile_set, coords, bit, p_terrain); + c.set_priority(10); + if ((int(bit) % 2) == 0) { + // Side peering bits: add the constraint if the center is of the same terrain. + Vector2i neighbor = tile_set->get_neighbor_cell(coords, bit); + if (cells_with_terrain_center_bit.has(neighbor)) { + constraints.insert(c); + } + } else { + // Corner peering bits: add the constraint if all tiles on the constraint has the same center bit. + HashMap<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits(); + bool valid = true; + for (KeyValue<Vector2i, TileSet::CellNeighbor> kv : overlapping_terrain_bits) { + if (!cells_with_terrain_center_bit.has(kv.key)) { + valid = false; + break; + } + } + if (valid) { + constraints.insert(c); + } + } + } + } + } + + // Fills in the constraint list from existing tiles. + for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(painted_set, p_terrain_set, p_ignore_empty_terrains)) { + constraints.insert(c); + } + + // Fill the terrains. + output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); + return output; +} + +HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) { + HashMap<Vector2i, TileSet::TerrainsPattern> output; + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND_V(!tile_set.is_valid(), output); + ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output); + + // Make sure the path is correct and build the peering bit list while doing it. + Vector<TileSet::CellNeighbor> neighbor_list; + for (int i = 0; i < p_coords_array.size() - 1; i++) { + // Find the adequate neighbor. + TileSet::CellNeighbor found_bit = TileSet::CELL_NEIGHBOR_MAX; + for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { + TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); + if (tile_set->is_existing_neighbor(bit)) { + if (tile_set->get_neighbor_cell(p_coords_array[i], bit) == p_coords_array[i + 1]) { + found_bit = bit; + break; + } + } + } + ERR_FAIL_COND_V_MSG(found_bit == TileSet::CELL_NEIGHBOR_MAX, output, vformat("Invalid terrain path, %s is not a neighboring tile of %s", p_coords_array[i + 1], p_coords_array[i])); + neighbor_list.push_back(found_bit); + } + + // Build list and set of tiles that can be modified (painted and their surroundings). + Vector<Vector2i> can_modify_list; + RBSet<Vector2i> can_modify_set; + RBSet<Vector2i> painted_set; + for (int i = p_coords_array.size() - 1; i >= 0; i--) { + const Vector2i &coords = p_coords_array[i]; + can_modify_list.push_back(coords); + can_modify_set.insert(coords); + painted_set.insert(coords); + } + for (Vector2i coords : p_coords_array) { + // Find the adequate neighbor. + for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { + TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); + if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { + Vector2i neighbor = tile_set->get_neighbor_cell(coords, bit); + if (!can_modify_set.has(neighbor)) { + can_modify_list.push_back(neighbor); + can_modify_set.insert(neighbor); + } + } + } + } + + RBSet<TerrainConstraint> constraints; + + // Add new constraints from the path drawn. + for (Vector2i coords : p_coords_array) { + // Constraints on the center bit. + TerrainConstraint c = TerrainConstraint(tile_set, coords, p_terrain); + c.set_priority(10); + constraints.insert(c); + } + for (int i = 0; i < p_coords_array.size() - 1; i++) { + // Constraints on the peering bits. + TerrainConstraint c = TerrainConstraint(tile_set, p_coords_array[i], neighbor_list[i], p_terrain); + c.set_priority(10); + constraints.insert(c); + } + + // Fills in the constraint list from existing tiles. + for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(painted_set, p_terrain_set, p_ignore_empty_terrains)) { + constraints.insert(c); + } + + // Fill the terrains. + output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); + return output; +} + +HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) { + HashMap<Vector2i, TileSet::TerrainsPattern> output; + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND_V(!tile_set.is_valid(), output); + ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output); + + // Build list and set of tiles that can be modified (painted and their surroundings). + Vector<Vector2i> can_modify_list; + RBSet<Vector2i> can_modify_set; + RBSet<Vector2i> painted_set; + for (int i = p_coords_array.size() - 1; i >= 0; i--) { + const Vector2i &coords = p_coords_array[i]; + can_modify_list.push_back(coords); + can_modify_set.insert(coords); + painted_set.insert(coords); + } + for (Vector2i coords : p_coords_array) { + // Find the adequate neighbor. + for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { + TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); + if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) { + Vector2i neighbor = tile_set->get_neighbor_cell(coords, bit); + if (!can_modify_set.has(neighbor)) { + can_modify_list.push_back(neighbor); + can_modify_set.insert(neighbor); + } + } + } + } + + // Add constraint by the new ones. + RBSet<TerrainConstraint> constraints; + + // Add new constraints from the path drawn. + for (Vector2i coords : p_coords_array) { + // Constraints on the center bit. + RBSet<TerrainConstraint> added_constraints = _get_terrain_constraints_from_added_pattern(coords, p_terrain_set, p_terrains_pattern); + for (TerrainConstraint c : added_constraints) { + c.set_priority(10); + constraints.insert(c); + } + } + + // Fills in the constraint list from modified tiles border. + for (TerrainConstraint c : _get_terrain_constraints_from_painted_cells_list(painted_set, p_terrain_set, p_ignore_empty_terrains)) { + constraints.insert(c); + } + + // Fill the terrains. + output = terrain_fill_constraints(can_modify_list, p_terrain_set, constraints); + return output; +} + +TileMapCell TileMapLayer::get_cell(const Vector2i &p_coords, bool p_use_proxies) const { + if (!tile_map.has(p_coords)) { + return TileMapCell(); + } else { + TileMapCell c = tile_map.find(p_coords)->value.cell; + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (p_use_proxies && tile_set.is_valid()) { + Array proxyed = tile_set->map_tile_proxy(c.source_id, c.get_atlas_coords(), c.alternative_tile); + c.source_id = proxyed[0]; + c.set_atlas_coords(proxyed[1]); + c.alternative_tile = proxyed[2]; + } + return c; + } +} + +void TileMapLayer::set_tile_data(TileMapDataFormat p_format, const Vector<int> &p_data) { + ERR_FAIL_COND(p_format > TileMapDataFormat::FORMAT_3); + + // Set data for a given tile from raw data. + + int c = p_data.size(); + const int *r = p_data.ptr(); + + int offset = (p_format >= TileMapDataFormat::FORMAT_2) ? 3 : 2; + ERR_FAIL_COND_MSG(c % offset != 0, vformat("Corrupted tile data. Got size: %s. Expected modulo: %s", offset)); + + clear(); + +#ifdef DISABLE_DEPRECATED + ERR_FAIL_COND_MSG(p_format != TileMapDataFormat::FORMAT_3, vformat("Cannot handle deprecated TileMap data format version %d. This Godot version was compiled with no support for deprecated data.", p_format)); +#endif + + for (int i = 0; i < c; i += offset) { + const uint8_t *ptr = (const uint8_t *)&r[i]; + uint8_t local[12]; + for (int j = 0; j < ((p_format >= TileMapDataFormat::FORMAT_2) ? 12 : 8); j++) { + local[j] = ptr[j]; + } + +#ifdef BIG_ENDIAN_ENABLED + + SWAP(local[0], local[3]); + SWAP(local[1], local[2]); + SWAP(local[4], local[7]); + SWAP(local[5], local[6]); + //TODO: ask someone to check this... + if (FORMAT >= FORMAT_2) { + SWAP(local[8], local[11]); + SWAP(local[9], local[10]); + } +#endif + // Extracts position in TileMap. + int16_t x = decode_uint16(&local[0]); + int16_t y = decode_uint16(&local[2]); + + if (p_format == TileMapDataFormat::FORMAT_3) { + uint16_t source_id = decode_uint16(&local[4]); + uint16_t atlas_coords_x = decode_uint16(&local[6]); + uint16_t atlas_coords_y = decode_uint16(&local[8]); + uint16_t alternative_tile = decode_uint16(&local[10]); + set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile); + } else { +#ifndef DISABLE_DEPRECATED + // Previous decated format. + + uint32_t v = decode_uint32(&local[4]); + // Extract the transform flags that used to be in the tilemap. + bool flip_h = v & (1UL << 29); + bool flip_v = v & (1UL << 30); + bool transpose = v & (1UL << 31); + v &= (1UL << 29) - 1; + + // Extract autotile/atlas coords. + int16_t coord_x = 0; + int16_t coord_y = 0; + if (p_format == TileMapDataFormat::FORMAT_2) { + coord_x = decode_uint16(&local[8]); + coord_y = decode_uint16(&local[10]); + } + + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (tile_set.is_valid()) { + Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose); + if (a.size() == 3) { + set_cell(Vector2i(x, y), a[0], a[1], a[2]); + } else { + ERR_PRINT(vformat("No valid tile in Tileset for: tile:%s coords:%s flip_h:%s flip_v:%s transpose:%s", v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose)); + } + } else { + int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2); + set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile); + } +#endif + } + } +} + +Vector<int> TileMapLayer::get_tile_data() const { + // Export tile data to raw format. + Vector<int> tile_data; + tile_data.resize(tile_map.size() * 3); + int *w = tile_data.ptrw(); + + // Save in highest format. + + int idx = 0; + for (const KeyValue<Vector2i, CellData> &E : tile_map) { + uint8_t *ptr = (uint8_t *)&w[idx]; + encode_uint16((int16_t)(E.key.x), &ptr[0]); + encode_uint16((int16_t)(E.key.y), &ptr[2]); + encode_uint16(E.value.cell.source_id, &ptr[4]); + encode_uint16(E.value.cell.coord_x, &ptr[6]); + encode_uint16(E.value.cell.coord_y, &ptr[8]); + encode_uint16(E.value.cell.alternative_tile, &ptr[10]); + idx += 3; + } + + return tile_data; +} + +void TileMapLayer::notify_tile_map_change(DirtyFlags p_what) { + TileMap *tile_map_node = _fetch_tilemap(); + dirty.flags[p_what] = true; + tile_map_node->queue_internal_update(); +} + +void TileMapLayer::internal_update() { + // Find TileData that need a runtime modification. + // This may add cells to the dirty list is a runtime modification has been notified. + _build_runtime_update_tile_data(); + + // Update all subsystems. + _rendering_update(); + _physics_update(); + _navigation_update(); + _scenes_update(); +#ifdef DEBUG_ENABLED + _debug_update(); +#endif // DEBUG_ENABLED + + _clear_runtime_update_tile_data(); + + // Clear the "what is dirty" flags. + for (int i = 0; i < DIRTY_FLAGS_MAX; i++) { + dirty.flags[i] = false; + } + + // List the cells to delete definitely. + Vector<Vector2i> to_delete; + for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) { + CellData &cell_data = *cell_data_list_element->self(); + // Select the the cell from tile_map if it is invalid. + if (cell_data.cell.source_id == TileSet::INVALID_SOURCE) { + to_delete.push_back(cell_data.coords); + } + } + + // Remove cells that are empty after the cleanup. + for (const Vector2i &coords : to_delete) { + tile_map.erase(coords); + } + + // Clear the dirty cells list. + dirty.cell_list.clear(); +} + +void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) { + // Set the current cell tile (using integer position). + Vector2i pk(p_coords); + HashMap<Vector2i, CellData>::Iterator E = tile_map.find(pk); + + int source_id = p_source_id; + Vector2i atlas_coords = p_atlas_coords; + int alternative_tile = p_alternative_tile; + + if ((source_id == TileSet::INVALID_SOURCE || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) && + (source_id != TileSet::INVALID_SOURCE || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) { + source_id = TileSet::INVALID_SOURCE; + atlas_coords = TileSetSource::INVALID_ATLAS_COORDS; + alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; + } + + if (!E) { + if (source_id == TileSet::INVALID_SOURCE) { + return; // Nothing to do, the tile is already empty. + } + + // Insert a new cell in the tile map. + CellData new_cell_data; + new_cell_data.coords = pk; + E = tile_map.insert(pk, new_cell_data); + } else { + if (E->value.cell.source_id == source_id && E->value.cell.get_atlas_coords() == atlas_coords && E->value.cell.alternative_tile == alternative_tile) { + return; // Nothing changed. + } + } + + TileMapCell &c = E->value.cell; + c.source_id = source_id; + c.set_atlas_coords(atlas_coords); + c.alternative_tile = alternative_tile; + + // Make the given cell dirty. + if (!E->value.dirty_list_element.in_list()) { + dirty.cell_list.add(&(E->value.dirty_list_element)); + } + TileMap *tile_map_node = _fetch_tilemap(); + if (tile_map_node) { // Needed to avoid crashes in destructor. + tile_map_node->queue_internal_update(); + } + + used_rect_cache_dirty = true; +} + +void TileMapLayer::erase_cell(const Vector2i &p_coords) { + set_cell(p_coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); +} + +int TileMapLayer::get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies) const { + // Get a cell source id from position. + HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords); + + if (!E) { + return TileSet::INVALID_SOURCE; + } + + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (p_use_proxies && tile_set.is_valid()) { + Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile); + return proxyed[0]; + } + + return E->value.cell.source_id; +} + +Vector2i TileMapLayer::get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies) const { + // Get a cell source id from position. + HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords); + + if (!E) { + return TileSetSource::INVALID_ATLAS_COORDS; + } + + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (p_use_proxies && tile_set.is_valid()) { + Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile); + return proxyed[1]; + } + + return E->value.cell.get_atlas_coords(); +} + +int TileMapLayer::get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies) const { + // Get a cell source id from position. + HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords); + + if (!E) { + return TileSetSource::INVALID_TILE_ALTERNATIVE; + } + + const Ref<TileSet> &tile_set = _fetch_tileset(); + if (p_use_proxies && tile_set.is_valid()) { + Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile); + return proxyed[2]; + } + + return E->value.cell.alternative_tile; +} + +TileData *TileMapLayer::get_cell_tile_data(const Vector2i &p_coords, bool p_use_proxies) const { + int source_id = get_cell_source_id(p_coords, p_use_proxies); + if (source_id == TileSet::INVALID_SOURCE) { + return nullptr; + } + + const Ref<TileSet> &tile_set = _fetch_tileset(); + Ref<TileSetAtlasSource> source = tile_set->get_source(source_id); + if (source.is_valid()) { + return source->get_tile_data(get_cell_atlas_coords(p_coords, p_use_proxies), get_cell_alternative_tile(p_coords, p_use_proxies)); + } + + return nullptr; +} + +void TileMapLayer::clear() { + // Remove all tiles. + for (KeyValue<Vector2i, CellData> &kv : tile_map) { + erase_cell(kv.key); + } + used_rect_cache_dirty = true; +} + +Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_array) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr); + + Ref<TileMapPattern> output; + output.instantiate(); + if (p_coords_array.is_empty()) { + return output; + } + + Vector2i min = Vector2i(p_coords_array[0]); + for (int i = 1; i < p_coords_array.size(); i++) { + min = min.min(p_coords_array[i]); + } + + Vector<Vector2i> coords_in_pattern_array; + coords_in_pattern_array.resize(p_coords_array.size()); + Vector2i ensure_positive_offset; + for (int i = 0; i < p_coords_array.size(); i++) { + Vector2i coords = p_coords_array[i]; + Vector2i coords_in_pattern = coords - min; + if (tile_set->get_tile_shape() != TileSet::TILE_SHAPE_SQUARE) { + if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED) { + if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(min.y % 2) && bool(coords_in_pattern.y % 2)) { + coords_in_pattern.x -= 1; + if (coords_in_pattern.x < 0) { + ensure_positive_offset.x = 1; + } + } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(min.x % 2) && bool(coords_in_pattern.x % 2)) { + coords_in_pattern.y -= 1; + if (coords_in_pattern.y < 0) { + ensure_positive_offset.y = 1; + } + } + } else if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED_OFFSET) { + if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(min.y % 2) && bool(coords_in_pattern.y % 2)) { + coords_in_pattern.x += 1; + } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(min.x % 2) && bool(coords_in_pattern.x % 2)) { + coords_in_pattern.y += 1; + } + } + } + coords_in_pattern_array.write[i] = coords_in_pattern; + } + + for (int i = 0; i < coords_in_pattern_array.size(); i++) { + Vector2i coords = p_coords_array[i]; + Vector2i coords_in_pattern = coords_in_pattern_array[i]; + output->set_cell(coords_in_pattern + ensure_positive_offset, get_cell_source_id(coords), get_cell_atlas_coords(coords), get_cell_alternative_tile(coords)); + } + + return output; +} + +void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND(tile_set.is_null()); + ERR_FAIL_COND(p_pattern.is_null()); + + TypedArray<Vector2i> used_cells = p_pattern->get_used_cells(); + for (int i = 0; i < used_cells.size(); i++) { + Vector2i coords = tile_set->map_pattern(p_position, used_cells[i], p_pattern); + set_cell(coords, p_pattern->get_cell_source_id(used_cells[i]), p_pattern->get_cell_atlas_coords(used_cells[i]), p_pattern->get_cell_alternative_tile(used_cells[i])); + } +} + +void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND(!tile_set.is_valid()); + ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count()); + + Vector<Vector2i> cells_vector; + HashSet<Vector2i> painted_set; + for (int i = 0; i < p_cells.size(); i++) { + cells_vector.push_back(p_cells[i]); + painted_set.insert(p_cells[i]); + } + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_connect(cells_vector, p_terrain_set, p_terrain, p_ignore_empty_terrains); + for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : terrain_fill_output) { + if (painted_set.has(kv.key)) { + // Paint a random tile with the correct terrain for the painted path. + TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); + set_cell(kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + } else { + // Avoids updating the painted path from the output if the new pattern is the same as before. + TileSet::TerrainsPattern in_map_terrain_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); + TileMapCell cell = get_cell(kv.key); + if (cell.source_id != TileSet::INVALID_SOURCE) { + TileSetSource *source = *tile_set->get_source(cell.source_id); + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + // Get tile data. + TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); + if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { + in_map_terrain_pattern = tile_data->get_terrains_pattern(); + } + } + } + if (in_map_terrain_pattern != kv.value) { + TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); + set_cell(kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + } + } + } +} + +void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) { + const Ref<TileSet> &tile_set = _fetch_tileset(); + ERR_FAIL_COND(!tile_set.is_valid()); + ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count()); + + Vector<Vector2i> vector_path; + HashSet<Vector2i> painted_set; + for (int i = 0; i < p_path.size(); i++) { + vector_path.push_back(p_path[i]); + painted_set.insert(p_path[i]); + } + + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = terrain_fill_path(vector_path, p_terrain_set, p_terrain, p_ignore_empty_terrains); + for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : terrain_fill_output) { + if (painted_set.has(kv.key)) { + // Paint a random tile with the correct terrain for the painted path. + TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); + set_cell(kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + } else { + // Avoids updating the painted path from the output if the new pattern is the same as before. + TileSet::TerrainsPattern in_map_terrain_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set); + TileMapCell cell = get_cell(kv.key); + if (cell.source_id != TileSet::INVALID_SOURCE) { + TileSetSource *source = *tile_set->get_source(cell.source_id); + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + // Get tile data. + TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile); + if (tile_data && tile_data->get_terrain_set() == p_terrain_set) { + in_map_terrain_pattern = tile_data->get_terrains_pattern(); + } + } + } + if (in_map_terrain_pattern != kv.value) { + TileMapCell c = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value); + set_cell(kv.key, c.source_id, c.get_atlas_coords(), c.alternative_tile); + } + } + } +} + +TypedArray<Vector2i> TileMapLayer::get_used_cells() const { + // Returns the cells used in the tilemap. + TypedArray<Vector2i> a; + for (const KeyValue<Vector2i, CellData> &E : tile_map) { + const TileMapCell &c = E.value.cell; + if (c.source_id == TileSet::INVALID_SOURCE) { + continue; + } + a.push_back(E.key); + } + + return a; +} + +TypedArray<Vector2i> TileMapLayer::get_used_cells_by_id(int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) const { + // Returns the cells used in the tilemap. + TypedArray<Vector2i> a; + for (const KeyValue<Vector2i, CellData> &E : tile_map) { + const TileMapCell &c = E.value.cell; + if (c.source_id == TileSet::INVALID_SOURCE) { + continue; + } + if ((p_source_id == TileSet::INVALID_SOURCE || p_source_id == c.source_id) && + (p_atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || p_atlas_coords == c.get_atlas_coords()) && + (p_alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE || p_alternative_tile == c.alternative_tile)) { + a.push_back(E.key); + } + } + + return a; +} + +Rect2i TileMapLayer::get_used_rect() const { + // Return the rect of the currently used area. + if (used_rect_cache_dirty) { + used_rect_cache = Rect2i(); + + bool first = true; + for (const KeyValue<Vector2i, CellData> &E : tile_map) { + const TileMapCell &c = E.value.cell; + if (c.source_id == TileSet::INVALID_SOURCE) { + continue; + } + if (first) { + used_rect_cache = Rect2i(E.key.x, E.key.y, 0, 0); + first = false; + } else { + used_rect_cache.expand_to(E.key); + } + } + if (!first) { + // Only if we have at least one cell. + // The cache expands to top-left coordinate, so we add one full tile. + used_rect_cache.size += Vector2i(1, 1); + } + used_rect_cache_dirty = false; + } + + return used_rect_cache; +} + +void TileMapLayer::set_enabled(bool p_enabled) { + if (enabled == p_enabled) { + return; + } + enabled = p_enabled; + dirty.flags[DIRTY_FLAGS_LAYER_ENABLED] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); + + tile_map_node->update_configuration_warnings(); +} + +bool TileMapLayer::is_enabled() const { + return enabled; +} + +void TileMapLayer::set_self_modulate(const Color &p_self_modulate) { + if (get_self_modulate() == p_self_modulate) { + return; + } + CanvasItem::set_self_modulate(p_self_modulate); + dirty.flags[DIRTY_FLAGS_LAYER_SELF_MODULATE] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); +} + +void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) { + if (is_y_sort_enabled() == p_y_sort_enabled) { + return; + } + CanvasItem::set_y_sort_enabled(p_y_sort_enabled); + dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); + + tile_map_node->update_configuration_warnings(); + _update_notify_local_transform(); +} + +void TileMapLayer::set_y_sort_origin(int p_y_sort_origin) { + if (y_sort_origin == p_y_sort_origin) { + return; + } + y_sort_origin = p_y_sort_origin; + dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); +} + +int TileMapLayer::get_y_sort_origin() const { + return y_sort_origin; +} + +void TileMapLayer::set_z_index(int p_z_index) { + if (get_z_index() == p_z_index) { + return; + } + CanvasItem::set_z_index(p_z_index); + dirty.flags[DIRTY_FLAGS_LAYER_Z_INDEX] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); + + tile_map_node->update_configuration_warnings(); +} + +void TileMapLayer::set_use_kinematic_bodies(bool p_use_kinematic_bodies) { + use_kinematic_bodies = p_use_kinematic_bodies; + dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] = p_use_kinematic_bodies; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); +} + +bool TileMapLayer::is_using_kinematic_bodies() const { + return use_kinematic_bodies; +} + +void TileMapLayer::set_navigation_enabled(bool p_enabled) { + if (navigation_enabled == p_enabled) { + return; + } + navigation_enabled = p_enabled; + dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED] = true; + TileMap *tile_map_node = _fetch_tilemap(); + tile_map_node->queue_internal_update(); + tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed); +} + +bool TileMapLayer::is_navigation_enabled() const { + return navigation_enabled; +} + +void TileMapLayer::set_navigation_map(RID p_map) { + ERR_FAIL_COND_MSG(!is_inside_tree(), "A TileMap navigation map can only be changed while inside the SceneTree."); + navigation_map = p_map; + uses_world_navigation_map = p_map == get_world_2d()->get_navigation_map(); +} + +RID TileMapLayer::get_navigation_map() const { + if (navigation_map.is_valid()) { + return navigation_map; + } + return RID(); +} + +void TileMapLayer::fix_invalid_tiles() { + Ref<TileSet> tileset = _fetch_tileset(); + ERR_FAIL_COND_MSG(tileset.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet."); + + RBSet<Vector2i> coords; + for (const KeyValue<Vector2i, CellData> &E : tile_map) { + TileSetSource *source = *tileset->get_source(E.value.cell.source_id); + if (!source || !source->has_tile(E.value.cell.get_atlas_coords()) || !source->has_alternative_tile(E.value.cell.get_atlas_coords(), E.value.cell.alternative_tile)) { + coords.insert(E.key); + } + } + for (const Vector2i &E : coords) { + set_cell(E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); + } +} + +bool TileMapLayer::has_body_rid(RID p_physics_body) const { + return bodies_coords.has(p_physics_body); +} + +Vector2i TileMapLayer::get_coords_for_body_rid(RID p_physics_body) const { + return bodies_coords[p_physics_body]; +} + +TileMapLayer::TileMapLayer() { + set_notify_transform(true); +} + +TileMapLayer::~TileMapLayer() { + in_destructor = true; + clear(); + internal_update(); +} + +HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coords_and_peering_bits() const { + HashMap<Vector2i, TileSet::CellNeighbor> output; + + ERR_FAIL_COND_V(is_center_bit(), output); + ERR_FAIL_COND_V(!tile_set.is_valid(), output); + + TileSet::TileShape shape = tile_set->get_tile_shape(); + if (shape == TileSet::TILE_SHAPE_SQUARE) { + switch (bit) { + case 1: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE; + break; + case 2: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER; + break; + case 3: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE; + break; + default: + ERR_FAIL_V(output); + } + } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) { + switch (bit) { + case 1: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE; + break; + case 2: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER; + break; + case 3: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; + break; + default: + ERR_FAIL_V(output); + } + } else { + // Half offset shapes. + TileSet::TileOffsetAxis offset_axis = tile_set->get_tile_offset_axis(); + if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + switch (bit) { + case 1: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE; + break; + case 2: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_CORNER; + break; + case 3: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE; + break; + case 4: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER; + break; + case 5: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; + break; + default: + ERR_FAIL_V(output); + } + } else { + switch (bit) { + case 1: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER; + break; + case 2: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE; + break; + case 3: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER; + break; + case 4: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE; + break; + case 5: + output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE; + output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; + break; + default: + ERR_FAIL_V(output); + } + } + } + return output; +} + +TerrainConstraint::TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, int p_terrain) { + ERR_FAIL_COND(!p_tile_set.is_valid()); + tile_set = p_tile_set; + bit = 0; + base_cell_coords = p_position; + terrain = p_terrain; +} + +TerrainConstraint::TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain) { + // The way we build the constraint make it easy to detect conflicting constraints. + ERR_FAIL_COND(!p_tile_set.is_valid()); + tile_set = p_tile_set; + + TileSet::TileShape shape = tile_set->get_tile_shape(); + if (shape == TileSet::TILE_SHAPE_SQUARE) { + switch (p_bit) { + case TileSet::CELL_NEIGHBOR_RIGHT_SIDE: + bit = 1; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: + bit = 2; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE: + bit = 3; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_LEFT_SIDE: + bit = 1; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER); + break; + case TileSet::CELL_NEIGHBOR_TOP_SIDE: + bit = 3; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE); + break; + default: + ERR_FAIL(); + break; + } + } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) { + switch (p_bit) { + case TileSet::CELL_NEIGHBOR_RIGHT_CORNER: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE: + bit = 1; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER: + bit = 2; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE: + bit = 3; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_LEFT_CORNER: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE: + bit = 1; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_CORNER: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_CORNER); + break; + case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE: + bit = 3; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); + break; + default: + ERR_FAIL(); + break; + } + } else { + // Half-offset shapes. + TileSet::TileOffsetAxis offset_axis = tile_set->get_tile_offset_axis(); + if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + switch (p_bit) { + case TileSet::CELL_NEIGHBOR_RIGHT_SIDE: + bit = 1; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: + bit = 2; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE: + bit = 3; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER: + bit = 4; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE: + bit = 5; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_LEFT_SIDE: + bit = 1; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER: + bit = 4; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE: + bit = 3; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_CORNER: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE: + bit = 5; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER: + bit = 4; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); + break; + default: + ERR_FAIL(); + break; + } + } else { + switch (p_bit) { + case TileSet::CELL_NEIGHBOR_RIGHT_CORNER: + bit = 1; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE: + bit = 2; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: + bit = 3; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE: + bit = 4; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER: + bit = 1; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE: + bit = 5; + base_cell_coords = p_position; + break; + case TileSet::CELL_NEIGHBOR_LEFT_CORNER: + bit = 3; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE: + bit = 2; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER: + bit = 1; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_SIDE: + bit = 4; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER: + bit = 3; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE); + break; + case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE: + bit = 5; + base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE); + break; + default: + ERR_FAIL(); + break; + } + } + } + terrain = p_terrain; +}
\ No newline at end of file diff --git a/scene/2d/tile_map_layer.h b/scene/2d/tile_map_layer.h new file mode 100644 index 0000000000..2cc57f50d1 --- /dev/null +++ b/scene/2d/tile_map_layer.h @@ -0,0 +1,417 @@ +/**************************************************************************/ +/* tile_map_layer.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TILE_MAP_LAYER_H +#define TILE_MAP_LAYER_H + +#include "scene/2d/tile_map.h" +#include "scene/resources/tile_set.h" + +class TileSetAtlasSource; + +class TerrainConstraint { +private: + Ref<TileSet> tile_set; + Vector2i base_cell_coords; + int bit = -1; + int terrain = -1; + + int priority = 1; + +public: + bool operator<(const TerrainConstraint &p_other) const { + if (base_cell_coords == p_other.base_cell_coords) { + return bit < p_other.bit; + } + return base_cell_coords < p_other.base_cell_coords; + } + + String to_string() const { + return vformat("Constraint {pos:%s, bit:%d, terrain:%d, priority:%d}", base_cell_coords, bit, terrain, priority); + } + + Vector2i get_base_cell_coords() const { + return base_cell_coords; + } + + bool is_center_bit() const { + return bit == 0; + } + + HashMap<Vector2i, TileSet::CellNeighbor> get_overlapping_coords_and_peering_bits() const; + + void set_terrain(int p_terrain) { + terrain = p_terrain; + } + + int get_terrain() const { + return terrain; + } + + void set_priority(int p_priority) { + priority = p_priority; + } + + int get_priority() const { + return priority; + } + + TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, int p_terrain); // For the center terrain bit + TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain); // For peering bits + TerrainConstraint(){}; +}; + +#ifdef DEBUG_ENABLED +class DebugQuadrant; +#endif // DEBUG_ENABLED +class RenderingQuadrant; + +struct CellData { + Vector2i coords; + TileMapCell cell; + + // Debug. + SelfList<CellData> debug_quadrant_list_element; + + // Rendering. + Ref<RenderingQuadrant> rendering_quadrant; + SelfList<CellData> rendering_quadrant_list_element; + LocalVector<RID> occluders; + + // Physics. + LocalVector<RID> bodies; + + // Navigation. + LocalVector<RID> navigation_regions; + + // Scenes. + String scene; + + // Runtime TileData cache. + TileData *runtime_tile_data_cache = nullptr; + + // List elements. + SelfList<CellData> dirty_list_element; + + bool operator<(const CellData &p_other) const { + return coords < p_other.coords; + } + + // For those, copy everything but SelfList elements. + void operator=(const CellData &p_other) { + coords = p_other.coords; + cell = p_other.cell; + occluders = p_other.occluders; + bodies = p_other.bodies; + navigation_regions = p_other.navigation_regions; + scene = p_other.scene; + runtime_tile_data_cache = p_other.runtime_tile_data_cache; + } + + CellData(const CellData &p_other) : + debug_quadrant_list_element(this), + rendering_quadrant_list_element(this), + dirty_list_element(this) { + coords = p_other.coords; + cell = p_other.cell; + occluders = p_other.occluders; + bodies = p_other.bodies; + navigation_regions = p_other.navigation_regions; + scene = p_other.scene; + runtime_tile_data_cache = p_other.runtime_tile_data_cache; + } + + CellData() : + debug_quadrant_list_element(this), + rendering_quadrant_list_element(this), + dirty_list_element(this) { + } +}; + +// For compatibility reasons, we use another comparator for Y-sorted layers. +struct CellDataYSortedComparator { + _FORCE_INLINE_ bool operator()(const CellData &p_a, const CellData &p_b) const { + return p_a.coords.x == p_b.coords.x ? (p_a.coords.y < p_b.coords.y) : (p_a.coords.x > p_b.coords.x); + } +}; + +#ifdef DEBUG_ENABLED +class DebugQuadrant : public RefCounted { + GDCLASS(DebugQuadrant, RefCounted); + +public: + Vector2i quadrant_coords; + SelfList<CellData>::List cells; + RID canvas_item; + + SelfList<DebugQuadrant> dirty_quadrant_list_element; + + DebugQuadrant() : + dirty_quadrant_list_element(this) { + } + + ~DebugQuadrant() { + cells.clear(); + } +}; +#endif // DEBUG_ENABLED + +class RenderingQuadrant : public RefCounted { + GDCLASS(RenderingQuadrant, RefCounted); + +public: + struct CoordsWorldComparator { + _ALWAYS_INLINE_ bool operator()(const Vector2 &p_a, const Vector2 &p_b) const { + // We sort the cells by their local coords, as it is needed by rendering. + if (p_a.y == p_b.y) { + return p_a.x > p_b.x; + } else { + return p_a.y < p_b.y; + } + } + }; + + Vector2i quadrant_coords; + SelfList<CellData>::List cells; + List<RID> canvas_items; + Vector2 canvas_items_position; + + SelfList<RenderingQuadrant> dirty_quadrant_list_element; + + RenderingQuadrant() : + dirty_quadrant_list_element(this) { + } + + ~RenderingQuadrant() { + cells.clear(); + } +}; + +class TileMapLayer : public Node2D { + GDCLASS(TileMapLayer, Node2D); + +public: + enum DirtyFlags { + DIRTY_FLAGS_LAYER_ENABLED = 0, + DIRTY_FLAGS_LAYER_IN_TREE, + DIRTY_FLAGS_LAYER_IN_CANVAS, + DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM, + DIRTY_FLAGS_LAYER_VISIBILITY, + DIRTY_FLAGS_LAYER_SELF_MODULATE, + DIRTY_FLAGS_LAYER_Y_SORT_ENABLED, + DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN, + DIRTY_FLAGS_LAYER_Z_INDEX, + DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES, + DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED, + DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE, + + DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER, + DIRTY_FLAGS_TILE_MAP_LIGHT_MASK, + DIRTY_FLAGS_TILE_MAP_MATERIAL, + DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL, + DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER, + DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT, + DIRTY_FLAGS_TILE_MAP_TILE_SET, + DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE, + DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE, + DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE, + DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED, + DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE, + DIRTY_FLAGS_MAX, + }; + +private: + // Exposed properties. + bool enabled = true; + int y_sort_origin = 0; + bool use_kinematic_bodies = false; + bool navigation_enabled = true; + RID navigation_map; + bool uses_world_navigation_map = false; + + // Internal. + int layer_index_in_tile_map_node = -1; + HashMap<Vector2i, CellData> tile_map; + + // Dirty flag. Allows knowing what was modified since the last update. + struct { + bool flags[DIRTY_FLAGS_MAX] = { false }; + SelfList<CellData>::List cell_list; + } dirty; + bool in_destructor = false; + + // Rect cache. + mutable Rect2 rect_cache; + mutable bool rect_cache_dirty = true; + mutable Rect2i used_rect_cache; + mutable bool used_rect_cache_dirty = true; + + // Method to fetch the TileSet to use + TileMap *_fetch_tilemap() const; + Ref<TileSet> _fetch_tileset() const; + + // Runtime tile data. + bool _runtime_update_tile_data_was_cleaned_up = false; + void _build_runtime_update_tile_data(); + void _build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list = false); + void _clear_runtime_update_tile_data(); + + // Per-system methods. +#ifdef DEBUG_ENABLED + HashMap<Vector2i, Ref<DebugQuadrant>> debug_quadrant_map; + Vector2i _coords_to_debug_quadrant_coords(const Vector2i &p_coords) const; + bool _debug_was_cleaned_up = false; + void _debug_update(); + void _debug_quadrants_update_cell(CellData &r_cell_data, SelfList<DebugQuadrant>::List &r_dirty_debug_quadrant_list); +#endif // DEBUG_ENABLED + + HashMap<Vector2i, Ref<RenderingQuadrant>> rendering_quadrant_map; + bool _rendering_was_cleaned_up = false; + void _rendering_update(); + void _rendering_notification(int p_what); + void _rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list); + void _rendering_occluders_clear_cell(CellData &r_cell_data); + void _rendering_occluders_update_cell(CellData &r_cell_data); +#ifdef DEBUG_ENABLED + void _rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data); +#endif // DEBUG_ENABLED + + HashMap<RID, Vector2i> bodies_coords; // Mapping for RID to coords. + bool _physics_was_cleaned_up = false; + void _physics_update(); + void _physics_notification(int p_what); + void _physics_clear_cell(CellData &r_cell_data); + void _physics_update_cell(CellData &r_cell_data); +#ifdef DEBUG_ENABLED + void _physics_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data); +#endif // DEBUG_ENABLED + + bool _navigation_was_cleaned_up = false; + void _navigation_update(); + void _navigation_notification(int p_what); + void _navigation_clear_cell(CellData &r_cell_data); + void _navigation_update_cell(CellData &r_cell_data); +#ifdef DEBUG_ENABLED + void _navigation_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data); +#endif // DEBUG_ENABLED + + bool _scenes_was_cleaned_up = false; + void _scenes_update(); + void _scenes_clear_cell(CellData &r_cell_data); + void _scenes_update_cell(CellData &r_cell_data); +#ifdef DEBUG_ENABLED + void _scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data); +#endif // DEBUG_ENABLED + + // Terrains. + TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern); + RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const; + RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const; + + void _renamed(); + void _update_notify_local_transform(); + +protected: + void _notification(int p_what); + +public: + // TileMap node. + void set_layer_index_in_tile_map_node(int p_index); + + // Rect caching. + Rect2 get_rect(bool &r_changed) const; + + // Terrains. + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints); // Not exposed. + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed. + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed. + HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true); // Not exposed. + + // Not exposed to users. + TileMapCell get_cell(const Vector2i &p_coords, bool p_use_proxies = false) const; + + // For TileMap node's use. + void set_tile_data(TileMapDataFormat p_format, const Vector<int> &p_data); + Vector<int> get_tile_data() const; + void notify_tile_map_change(DirtyFlags p_what); + void internal_update(); + + // --- Exposed in TileMap --- + + // Cells manipulation. + void set_cell(const Vector2i &p_coords, int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = 0); + void erase_cell(const Vector2i &p_coords); + + int get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies = false) const; + Vector2i get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies = false) const; + int get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies = false) const; + TileData *get_cell_tile_data(const Vector2i &p_coords, bool p_use_proxies = false) const; // Helper method to make accessing the data easier. + void clear(); + + // Patterns. + Ref<TileMapPattern> get_pattern(TypedArray<Vector2i> p_coords_array); + void set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern); + + // Terrains. + void set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); + void set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); + + // Cells usage. + TypedArray<Vector2i> get_used_cells() const; + TypedArray<Vector2i> get_used_cells_by_id(int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE) const; + Rect2i get_used_rect() const; + + // Layer properties. + void set_enabled(bool p_enabled); + bool is_enabled() const; + virtual void set_self_modulate(const Color &p_self_modulate) override; + virtual void set_y_sort_enabled(bool p_y_sort_enabled) override; + void set_y_sort_origin(int p_y_sort_origin); + int get_y_sort_origin() const; + virtual void set_z_index(int p_z_index) override; + void set_use_kinematic_bodies(bool p_use_kinematic_bodies); + bool is_using_kinematic_bodies() const; + void set_navigation_enabled(bool p_enabled); + bool is_navigation_enabled() const; + void set_navigation_map(RID p_map); + RID get_navigation_map() const; + + // Fixing and clearing methods. + void fix_invalid_tiles(); + + // Find coords for body. + bool has_body_rid(RID p_physics_body) const; + Vector2i get_coords_for_body_rid(RID p_physics_body) const; // For finding tiles from collision. + + TileMapLayer(); + ~TileMapLayer(); +}; + +#endif // TILE_MAP_LAYER_H diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 3971e615a1..bfdbd14cc9 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -37,6 +37,8 @@ #include "scene/main/viewport.h" #include "scene/scene_string_names.h" +#define PARAM_PREFIX "parameters/" + // Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004) // Speaker-Placement Correction Amplitude Panning (SPCAP) class Spcap { @@ -525,9 +527,35 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() { return output_volume_vector; } +void AudioStreamPlayer3D::_update_stream_parameters() { + if (stream.is_null()) { + return; + } + List<AudioStream::Parameter> parameters; + stream->get_parameter_list(¶meters); + for (const AudioStream::Parameter &K : parameters) { + const PropertyInfo &pi = K.property; + StringName key = PARAM_PREFIX + pi.name; + if (!playback_parameters.has(key)) { + ParameterData pd; + pd.path = pi.name; + pd.value = K.default_value; + playback_parameters.insert(key, pd); + } + } +} + void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) { + if (stream.is_valid()) { + stream->disconnect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer3D::_update_stream_parameters)); + } stop(); stream = p_stream; + _update_stream_parameters(); + if (stream.is_valid()) { + stream->connect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer3D::_update_stream_parameters)); + } + notify_property_list_changed(); } Ref<AudioStream> AudioStreamPlayer3D::get_stream() const { @@ -579,6 +607,10 @@ void AudioStreamPlayer3D::play(float p_from_pos) { Ref<AudioStreamPlayback> stream_playback = stream->instantiate_playback(); ERR_FAIL_COND_MSG(stream_playback.is_null(), "Failed to instantiate playback."); + for (const KeyValue<StringName, ParameterData> &K : playback_parameters) { + stream_playback->set_parameter(K.value.path, K.value.value); + } + stream_playbacks.push_back(stream_playback); setplayback = stream_playback; setplay.set(p_from_pos); @@ -818,6 +850,42 @@ void AudioStreamPlayer3D::_on_bus_renamed(int p_bus_index, const StringName &p_o notify_property_list_changed(); } +bool AudioStreamPlayer3D::_set(const StringName &p_name, const Variant &p_value) { + HashMap<StringName, ParameterData>::Iterator I = playback_parameters.find(p_name); + if (!I) { + return false; + } + ParameterData &pd = I->value; + pd.value = p_value; + for (Ref<AudioStreamPlayback> &playback : stream_playbacks) { + playback->set_parameter(pd.path, pd.value); + } + return true; +} + +bool AudioStreamPlayer3D::_get(const StringName &p_name, Variant &r_ret) const { + HashMap<StringName, ParameterData>::ConstIterator I = playback_parameters.find(p_name); + if (!I) { + return false; + } + + r_ret = I->value.value; + return true; +} + +void AudioStreamPlayer3D::_get_property_list(List<PropertyInfo> *p_list) const { + if (stream.is_null()) { + return; + } + List<AudioStream::Parameter> parameters; + stream->get_parameter_list(¶meters); + for (const AudioStream::Parameter &K : parameters) { + PropertyInfo pi = K.property; + pi.name = PARAM_PREFIX + pi.name; + p_list->push_back(pi); + } +} + void AudioStreamPlayer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer3D::set_stream); ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer3D::get_stream); diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index f20170e63b..facded1b9c 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -121,11 +121,23 @@ private: float panning_strength = 1.0f; float cached_global_panning_strength = 0.5f; + struct ParameterData { + StringName path; + Variant value; + }; + + HashMap<StringName, ParameterData> playback_parameters; + void _update_stream_parameters(); + protected: void _validate_property(PropertyInfo &p_property) const; void _notification(int p_what); static void _bind_methods(); + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + public: void set_stream(Ref<AudioStream> p_stream); Ref<AudioStream> get_stream() const; diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp index 45de9b907c..5683fb7306 100644 --- a/scene/3d/bone_attachment_3d.cpp +++ b/scene/3d/bone_attachment_3d.cpp @@ -150,7 +150,7 @@ void BoneAttachment3D::_check_bind() { if (bone_idx != -1) { sk->connect(SNAME("bone_pose_changed"), callable_mp(this, &BoneAttachment3D::on_bone_pose_update)); bound = true; - call_deferred(SNAME("on_bone_pose_update"), bone_idx); + callable_mp(this, &BoneAttachment3D::on_bone_pose_update).call_deferred(bone_idx); } } } diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 4562ecfb5f..0cfe0f8cb7 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -295,16 +295,12 @@ void CollisionObject3D::_input_event_call(Camera3D *p_camera, const Ref<InputEve } void CollisionObject3D::_mouse_enter() { - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter); - } + GDVIRTUAL_CALL(_mouse_enter); emit_signal(SceneStringNames::get_singleton()->mouse_entered); } void CollisionObject3D::_mouse_exit() { - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit); - } + GDVIRTUAL_CALL(_mouse_exit); emit_signal(SceneStringNames::get_singleton()->mouse_exited); } @@ -628,6 +624,7 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3 total_subshapes++; _update_shape_data(p_owner); + update_gizmos(); } int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const { @@ -691,6 +688,8 @@ void CollisionObject3D::shape_owner_clear_shapes(uint32_t p_owner) { while (shape_owner_get_shape_count(p_owner) > 0) { shape_owner_remove_shape(p_owner, 0); } + + update_gizmos(); } uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const { diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 0bb0382301..61941a0e53 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -35,6 +35,7 @@ #include "scene/resources/concave_polygon_shape_3d.h" #include "scene/resources/convex_polygon_shape_3d.h" #include "scene/resources/world_boundary_shape_3d.h" +#include "vehicle_body_3d.h" void CollisionShape3D::make_convex_from_siblings() { Node *p = get_parent(); @@ -130,13 +131,24 @@ PackedStringArray CollisionShape3D::get_configuration_warnings() const { } if (shape.is_valid() && Object::cast_to<RigidBody3D>(col_object)) { + String body_type = "RigidBody3D"; + if (Object::cast_to<VehicleBody3D>(col_object)) { + body_type = "VehicleBody3D"; + } + if (Object::cast_to<ConcavePolygonShape3D>(*shape)) { - warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static.")); + warnings.push_back(vformat(RTR("When used for collision, ConcavePolygonShape3D is intended to work with static CollisionObject3D nodes like StaticBody3D.\nIt will likely not behave well for %ss (except when frozen and freeze_mode set to FREEZE_MODE_STATIC)."), body_type)); } else if (Object::cast_to<WorldBoundaryShape3D>(*shape)) { warnings.push_back(RTR("WorldBoundaryShape3D doesn't support RigidBody3D in another mode than static.")); } } + if (shape.is_valid() && Object::cast_to<CharacterBody3D>(col_object)) { + if (Object::cast_to<ConcavePolygonShape3D>(*shape)) { + warnings.push_back(RTR("When used for collision, ConcavePolygonShape3D is intended to work with static CollisionObject3D nodes like StaticBody3D.\nIt will likely not behave well for CharacterBody3Ds.")); + } + } + Vector3 scale = get_transform().get_basis().get_scale(); if (!(Math::is_zero_approx(scale.x - scale.y) && Math::is_zero_approx(scale.y - scale.z))) { warnings.push_back(RTR("A non-uniformly scaled CollisionShape3D node will probably not function as expected.\nPlease make its scale uniform (i.e. the same on all axes), and change the size of its shape resource instead.")); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index fc84b3308e..dfb039d709 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -460,7 +460,12 @@ void GPUParticles3D::_notification(int p_what) { // Use internal process when emitting and one_shot is on so that when // the shot ends the editor can properly update. case NOTIFICATION_INTERNAL_PROCESS: { - RS::get_singleton()->particles_set_emitter_velocity(particles, (get_global_position() - previous_position) / get_process_delta_time()); + const Vector3 velocity = (get_global_position() - previous_position) / get_process_delta_time(); + + if (velocity != previous_velocity) { + RS::get_singleton()->particles_set_emitter_velocity(particles, velocity); + previous_velocity = velocity; + } previous_position = get_global_position(); if (one_shot) { diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h index ae9349817c..0c9f2c1378 100644 --- a/scene/3d/gpu_particles_3d.h +++ b/scene/3d/gpu_particles_3d.h @@ -95,6 +95,7 @@ private: double emission_time = 0.0; double active_time = 0.0; float interp_to_end_factor = 0; + Vector3 previous_velocity; Vector3 previous_position; void _attach_sub_emitter(); diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 76933cd956..92b783392d 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -734,15 +734,15 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa MeshesFound &mf = meshes_found.write[m_i]; - Size2i lightmap_size = mf.mesh->get_lightmap_size_hint(); - - if (lightmap_size == Size2i(0, 0)) { + Size2i mesh_lightmap_size = mf.mesh->get_lightmap_size_hint(); + if (mesh_lightmap_size == Size2i(0, 0)) { // TODO we should compute a size if no lightmap hint is set, as we did in 3.x. // For now set to basic size to avoid crash. - lightmap_size = Size2i(64, 64); + mesh_lightmap_size = Size2i(64, 64); } + Size2i lightmap_size = Size2i(Size2(mesh_lightmap_size) * mf.lightmap_scale * texel_scale); + ERR_FAIL_COND_V(lightmap_size.x == 0 || lightmap_size.y == 0, BAKE_ERROR_LIGHTMAP_TOO_SMALL); - lightmap_size *= mf.lightmap_scale; TypedArray<RID> overrides; overrides.resize(mf.overrides.size()); for (int i = 0; i < mf.overrides.size(); i++) { @@ -1493,6 +1493,15 @@ float LightmapGI::get_bias() const { return bias; } +void LightmapGI::set_texel_scale(float p_multiplier) { + ERR_FAIL_COND(p_multiplier < (0.01 - CMP_EPSILON)); + texel_scale = p_multiplier; +} + +float LightmapGI::get_texel_scale() const { + return texel_scale; +} + void LightmapGI::set_max_texture_size(int p_size) { ERR_FAIL_COND_MSG(p_size < 2048, vformat("The LightmapGI maximum texture size supplied (%d) is too small. The minimum allowed value is 2048.", p_size)); ERR_FAIL_COND_MSG(p_size > 16384, vformat("The LightmapGI maximum texture size supplied (%d) is too large. The maximum allowed value is 16384.", p_size)); @@ -1576,6 +1585,9 @@ void LightmapGI::_bind_methods() { ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &LightmapGI::set_environment_custom_energy); ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &LightmapGI::get_environment_custom_energy); + ClassDB::bind_method(D_METHOD("set_texel_scale", "texel_scale"), &LightmapGI::set_texel_scale); + ClassDB::bind_method(D_METHOD("get_texel_scale"), &LightmapGI::get_texel_scale); + ClassDB::bind_method(D_METHOD("set_max_texture_size", "max_texture_size"), &LightmapGI::set_max_texture_size); ClassDB::bind_method(D_METHOD("get_max_texture_size"), &LightmapGI::get_max_texture_size); @@ -1609,6 +1621,7 @@ void LightmapGI::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "denoiser_strength", PROPERTY_HINT_RANGE, "0.001,0.2,0.001,or_greater"), "set_denoiser_strength", "get_denoiser_strength"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texel_scale", PROPERTY_HINT_RANGE, "0.01,100.0,0.01"), "set_texel_scale", "get_texel_scale"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size", PROPERTY_HINT_RANGE, "2048,16384,1"), "set_max_texture_size", "get_max_texture_size"); ADD_GROUP("Environment", "environment_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode"); diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h index fec0075693..765e4a731d 100644 --- a/scene/3d/lightmap_gi.h +++ b/scene/3d/lightmap_gi.h @@ -142,6 +142,7 @@ public: BAKE_ERROR_CANT_CREATE_IMAGE, BAKE_ERROR_USER_ABORTED, BAKE_ERROR_TEXTURE_SIZE_TOO_SMALL, + BAKE_ERROR_LIGHTMAP_TOO_SMALL, }; enum EnvironmentMode { @@ -158,6 +159,7 @@ private: int bounces = 3; float bounce_indirect_energy = 1.0; float bias = 0.0005; + float texel_scale = 1.0; int max_texture_size = 16384; bool interior = false; EnvironmentMode environment_mode = ENVIRONMENT_MODE_SCENE; @@ -284,6 +286,9 @@ public: void set_bias(float p_bias); float get_bias() const; + void set_texel_scale(float p_multiplier); + float get_texel_scale() const; + void set_max_texture_size(int p_size); int get_max_texture_size() const; diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 94c0a2279a..fa5c8f820d 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -258,7 +258,7 @@ void NavigationRegion3D::bake_navigation_mesh(bool p_on_thread) { void NavigationRegion3D::_bake_finished(Ref<NavigationMesh> p_navigation_mesh) { if (!Thread::is_main_thread()) { - call_deferred(SNAME("_bake_finished"), p_navigation_mesh); + callable_mp(this, &NavigationRegion3D::_bake_finished).call_deferred(p_navigation_mesh); return; } @@ -308,7 +308,6 @@ void NavigationRegion3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationRegion3D::get_travel_cost); ClassDB::bind_method(D_METHOD("bake_navigation_mesh", "on_thread"), &NavigationRegion3D::bake_navigation_mesh, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("_bake_finished", "navigation_mesh"), &NavigationRegion3D::_bake_finished); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_mesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index cb8279d534..c4d1e6bef7 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -30,7 +30,6 @@ #include "node_3d.h" -#include "core/object/message_queue.h" #include "scene/3d/visual_instance_3d.h" #include "scene/main/viewport.h" #include "scene/property_utils.h" @@ -124,7 +123,7 @@ void Node3D::_propagate_transform_changed(Node3D *p_origin) { get_tree()->xform_change_list.add(&xform_change); } else { // This should very rarely happen, but if it does at least make sure the notification is received eventually. - MessageQueue::get_singleton()->push_callable(callable_mp(this, &Node3D::_propagate_transform_changed_deferred)); + callable_mp(this, &Node3D::_propagate_transform_changed_deferred).call_deferred(); } } _set_dirty_bits(DIRTY_GLOBAL_TRANSFORM); @@ -568,7 +567,7 @@ void Node3D::update_gizmos() { return; } data.gizmos_dirty = true; - MessageQueue::get_singleton()->push_callable(callable_mp(this, &Node3D::_update_gizmos)); + callable_mp(this, &Node3D::_update_gizmos).call_deferred(); #endif } diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 445c1003b5..ec5f8187a9 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -30,7 +30,6 @@ #include "skeleton_3d.h" -#include "core/object/message_queue.h" #include "core/variant/type_info.h" #include "scene/3d/physics_body_3d.h" #include "scene/resources/surface_tool.h" diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index db2c0e1387..3f1878f30f 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -416,8 +416,8 @@ void SoftBody3D::_draw_soft_mesh() { /// Necessary in order to render the mesh correctly (Soft body nodes are in global space) simulation_started = true; - call_deferred(SNAME("set_as_top_level"), true); - call_deferred(SNAME("set_transform"), Transform3D()); + callable_mp((Node3D *)this, &Node3D::set_as_top_level).call_deferred(true); + callable_mp((Node3D *)this, &Node3D::set_transform).call_deferred(Transform3D()); } _update_physics_server(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index b8b0d31d45..8e76e75d0e 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -1439,14 +1439,16 @@ PackedStringArray AnimatedSprite3D::get_configuration_warnings() const { } void AnimatedSprite3D::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { - if (p_idx == 0 && p_function == "play" && frames.is_valid()) { - List<StringName> al; - frames->get_animation_list(&al); - for (const StringName &name : al) { - r_options->push_back(String(name).quote()); + if (p_idx == 0 && frames.is_valid()) { + if (p_function == "play" || p_function == "play_backwards" || p_function == "set_animation" || p_function == "set_autoplay") { + List<StringName> al; + frames->get_animation_list(&al); + for (const StringName &name : al) { + r_options->push_back(String(name).quote()); + } } } - Node::get_argument_options(p_function, p_idx, r_options); + SpriteBase3D::get_argument_options(p_function, p_idx, r_options); } #ifndef DISABLE_DEPRECATED diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 33f865382d..503c39ae3e 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -250,7 +250,7 @@ GeometryInstance3D::VisibilityRangeFadeMode GeometryInstance3D::get_visibility_r return visibility_range_fade_mode; } -const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringName p_name) const { +const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringName &p_name) const { StringName *r = instance_shader_parameter_property_remap.getptr(p_name); if (!r) { String s = p_name; diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index ef0f7966e2..59ede26ac1 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -135,7 +135,7 @@ private: GIMode gi_mode = GI_MODE_STATIC; bool ignore_occlusion_culling = false; - const StringName *_instance_uniform_get_remap(const StringName p_name) const; + const StringName *_instance_uniform_get_remap(const StringName &p_name) const; protected: bool _set(const StringName &p_name, const Variant &p_value); diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index c12e78eddc..70e32c1a31 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -58,13 +58,13 @@ void XRCamera3D::_unbind_tracker() { tracker.unref(); } -void XRCamera3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_type) { +void XRCamera3D::_changed_tracker(const StringName &p_tracker_name, int p_tracker_type) { if (p_tracker_name == tracker_name) { _bind_tracker(); } } -void XRCamera3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_type) { +void XRCamera3D::_removed_tracker(const StringName &p_tracker_name, int p_tracker_type) { if (p_tracker_name == tracker_name) { _unbind_tracker(); } @@ -258,7 +258,7 @@ void XRNode3D::_validate_property(PropertyInfo &p_property) const { } } -void XRNode3D::set_tracker(const StringName p_tracker_name) { +void XRNode3D::set_tracker(const StringName &p_tracker_name) { if (tracker.is_valid() && tracker->get_tracker_name() == p_tracker_name) { // didn't change return; @@ -282,7 +282,7 @@ StringName XRNode3D::get_tracker() const { return tracker_name; } -void XRNode3D::set_pose_name(const StringName p_pose_name) { +void XRNode3D::set_pose_name(const StringName &p_pose_name) { pose_name = p_pose_name; // Update pose if we are bound to a tracker with a valid pose @@ -363,7 +363,7 @@ void XRNode3D::_unbind_tracker() { } } -void XRNode3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_type) { +void XRNode3D::_changed_tracker(const StringName &p_tracker_name, int p_tracker_type) { if (tracker_name == p_tracker_name) { // just in case unref our current tracker _unbind_tracker(); @@ -373,7 +373,7 @@ void XRNode3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_t } } -void XRNode3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_type) { +void XRNode3D::_removed_tracker(const StringName &p_tracker_name, int p_tracker_type) { if (tracker_name == p_tracker_name) { // unref our tracker, it's no longer available _unbind_tracker(); diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h index 185a6361d3..ad52cf113d 100644 --- a/scene/3d/xr_nodes.h +++ b/scene/3d/xr_nodes.h @@ -50,8 +50,8 @@ protected: void _bind_tracker(); void _unbind_tracker(); - void _changed_tracker(const StringName p_tracker_name, int p_tracker_type); - void _removed_tracker(const StringName p_tracker_name, int p_tracker_type); + void _changed_tracker(const StringName &p_tracker_name, int p_tracker_type); + void _removed_tracker(const StringName &p_tracker_name, int p_tracker_type); void _pose_changed(const Ref<XRPose> &p_pose); public: @@ -87,8 +87,8 @@ protected: virtual void _bind_tracker(); virtual void _unbind_tracker(); - void _changed_tracker(const StringName p_tracker_name, int p_tracker_type); - void _removed_tracker(const StringName p_tracker_name, int p_tracker_type); + void _changed_tracker(const StringName &p_tracker_name, int p_tracker_type); + void _removed_tracker(const StringName &p_tracker_name, int p_tracker_type); void _pose_changed(const Ref<XRPose> &p_pose); void _pose_lost_tracking(const Ref<XRPose> &p_pose); @@ -96,10 +96,10 @@ protected: public: void _validate_property(PropertyInfo &p_property) const; - void set_tracker(const StringName p_tracker_name); + void set_tracker(const StringName &p_tracker_name); StringName get_tracker() const; - void set_pose_name(const StringName p_pose); + void set_pose_name(const StringName &p_pose); StringName get_pose_name() const; bool get_is_active() const; diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index 37c360b8f8..dbec2be0ba 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -332,7 +332,7 @@ void AnimationNodeBlendSpace2D::_queue_auto_triangles() { } trianges_dirty = true; - call_deferred(SNAME("_update_triangles")); + callable_mp(this, &AnimationNodeBlendSpace2D::_update_triangles).call_deferred(); } void AnimationNodeBlendSpace2D::_update_triangles() { @@ -689,8 +689,6 @@ void AnimationNodeBlendSpace2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace2D::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace2D::is_using_sync); - ClassDB::bind_method(D_METHOD("_update_triangles"), &AnimationNodeBlendSpace2D::_update_triangles); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_auto_triangles", "get_auto_triangles"); for (int i = 0; i < MAX_BLEND_POINTS; i++) { diff --git a/scene/animation/animation_mixer.compat.inc b/scene/animation/animation_mixer.compat.inc new file mode 100644 index 0000000000..09c7d7a977 --- /dev/null +++ b/scene/animation/animation_mixer.compat.inc @@ -0,0 +1,44 @@ +/**************************************************************************/ +/* animation_mixer.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +Variant AnimationMixer::_post_process_key_value_bind_compat_86687(const Ref<Animation> &p_anim, int p_track, Variant p_value, Object *p_object, int p_object_idx) { + if (!p_object) { + return Variant(); + } + return _post_process_key_value(p_anim, p_track, p_value, p_object->get_instance_id(), p_object_idx); +} + +void AnimationMixer::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("_post_process_key_value_bind_compat", "animation", "track", "value", "object", "object_idx"), &AnimationMixer::_post_process_key_value_bind_compat_86687); +} + +#endif // DISABLE_DEPRECATED diff --git a/scene/animation/animation_mixer.cpp b/scene/animation/animation_mixer.cpp index da00d1dd7b..2adb3695a7 100644 --- a/scene/animation/animation_mixer.cpp +++ b/scene/animation/animation_mixer.cpp @@ -29,8 +29,12 @@ /**************************************************************************/ #include "animation_mixer.h" +#include "animation_mixer.compat.inc" #include "core/config/engine.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" #include "scene/resources/animation.h" #include "scene/scene_string_names.h" @@ -543,7 +547,7 @@ void AnimationMixer::_clear_caches() { _init_root_motion_cache(); _clear_audio_streams(); _clear_playing_caches(); - for (KeyValue<NodePath, TrackCache *> &K : track_cache) { + for (KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) { memdelete(K.value); } track_cache.clear(); @@ -562,8 +566,9 @@ void AnimationMixer::_clear_audio_streams() { void AnimationMixer::_clear_playing_caches() { for (const TrackCache *E : playing_caches) { - if (ObjectDB::get_instance(E->object_id)) { - E->object->call(SNAME("stop"), true); + Object *t_obj = ObjectDB::get_instance(E->object_id); + if (t_obj) { + t_obj->call(SNAME("stop"), true); } } playing_caches.clear(); @@ -606,23 +611,20 @@ bool AnimationMixer::_update_caches() { Ref<Animation> anim = get_animation(E); for (int i = 0; i < anim->get_track_count(); i++) { NodePath path = anim->track_get_path(i); - Animation::TrackType track_type = anim->track_get_type(i); - - Animation::TrackType track_cache_type = track_type; - if (track_cache_type == Animation::TYPE_POSITION_3D || track_cache_type == Animation::TYPE_ROTATION_3D || track_cache_type == Animation::TYPE_SCALE_3D) { - track_cache_type = Animation::TYPE_POSITION_3D; // Reference them as position3D tracks, even if they modify rotation or scale. - } + Animation::TypeHash thash = anim->track_get_type_hash(i); + Animation::TrackType track_src_type = anim->track_get_type(i); + Animation::TrackType track_cache_type = Animation::get_cache_type(track_src_type); TrackCache *track = nullptr; - if (track_cache.has(path)) { - track = track_cache.get(path); + if (track_cache.has(thash)) { + track = track_cache.get(thash); } // If not valid, delete track. if (track && (track->type != track_cache_type || ObjectDB::get_instance(track->object_id) == nullptr)) { playing_caches.erase(track); memdelete(track); - track_cache.erase(path); + track_cache.erase(thash); track = nullptr; } @@ -636,7 +638,8 @@ bool AnimationMixer::_update_caches() { continue; } - switch (track_type) { + switch (track_src_type) { + case Animation::TYPE_BEZIER: case Animation::TYPE_VALUE: { // If a value track without a key is cached first, the initial value cannot be determined. // It is a corner case, but which may cause problems with blending. @@ -645,16 +648,20 @@ bool AnimationMixer::_update_caches() { TrackCacheValue *track_value = memnew(TrackCacheValue); if (resource.is_valid()) { - track_value->object = resource.ptr(); + track_value->object_id = resource->get_instance_id(); } else { - track_value->object = child; + track_value->object_id = child->get_instance_id(); } - track_value->is_continuous = anim->value_track_get_update_mode(i) != Animation::UPDATE_DISCRETE; - track_value->is_using_angle = anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; + if (track_src_type == Animation::TYPE_VALUE) { + track_value->is_continuous = anim->value_track_get_update_mode(i) != Animation::UPDATE_DISCRETE; + track_value->is_using_angle = anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; + } else { + track_value->is_continuous = true; + track_value->is_using_angle = false; + } track_value->subpath = leftover_path; - track_value->object_id = track_value->object->get_instance_id(); track = track_value; @@ -663,9 +670,9 @@ bool AnimationMixer::_update_caches() { // If there is a Reset Animation, it takes precedence by overwriting. if (has_reset_anim) { - int rt = reset_anim->find_track(path, track_type); + int rt = reset_anim->find_track(path, track_src_type); if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { - track_value->init_value = reset_anim->track_get_key_value(rt, 0); + track_value->init_value = track_src_type == Animation::TYPE_VALUE ? reset_anim->track_get_key_value(rt, 0) : (reset_anim->track_get_key_value(rt, 0).operator Array())[0]; } } @@ -684,14 +691,12 @@ bool AnimationMixer::_update_caches() { TrackCacheTransform *track_xform = memnew(TrackCacheTransform); track_xform->type = Animation::TYPE_POSITION_3D; - track_xform->node_3d = node_3d; - track_xform->skeleton = nullptr; track_xform->bone_idx = -1; bool has_rest = false; - if (path.get_subname_count() == 1 && Object::cast_to<Skeleton3D>(node_3d)) { - Skeleton3D *sk = Object::cast_to<Skeleton3D>(node_3d); - track_xform->skeleton = sk; + Skeleton3D *sk = Object::cast_to<Skeleton3D>(node_3d); + if (sk && path.get_subname_count() == 1) { + track_xform->skeleton_id = sk->get_instance_id(); int bone_idx = sk->find_bone(path.get_subname(0)); if (bone_idx != -1) { has_rest = true; @@ -703,12 +708,11 @@ bool AnimationMixer::_update_caches() { } } - track_xform->object = node_3d; - track_xform->object_id = track_xform->object->get_instance_id(); + track_xform->object_id = node_3d->get_instance_id(); track = track_xform; - switch (track_type) { + switch (track_src_type) { case Animation::TYPE_POSITION_3D: { track_xform->loc_used = true; } break; @@ -724,9 +728,9 @@ bool AnimationMixer::_update_caches() { // For non Skeleton3D bone animation. if (has_reset_anim && !has_rest) { - int rt = reset_anim->find_track(path, track_type); + int rt = reset_anim->find_track(path, track_src_type); if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { - switch (track_type) { + switch (track_src_type) { case Animation::TYPE_POSITION_3D: { track_xform->init_loc = reset_anim->track_get_key_value(rt, 0); } break; @@ -765,15 +769,12 @@ bool AnimationMixer::_update_caches() { TrackCacheBlendShape *track_bshape = memnew(TrackCacheBlendShape); - track_bshape->mesh_3d = mesh_3d; track_bshape->shape_index = blend_shape_idx; - - track_bshape->object = mesh_3d; track_bshape->object_id = mesh_3d->get_instance_id(); track = track_bshape; if (has_reset_anim) { - int rt = reset_anim->find_track(path, track_type); + int rt = reset_anim->find_track(path, track_src_type); if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { track_bshape->init_value = reset_anim->track_get_key_value(rt, 0); } @@ -784,43 +785,18 @@ bool AnimationMixer::_update_caches() { TrackCacheMethod *track_method = memnew(TrackCacheMethod); if (resource.is_valid()) { - track_method->object = resource.ptr(); + track_method->object_id = resource->get_instance_id(); } else { - track_method->object = child; + track_method->object_id = child->get_instance_id(); } - track_method->object_id = track_method->object->get_instance_id(); - track = track_method; } break; - case Animation::TYPE_BEZIER: { - TrackCacheBezier *track_bezier = memnew(TrackCacheBezier); - - if (resource.is_valid()) { - track_bezier->object = resource.ptr(); - } else { - track_bezier->object = child; - } - - track_bezier->subpath = leftover_path; - track_bezier->object_id = track_bezier->object->get_instance_id(); - - track = track_bezier; - - if (has_reset_anim) { - int rt = reset_anim->find_track(path, track_type); - if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { - track_bezier->init_value = (reset_anim->track_get_key_value(rt, 0).operator Array())[0]; - } - } - - } break; case Animation::TYPE_AUDIO: { TrackCacheAudio *track_audio = memnew(TrackCacheAudio); - track_audio->object = child; - track_audio->object_id = track_audio->object->get_instance_id(); + track_audio->object_id = child->get_instance_id(); track_audio->audio_stream.instantiate(); track_audio->audio_stream->set_polyphony(audio_max_polyphony); @@ -830,8 +806,7 @@ bool AnimationMixer::_update_caches() { case Animation::TYPE_ANIMATION: { TrackCacheAnimation *track_animation = memnew(TrackCacheAnimation); - track_animation->object = child; - track_animation->object_id = track_animation->object->get_instance_id(); + track_animation->object_id = child->get_instance_id(); track = track_animation; @@ -841,8 +816,8 @@ bool AnimationMixer::_update_caches() { continue; } } - - track_cache[path] = track; + track->path = path; + track_cache[thash] = track; } else if (track_cache_type == Animation::TYPE_POSITION_3D) { TrackCacheTransform *track_xform = static_cast<TrackCacheTransform *>(track); if (track->setup_pass != setup_pass) { @@ -850,7 +825,7 @@ bool AnimationMixer::_update_caches() { track_xform->rot_used = false; track_xform->scale_used = false; } - switch (track_type) { + switch (track_src_type) { case Animation::TYPE_POSITION_3D: { track_xform->loc_used = true; } break; @@ -868,8 +843,13 @@ bool AnimationMixer::_update_caches() { TrackCacheValue *track_value = static_cast<TrackCacheValue *>(track); bool was_continuous = track_value->is_continuous; bool was_using_angle = track_value->is_using_angle; - track_value->is_continuous |= anim->value_track_get_update_mode(i) != Animation::UPDATE_DISCRETE; - track_value->is_using_angle |= anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; + + if (track_src_type == Animation::TYPE_VALUE) { + track_value->is_continuous |= anim->value_track_get_update_mode(i) != Animation::UPDATE_DISCRETE; + track_value->is_using_angle |= anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; + } else { + track_value->is_continuous |= true; + } // TODO: Currently, misc type cannot be blended. // In the future, it should have a separate blend weight, just as bool is converted to 0 and 1. @@ -898,27 +878,26 @@ bool AnimationMixer::_update_caches() { } } - List<NodePath> to_delete; + List<Animation::TypeHash> to_delete; - for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { - TrackCache *tc = track_cache[K.key]; - if (tc->setup_pass != setup_pass) { + for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) { + if (K.value->setup_pass != setup_pass) { to_delete.push_back(K.key); } } while (to_delete.front()) { - NodePath np = to_delete.front()->get(); - memdelete(track_cache[np]); - track_cache.erase(np); + Animation::TypeHash thash = to_delete.front()->get(); + memdelete(track_cache[thash]); + track_cache.erase(thash); to_delete.pop_front(); } track_map.clear(); int idx = 0; - for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { - track_map[K.key] = idx; + for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) { + track_map[K.value->path] = idx; idx++; } @@ -944,28 +923,30 @@ void AnimationMixer::_process_animation(double p_delta, bool p_update_only) { clear_animation_instances(); } -Variant AnimationMixer::post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) { +Variant AnimationMixer::post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx) { Variant res; - if (GDVIRTUAL_CALL(_post_process_key_value, p_anim, p_track, p_value, const_cast<Object *>(p_object), p_object_idx, res)) { + if (GDVIRTUAL_CALL(_post_process_key_value, p_anim, p_track, p_value, p_object_id, p_object_sub_idx, res)) { return res; } - return _post_process_key_value(p_anim, p_track, p_value, p_object, p_object_idx); + return _post_process_key_value(p_anim, p_track, p_value, p_object_id, p_object_sub_idx); } -Variant AnimationMixer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) { - switch (p_anim->track_get_type(p_track)) { +Variant AnimationMixer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx) { #ifndef _3D_DISABLED + switch (p_anim->track_get_type(p_track)) { case Animation::TYPE_POSITION_3D: { - if (p_object_idx >= 0) { - const Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_object); - return Vector3(p_value) * skel->get_motion_scale(); + if (p_object_sub_idx >= 0) { + Skeleton3D *skel = Object::cast_to<Skeleton3D>(ObjectDB::get_instance(p_object_id)); + if (skel) { + return Vector3(p_value) * skel->get_motion_scale(); + } } return p_value; } break; -#endif // _3D_DISABLED default: { } break; } +#endif // _3D_DISABLED return p_value; } @@ -985,7 +966,7 @@ void AnimationMixer::_blend_init() { } // Init all value/transform/blend/bezier tracks that track_cache has. - for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) { TrackCache *track = K.value; track->total_weight = 0.0; @@ -1011,10 +992,6 @@ void AnimationMixer::_blend_init() { t->value = Animation::cast_to_blendwise(t->init_value); t->element_size = t->init_value.is_string() ? (real_t)(t->init_value.operator String()).length() : 0; } break; - case Animation::TYPE_BEZIER: { - TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track); - t->value = t->init_value; - } break; case Animation::TYPE_AUDIO: { TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track); for (KeyValue<ObjectID, PlayingAudioTrackInfo> &L : t->playing_streams) { @@ -1046,12 +1023,12 @@ void AnimationMixer::_blend_calc_total_weight() { if (!a->track_is_enabled(i)) { continue; } - NodePath path = a->track_get_path(i); - if (!track_cache.has(path)) { + Animation::TypeHash thash = a->track_get_type_hash(i); + if (!track_cache.has(thash)) { continue; // No path, but avoid error spamming. } - TrackCache *track = track_cache[path]; - int blend_idx = track_map[path]; + TrackCache *track = track_cache[thash]; + int blend_idx = track_map[track->path]; if (processed_indices.has(blend_idx)) { continue; // There is the case different track type with same path... Is there more faster iterating way than has()? } @@ -1086,13 +1063,13 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (!a->track_is_enabled(i)) { continue; } - NodePath path = a->track_get_path(i); - if (!track_cache.has(path)) { + Animation::TypeHash thash = a->track_get_type_hash(i); + if (!track_cache.has(thash)) { continue; // No path, but avoid error spamming. } - TrackCache *track = track_cache[path]; - ERR_CONTINUE(!track_map.has(path)); - int blend_idx = track_map[path]; + TrackCache *track = track_cache[thash]; + ERR_CONTINUE(!track_map.has(track->path)); + int blend_idx = track_map[track->path]; ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count); real_t blend = blend_idx < track_weights.size() ? track_weights[blend_idx] * weight : weight; if (!deterministic) { @@ -1104,11 +1081,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { blend = blend / track->total_weight; } Animation::TrackType ttype = a->track_get_type(i); - if (ttype != Animation::TYPE_POSITION_3D && ttype != Animation::TYPE_ROTATION_3D && ttype != Animation::TYPE_SCALE_3D && track->type != ttype) { - // Broken animation, but avoid error spamming. - continue; - } - track->root_motion = root_motion_track == path; + track->root_motion = root_motion_track == a->track_get_path(i); switch (ttype) { case Animation::TYPE_POSITION_3D: { #ifndef _3D_DISABLED @@ -1158,9 +1131,9 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx); + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); a->try_position_track_interpolate(i, (double)a->get_length(), &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); root_motion_cache.loc += (loc[1] - loc[0]) * blend; prev_time = 0; } @@ -1170,9 +1143,9 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx); + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); a->try_position_track_interpolate(i, 0, &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); root_motion_cache.loc += (loc[1] - loc[0]) * blend; prev_time = (double)a->get_length(); } @@ -1181,9 +1154,9 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx); + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); a->try_position_track_interpolate(i, time, &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); root_motion_cache.loc += (loc[1] - loc[0]) * blend; prev_time = !backward ? 0 : (double)a->get_length(); } @@ -1193,7 +1166,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - loc = post_process_key_value(a, i, loc, t->object, t->bone_idx); + loc = post_process_key_value(a, i, loc, t->object_id, t->bone_idx); t->loc += (loc - t->init_loc) * blend; } #endif // _3D_DISABLED @@ -1246,9 +1219,9 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - rot[0] = post_process_key_value(a, i, rot[0], t->object, t->bone_idx); + rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx); a->try_rotation_track_interpolate(i, (double)a->get_length(), &rot[1]); - rot[1] = post_process_key_value(a, i, rot[1], t->object, t->bone_idx); + rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx); root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = 0; } @@ -1258,7 +1231,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - rot[0] = post_process_key_value(a, i, rot[0], t->object, t->bone_idx); + rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx); a->try_rotation_track_interpolate(i, 0, &rot[1]); root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = (double)a->get_length(); @@ -1268,9 +1241,9 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - rot[0] = post_process_key_value(a, i, rot[0], t->object, t->bone_idx); + rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx); a->try_rotation_track_interpolate(i, time, &rot[1]); - rot[1] = post_process_key_value(a, i, rot[1], t->object, t->bone_idx); + rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx); root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = !backward ? 0 : (double)a->get_length(); } @@ -1280,7 +1253,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - rot = post_process_key_value(a, i, rot, t->object, t->bone_idx); + rot = post_process_key_value(a, i, rot, t->object_id, t->bone_idx); t->rot = (t->rot * Quaternion().slerp(t->init_rot.inverse() * rot, blend)).normalized(); } #endif // _3D_DISABLED @@ -1333,10 +1306,10 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - scale[0] = post_process_key_value(a, i, scale[0], t->object, t->bone_idx); + scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx); a->try_scale_track_interpolate(i, (double)a->get_length(), &scale[1]); root_motion_cache.scale += (scale[1] - scale[0]) * blend; - scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx); + scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx); prev_time = 0; } } else { @@ -1345,9 +1318,9 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - scale[0] = post_process_key_value(a, i, scale[0], t->object, t->bone_idx); + scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx); a->try_scale_track_interpolate(i, 0, &scale[1]); - scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx); + scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx); root_motion_cache.scale += (scale[1] - scale[0]) * blend; prev_time = (double)a->get_length(); } @@ -1356,9 +1329,9 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - scale[0] = post_process_key_value(a, i, scale[0], t->object, t->bone_idx); + scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx); a->try_scale_track_interpolate(i, time, &scale[1]); - scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx); + scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx); root_motion_cache.scale += (scale[1] - scale[0]) * blend; prev_time = !backward ? 0 : (double)a->get_length(); } @@ -1368,7 +1341,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - scale = post_process_key_value(a, i, scale, t->object, t->bone_idx); + scale = post_process_key_value(a, i, scale, t->object_id, t->bone_idx); t->scale += (scale - t->init_scale) * blend; } #endif // _3D_DISABLED @@ -1385,18 +1358,19 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (err != OK) { continue; } - value = post_process_key_value(a, i, value, t->object, t->shape_index); + value = post_process_key_value(a, i, value, t->object_id, t->shape_index); t->value += (value - t->init_value) * blend; #endif // _3D_DISABLED } break; + case Animation::TYPE_BEZIER: case Animation::TYPE_VALUE: { if (Math::is_zero_approx(blend)) { continue; // Nothing to blend. } TrackCacheValue *t = static_cast<TrackCacheValue *>(track); if (t->is_continuous) { - Variant value = a->value_track_interpolate(i, time); - value = post_process_key_value(a, i, value, t->object); + Variant value = ttype == Animation::TYPE_VALUE ? a->value_track_interpolate(i, time) : Variant(a->bezier_track_interpolate(i, time)); + value = post_process_key_value(a, i, value, t->object_id); if (value == Variant()) { continue; } @@ -1436,15 +1410,21 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { continue; } Variant value = a->track_get_key_value(i, idx); - value = post_process_key_value(a, i, value, t->object); - t->object->set_indexed(t->subpath, value); + value = post_process_key_value(a, i, value, t->object_id); + Object *t_obj = ObjectDB::get_instance(t->object_id); + if (t_obj) { + t_obj->set_indexed(t->subpath, value); + } } else { List<int> indices; a->track_get_key_indices_in_range(i, time, delta, &indices, looped_flag); for (int &F : indices) { Variant value = a->track_get_key_value(i, F); - value = post_process_key_value(a, i, value, t->object); - t->object->set_indexed(t->subpath, value); + value = post_process_key_value(a, i, value, t->object_id); + Object *t_obj = ObjectDB::get_instance(t->object_id); + if (t_obj) { + t_obj->set_indexed(t->subpath, value); + } } } } @@ -1466,31 +1446,23 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } StringName method = a->method_track_get_name(i, idx); Vector<Variant> params = a->method_track_get_params(i, idx); - _call_object(t->object, method, params, callback_mode_method == ANIMATION_CALLBACK_MODE_METHOD_DEFERRED); + _call_object(t->object_id, method, params, callback_mode_method == ANIMATION_CALLBACK_MODE_METHOD_DEFERRED); } else { List<int> indices; a->track_get_key_indices_in_range(i, time, delta, &indices, looped_flag); for (int &F : indices) { StringName method = a->method_track_get_name(i, F); Vector<Variant> params = a->method_track_get_params(i, F); - _call_object(t->object, method, params, callback_mode_method == ANIMATION_CALLBACK_MODE_METHOD_DEFERRED); + _call_object(t->object_id, method, params, callback_mode_method == ANIMATION_CALLBACK_MODE_METHOD_DEFERRED); } } } break; - case Animation::TYPE_BEZIER: { - if (Math::is_zero_approx(blend)) { - continue; // Nothing to blend. - } - TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track); - real_t bezier = a->bezier_track_interpolate(i, time); - bezier = post_process_key_value(a, i, bezier, t->object); - t->value += (bezier - t->init_value) * blend; - } break; case Animation::TYPE_AUDIO: { // The end of audio should be observed even if the blend value is 0, build up the information and store to the cache for that. TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track); - Node *asp = Object::cast_to<Node>(t->object); - if (!asp) { + Object *t_obj = ObjectDB::get_instance(t->object_id); + Node *asp = t_obj ? Object::cast_to<Node>(t_obj) : nullptr; + if (!t_obj || !asp) { t->playing_streams.clear(); continue; } @@ -1540,22 +1512,22 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { if (seeked) { start_ofs += time - a->track_get_key_time(i, idx); } - if (t->object->call(SNAME("get_stream")) != t->audio_stream) { - t->object->call(SNAME("set_stream"), t->audio_stream); + if (t_obj->call(SNAME("get_stream")) != t->audio_stream) { + t_obj->call(SNAME("set_stream"), t->audio_stream); t->audio_stream_playback.unref(); if (!playing_audio_stream_players.has(asp)) { playing_audio_stream_players.push_back(asp); } } - if (!t->object->call(SNAME("is_playing"))) { - t->object->call(SNAME("play")); + if (!t_obj->call(SNAME("is_playing"))) { + t_obj->call(SNAME("play")); } - if (!t->object->call(SNAME("has_stream_playback"))) { + if (!t_obj->call(SNAME("has_stream_playback"))) { t->audio_stream_playback.unref(); continue; } if (t->audio_stream_playback.is_null()) { - t->audio_stream_playback = t->object->call(SNAME("get_stream_playback")); + t->audio_stream_playback = t_obj->call(SNAME("get_stream_playback")); } PlayingAudioStreamInfo pasi; pasi.index = t->audio_stream_playback->play_stream(stream, start_ofs); @@ -1573,7 +1545,11 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { continue; } TrackCacheAnimation *t = static_cast<TrackCacheAnimation *>(track); - AnimationPlayer *player2 = Object::cast_to<AnimationPlayer>(t->object); + Object *t_obj = ObjectDB::get_instance(t->object_id); + if (!t_obj) { + continue; + } + AnimationPlayer *player2 = Object::cast_to<AnimationPlayer>(t_obj); if (!player2) { continue; } @@ -1640,7 +1616,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { void AnimationMixer::_blend_apply() { // Finally, set the tracks. - for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) { TrackCache *track = K.value; if (!deterministic && Math::is_zero_approx(track->total_weight)) { continue; @@ -1657,26 +1633,34 @@ void AnimationMixer::_blend_apply() { root_motion_position_accumulator = t->loc; root_motion_rotation_accumulator = t->rot; root_motion_scale_accumulator = t->scale; - } else if (t->skeleton && t->bone_idx >= 0) { + } else if (t->skeleton_id.is_valid() && t->bone_idx >= 0) { + Skeleton3D *t_skeleton = Object::cast_to<Skeleton3D>(ObjectDB::get_instance(t->skeleton_id)); + if (!t_skeleton) { + return; + } if (t->loc_used) { - t->skeleton->set_bone_pose_position(t->bone_idx, t->loc); + t_skeleton->set_bone_pose_position(t->bone_idx, t->loc); } if (t->rot_used) { - t->skeleton->set_bone_pose_rotation(t->bone_idx, t->rot); + t_skeleton->set_bone_pose_rotation(t->bone_idx, t->rot); } if (t->scale_used) { - t->skeleton->set_bone_pose_scale(t->bone_idx, t->scale); + t_skeleton->set_bone_pose_scale(t->bone_idx, t->scale); } - } else if (!t->skeleton) { + } else if (!t->skeleton_id.is_valid()) { + Node3D *t_node_3d = Object::cast_to<Node3D>(ObjectDB::get_instance(t->object_id)); + if (!t_node_3d) { + return; + } if (t->loc_used) { - t->node_3d->set_position(t->loc); + t_node_3d->set_position(t->loc); } if (t->rot_used) { - t->node_3d->set_rotation(t->rot.get_euler()); + t_node_3d->set_rotation(t->rot.get_euler()); } if (t->scale_used) { - t->node_3d->set_scale(t->scale); + t_node_3d->set_scale(t->scale); } } #endif // _3D_DISABLED @@ -1685,8 +1669,9 @@ void AnimationMixer::_blend_apply() { #ifndef _3D_DISABLED TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track); - if (t->mesh_3d) { - t->mesh_3d->set_blend_shape_value(t->shape_index, t->value); + MeshInstance3D *t_mesh_3d = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(t->object_id)); + if (t_mesh_3d) { + t_mesh_3d->set_blend_shape_value(t->shape_index, t->value); } #endif // _3D_DISABLED } break; @@ -1710,19 +1695,12 @@ void AnimationMixer::_blend_apply() { } } - // t->object isn't safe here, get instance from id (GH-85365). - Object *obj = ObjectDB::get_instance(t->object_id); - if (obj) { - obj->set_indexed(t->subpath, Animation::cast_from_blendwise(t->value, t->init_value.get_type())); + Object *t_obj = ObjectDB::get_instance(t->object_id); + if (t_obj) { + t_obj->set_indexed(t->subpath, Animation::cast_from_blendwise(t->value, t->init_value.get_type())); } } break; - case Animation::TYPE_BEZIER: { - TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track); - - t->object->set_indexed(t->subpath, t->value); - - } break; case Animation::TYPE_AUDIO: { TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track); @@ -1787,7 +1765,7 @@ void AnimationMixer::_blend_apply() { } } -void AnimationMixer::_call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) { +void AnimationMixer::_call_object(ObjectID p_object_id, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) { // Separate function to use alloca() more efficiently const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * p_params.size()); const Variant *args = p_params.ptr(); @@ -1795,11 +1773,15 @@ void AnimationMixer::_call_object(Object *p_object, const StringName &p_method, for (uint32_t i = 0; i < argcount; i++) { argptrs[i] = &args[i]; } + Object *t_obj = ObjectDB::get_instance(p_object_id); + if (!t_obj) { + return; + } if (p_deferred) { - MessageQueue::get_singleton()->push_callp(p_object, p_method, argptrs, argcount); + Callable(t_obj, p_method).call_deferredp(argptrs, argcount); } else { Callable::CallError ce; - p_object->callp(p_method, argptrs, argcount, ce); + t_obj->callp(p_method, argptrs, argcount, ce); } } @@ -1879,7 +1861,7 @@ bool AnimationMixer::can_apply_reset() const { } void AnimationMixer::_build_backup_track_cache() { - for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) { TrackCache *track = K.value; track->total_weight = 1.0; switch (track->type) { @@ -1888,25 +1870,33 @@ void AnimationMixer::_build_backup_track_cache() { TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); if (t->root_motion) { // Do nothing. - } else if (t->skeleton && t->bone_idx >= 0) { + } else if (t->skeleton_id.is_valid() && t->bone_idx >= 0) { + Skeleton3D *t_skeleton = Object::cast_to<Skeleton3D>(ObjectDB::get_instance(t->skeleton_id)); + if (!t_skeleton) { + return; + } if (t->loc_used) { - t->loc = t->skeleton->get_bone_pose_position(t->bone_idx); + t->loc = t_skeleton->get_bone_pose_position(t->bone_idx); } if (t->rot_used) { - t->rot = t->skeleton->get_bone_pose_rotation(t->bone_idx); + t->rot = t_skeleton->get_bone_pose_rotation(t->bone_idx); } if (t->scale_used) { - t->scale = t->skeleton->get_bone_pose_scale(t->bone_idx); + t->scale = t_skeleton->get_bone_pose_scale(t->bone_idx); + } + } else if (!t->skeleton_id.is_valid()) { + Node3D *t_node_3d = Object::cast_to<Node3D>(ObjectDB::get_instance(t->object_id)); + if (!t_node_3d) { + return; } - } else if (!t->skeleton) { if (t->loc_used) { - t->loc = t->node_3d->get_position(); + t->loc = t_node_3d->get_position(); } if (t->rot_used) { - t->rot = t->node_3d->get_quaternion(); + t->rot = t_node_3d->get_quaternion(); } if (t->scale_used) { - t->scale = t->node_3d->get_scale(); + t->scale = t_node_3d->get_scale(); } } #endif // _3D_DISABLED @@ -1914,25 +1904,28 @@ void AnimationMixer::_build_backup_track_cache() { case Animation::TYPE_BLEND_SHAPE: { #ifndef _3D_DISABLED TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track); - if (t->mesh_3d) { - t->value = t->mesh_3d->get_blend_shape_value(t->shape_index); + MeshInstance3D *t_mesh_3d = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(t->object_id)); + if (t_mesh_3d) { + t->value = t_mesh_3d->get_blend_shape_value(t->shape_index); } #endif // _3D_DISABLED } break; case Animation::TYPE_VALUE: { TrackCacheValue *t = static_cast<TrackCacheValue *>(track); - t->value = t->object->get_indexed(t->subpath); + Object *t_obj = ObjectDB::get_instance(t->object_id); + if (t_obj) { + t->value = t_obj->get_indexed(t->subpath); + } t->is_continuous = true; } break; - case Animation::TYPE_BEZIER: { - TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track); - t->value = t->object->get_indexed(t->subpath); - } break; case Animation::TYPE_AUDIO: { TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track); - Node *asp = Object::cast_to<Node>(t->object); - if (asp) { - t->object->call(SNAME("set_stream"), Ref<AudioStream>()); + Object *t_obj = ObjectDB::get_instance(t->object_id); + if (t_obj) { + Node *asp = Object::cast_to<Node>(t_obj); + if (asp) { + asp->call(SNAME("set_stream"), Ref<AudioStream>()); + } } } break; default: { @@ -1989,7 +1982,7 @@ void AnimationMixer::restore(const Ref<AnimatedValuesBackup> &p_backup) { ERR_FAIL_COND(p_backup.is_null()); track_cache = p_backup->get_data(); _blend_apply(); - track_cache = HashMap<NodePath, AnimationMixer::TrackCache *>(); + track_cache = HashMap<Animation::TypeHash, AnimationMixer::TrackCache *>(); cache_valid = false; } @@ -2054,6 +2047,26 @@ void AnimationMixer::_notification(int p_what) { } } +void AnimationMixer::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + String pf = p_function; + if (p_idx == 0) { + if (pf == "get_animation" || pf == "has_animation") { + List<StringName> al; + get_animation_list(&al); + for (const StringName &name : al) { + r_options->push_back(String(name).quote()); + } + } else if (pf == "get_animation_library" || pf == "has_animation_library" || pf == "remove_animation_library" || pf == "rename_animation_library") { + List<StringName> al; + get_animation_library_list(&al); + for (const StringName &name : al) { + r_options->push_back(String(name).quote()); + } + } + } + Node::get_argument_options(p_function, p_idx, r_options); +} + void AnimationMixer::_bind_methods() { /* ---- Data lists ---- */ ClassDB::bind_method(D_METHOD("add_animation_library", "name", "library"), &AnimationMixer::add_animation_library); @@ -2100,7 +2113,7 @@ void AnimationMixer::_bind_methods() { /* ---- Blending processor ---- */ ClassDB::bind_method(D_METHOD("clear_caches"), &AnimationMixer::clear_caches); ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationMixer::advance); - GDVIRTUAL_BIND(_post_process_key_value, "animation", "track", "value", "object", "object_idx"); + GDVIRTUAL_BIND(_post_process_key_value, "animation", "track", "value", "object_id", "object_sub_idx"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deterministic"), "set_deterministic", "is_deterministic"); @@ -2146,10 +2159,10 @@ AnimationMixer::AnimationMixer() { AnimationMixer::~AnimationMixer() { } -void AnimatedValuesBackup::set_data(const HashMap<NodePath, AnimationMixer::TrackCache *> p_data) { +void AnimatedValuesBackup::set_data(const HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> p_data) { clear_data(); - for (const KeyValue<NodePath, AnimationMixer::TrackCache *> &E : p_data) { + for (const KeyValue<Animation::TypeHash, AnimationMixer::TrackCache *> &E : p_data) { AnimationMixer::TrackCache *track = get_cache_copy(E.value); if (!track) { continue; // Some types of tracks do not get a copy and must be ignored. @@ -2159,9 +2172,9 @@ void AnimatedValuesBackup::set_data(const HashMap<NodePath, AnimationMixer::Trac } } -HashMap<NodePath, AnimationMixer::TrackCache *> AnimatedValuesBackup::get_data() const { - HashMap<NodePath, AnimationMixer::TrackCache *> ret; - for (const KeyValue<NodePath, AnimationMixer::TrackCache *> &E : data) { +HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> AnimatedValuesBackup::get_data() const { + HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> ret; + for (const KeyValue<Animation::TypeHash, AnimationMixer::TrackCache *> &E : data) { AnimationMixer::TrackCache *track = get_cache_copy(E.value); ERR_CONTINUE(!track); // Backup shouldn't contain tracks that cannot be copied, this is a mistake. @@ -2171,7 +2184,7 @@ HashMap<NodePath, AnimationMixer::TrackCache *> AnimatedValuesBackup::get_data() } void AnimatedValuesBackup::clear_data() { - for (KeyValue<NodePath, AnimationMixer::TrackCache *> &K : data) { + for (KeyValue<Animation::TypeHash, AnimationMixer::TrackCache *> &K : data) { memdelete(K.value); } data.clear(); @@ -2179,6 +2192,7 @@ void AnimatedValuesBackup::clear_data() { AnimationMixer::TrackCache *AnimatedValuesBackup::get_cache_copy(AnimationMixer::TrackCache *p_cache) const { switch (p_cache->type) { + case Animation::TYPE_BEZIER: case Animation::TYPE_VALUE: { AnimationMixer::TrackCacheValue *src = static_cast<AnimationMixer::TrackCacheValue *>(p_cache); AnimationMixer::TrackCacheValue *tc = memnew(AnimationMixer::TrackCacheValue(*src)); @@ -2199,12 +2213,6 @@ AnimationMixer::TrackCache *AnimatedValuesBackup::get_cache_copy(AnimationMixer: return tc; } - case Animation::TYPE_BEZIER: { - AnimationMixer::TrackCacheBezier *src = static_cast<AnimationMixer::TrackCacheBezier *>(p_cache); - AnimationMixer::TrackCacheBezier *tc = memnew(AnimationMixer::TrackCacheBezier(*src)); - return tc; - } - case Animation::TYPE_AUDIO: { AnimationMixer::TrackCacheAudio *src = static_cast<AnimationMixer::TrackCacheAudio *>(p_cache); AnimationMixer::TrackCacheAudio *tc = memnew(AnimationMixer::TrackCacheAudio(*src)); diff --git a/scene/animation/animation_mixer.h b/scene/animation/animation_mixer.h index 0cd204b384..098c2c3b86 100644 --- a/scene/animation/animation_mixer.h +++ b/scene/animation/animation_mixer.h @@ -31,9 +31,7 @@ #ifndef ANIMATION_MIXER_H #define ANIMATION_MIXER_H -#include "scene/3d/mesh_instance_3d.h" -#include "scene/3d/node_3d.h" -#include "scene/3d/skeleton_3d.h" +#include "scene/main/node.h" #include "scene/resources/animation.h" #include "scene/resources/animation_library.h" #include "scene/resources/audio_stream_polyphonic.h" @@ -138,7 +136,7 @@ protected: bool root_motion = false; uint64_t setup_pass = 0; Animation::TrackType type = Animation::TrackType::TYPE_ANIMATION; - Object *object = nullptr; + NodePath path; ObjectID object_id; real_t total_weight = 0.0; @@ -147,7 +145,6 @@ protected: root_motion(p_other.root_motion), setup_pass(p_other.setup_pass), type(p_other.type), - object(p_other.object), object_id(p_other.object_id), total_weight(p_other.total_weight) {} @@ -156,8 +153,7 @@ protected: struct TrackCacheTransform : public TrackCache { #ifndef _3D_DISABLED - Node3D *node_3d = nullptr; - Skeleton3D *skeleton = nullptr; + ObjectID skeleton_id; #endif // _3D_DISABLED int bone_idx = -1; bool loc_used = false; @@ -173,8 +169,7 @@ protected: TrackCacheTransform(const TrackCacheTransform &p_other) : TrackCache(p_other), #ifndef _3D_DISABLED - node_3d(p_other.node_3d), - skeleton(p_other.skeleton), + skeleton_id(p_other.skeleton_id), #endif bone_idx(p_other.bone_idx), loc_used(p_other.loc_used), @@ -201,14 +196,12 @@ protected: }; struct TrackCacheBlendShape : public TrackCache { - MeshInstance3D *mesh_3d = nullptr; float init_value = 0; float value = 0; int shape_index = -1; TrackCacheBlendShape(const TrackCacheBlendShape &p_other) : TrackCache(p_other), - mesh_3d(p_other.mesh_3d), init_value(p_other.init_value), value(p_other.value), shape_index(p_other.shape_index) {} @@ -247,23 +240,6 @@ protected: ~TrackCacheMethod() {} }; - struct TrackCacheBezier : public TrackCache { - real_t init_value = 0.0; - real_t value = 0.0; - Vector<StringName> subpath; - - TrackCacheBezier(const TrackCacheBezier &p_other) : - TrackCache(p_other), - init_value(p_other.init_value), - value(p_other.value), - subpath(p_other.subpath) {} - - TrackCacheBezier() { - type = Animation::TYPE_BEZIER; - } - ~TrackCacheBezier() {} - }; - // Audio stream information for each audio stream placed on the track. struct PlayingAudioStreamInfo { AudioStreamPlaybackPolyphonic::ID index = -1; // ID retrieved from AudioStreamPlaybackPolyphonic. @@ -309,7 +285,7 @@ protected: }; RootMotionCache root_motion_cache; - HashMap<NodePath, TrackCache *> track_cache; + HashMap<Animation::TypeHash, TrackCache *> track_cache; HashSet<TrackCache *> playing_caches; Vector<Node *> playing_audio_stream_players; @@ -340,6 +316,7 @@ protected: void _get_property_list(List<PropertyInfo> *p_list) const; void _notification(int p_what); virtual void _validate_property(PropertyInfo &p_property) const; + virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; static void _bind_methods(); void _node_removed(Node *p_node); @@ -351,9 +328,9 @@ protected: /* ---- Blending processor ---- */ virtual void _process_animation(double p_delta, bool p_update_only = false); - virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1); - Variant post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1); - GDVIRTUAL5RC(Variant, _post_process_key_value, Ref<Animation>, int, Variant, Object *, int); + virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx = -1); + Variant post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx = -1); + GDVIRTUAL5RC(Variant, _post_process_key_value, Ref<Animation>, int, Variant, ObjectID, int); void _blend_init(); virtual bool _blend_pre_process(double p_delta, int p_track_count, const HashMap<NodePath, int> &p_track_map); @@ -361,7 +338,13 @@ protected: void _blend_process(double p_delta, bool p_update_only = false); void _blend_apply(); virtual void _blend_post_process(); - void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred); + void _call_object(ObjectID p_object_id, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred); + +#ifndef DISABLE_DEPRECATED + virtual Variant _post_process_key_value_bind_compat_86687(const Ref<Animation> &p_anim, int p_track, Variant p_value, Object *p_object, int p_object_idx = -1); + + static void _bind_compatibility_methods(); +#endif // DISABLE_DEPRECATED public: /* ---- Data lists ---- */ @@ -443,11 +426,11 @@ public: class AnimatedValuesBackup : public RefCounted { GDCLASS(AnimatedValuesBackup, RefCounted); - HashMap<NodePath, AnimationMixer::TrackCache *> data; + HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> data; public: - void set_data(const HashMap<NodePath, AnimationMixer::TrackCache *> p_data); - HashMap<NodePath, AnimationMixer::TrackCache *> get_data() const; + void set_data(const HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> p_data); + HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> get_data() const; void clear_data(); AnimationMixer::TrackCache *get_cache_copy(AnimationMixer::TrackCache *p_cache) const; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 02b74c9188..b7bed59c00 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -233,7 +233,9 @@ void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, f pi.delta = delta; pi.seeked = p_seeked; } - pi.is_external_seeking = true; // AnimationPlayer doesn't have internal seeking. + // AnimationPlayer doesn't have internal seeking. + // However, immediately after playback, discrete keys should be retrieved with EXACT mode since behind keys must be ignored at that time. + pi.is_external_seeking = !p_started; pi.looped_flag = looped_flag; pi.weight = p_blend; make_animation_instance(cd.from->name, pi); @@ -665,7 +667,7 @@ void AnimationPlayer::get_argument_options(const StringName &p_function, int p_i r_options->push_back(String(name).quote()); } } - Node::get_argument_options(p_function, p_idx, r_options); + AnimationMixer::get_argument_options(p_function, p_idx, r_options); } void AnimationPlayer::_animation_removed(const StringName &p_name, const StringName &p_library) { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index da0687dd70..17fbc68973 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -619,7 +619,7 @@ void AnimationTree::_tree_changed() { return; } - call_deferred(SNAME("_update_properties")); + callable_mp(this, &AnimationTree::_update_properties).call_deferred(); properties_dirty = true; } @@ -886,8 +886,6 @@ void AnimationTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_animation_player", "path"), &AnimationTree::set_animation_player); ClassDB::bind_method(D_METHOD("get_animation_player"), &AnimationTree::get_animation_player); - ClassDB::bind_method(D_METHOD("_update_properties"), &AnimationTree::_update_properties); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tree_root", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode"), "set_tree_root", "get_tree_root"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "advance_expression_base_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node"), "set_advance_expression_base_node", "get_advance_expression_base_node"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "anim_player", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationPlayer"), "set_animation_player", "get_animation_player"); diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index 645850015b..fd520dadd6 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -28,6 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ +#ifndef _3D_DISABLED + #include "root_motion_view.h" #include "scene/animation/animation_tree.h" @@ -203,3 +205,5 @@ RootMotionView::RootMotionView() { RootMotionView::~RootMotionView() { set_base(RID()); } + +#endif // _3D_DISABLED diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index f3c986f9b3..bd4731d8dd 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -34,6 +34,8 @@ #include "core/math/audio_frame.h" #include "servers/audio_server.h" +#define PARAM_PREFIX "parameters/" + void AudioStreamPlayer::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -88,9 +90,71 @@ void AudioStreamPlayer::_notification(int p_what) { } } +void AudioStreamPlayer::_update_stream_parameters() { + if (stream.is_null()) { + return; + } + List<AudioStream::Parameter> parameters; + stream->get_parameter_list(¶meters); + for (const AudioStream::Parameter &K : parameters) { + const PropertyInfo &pi = K.property; + StringName key = PARAM_PREFIX + pi.name; + if (!playback_parameters.has(key)) { + ParameterData pd; + pd.path = pi.name; + pd.value = K.default_value; + playback_parameters.insert(key, pd); + } + } +} + void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) { + if (stream.is_valid()) { + stream->disconnect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer::_update_stream_parameters)); + } stop(); stream = p_stream; + _update_stream_parameters(); + if (stream.is_valid()) { + stream->connect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayer::_update_stream_parameters)); + } + notify_property_list_changed(); +} + +bool AudioStreamPlayer::_set(const StringName &p_name, const Variant &p_value) { + HashMap<StringName, ParameterData>::Iterator I = playback_parameters.find(p_name); + if (!I) { + return false; + } + ParameterData &pd = I->value; + pd.value = p_value; + for (Ref<AudioStreamPlayback> &playback : stream_playbacks) { + playback->set_parameter(pd.path, pd.value); + } + return true; +} + +bool AudioStreamPlayer::_get(const StringName &p_name, Variant &r_ret) const { + HashMap<StringName, ParameterData>::ConstIterator I = playback_parameters.find(p_name); + if (!I) { + return false; + } + + r_ret = I->value.value; + return true; +} + +void AudioStreamPlayer::_get_property_list(List<PropertyInfo> *p_list) const { + if (stream.is_null()) { + return; + } + List<AudioStream::Parameter> parameters; + stream->get_parameter_list(¶meters); + for (const AudioStream::Parameter &K : parameters) { + PropertyInfo pi = K.property; + pi.name = PARAM_PREFIX + pi.name; + p_list->push_back(pi); + } } Ref<AudioStream> AudioStreamPlayer::get_stream() const { @@ -144,6 +208,10 @@ void AudioStreamPlayer::play(float p_from_pos) { Ref<AudioStreamPlayback> stream_playback = stream->instantiate_playback(); ERR_FAIL_COND_MSG(stream_playback.is_null(), "Failed to instantiate playback."); + for (const KeyValue<StringName, ParameterData> &K : playback_parameters) { + stream_playback->set_parameter(K.value.path, K.value.value); + } + AudioServer::get_singleton()->start_playback_stream(stream_playback, bus, _get_volume_vector(), p_from_pos, pitch_scale); stream_playbacks.push_back(stream_playback); active.set(); diff --git a/scene/audio/audio_stream_player.h b/scene/audio/audio_stream_player.h index 9dbdccdc69..404d6fbebf 100644 --- a/scene/audio/audio_stream_player.h +++ b/scene/audio/audio_stream_player.h @@ -68,11 +68,23 @@ private: Vector<AudioFrame> _get_volume_vector(); + struct ParameterData { + StringName path; + Variant value; + }; + + HashMap<StringName, ParameterData> playback_parameters; + void _update_stream_parameters(); + protected: void _validate_property(PropertyInfo &p_property) const; void _notification(int p_what); static void _bind_methods(); + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + public: void set_stream(Ref<AudioStream> p_stream); Ref<AudioStream> get_stream() const; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 1d5c1c0ade..9d24595916 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -219,7 +219,7 @@ void ColorPicker::finish_shaders() { } void ColorPicker::set_focus_on_line_edit() { - c_text->call_deferred(SNAME("grab_focus")); + callable_mp((Control *)c_text, &Control::grab_focus).call_deferred(); } void ColorPicker::_update_controls() { @@ -557,6 +557,24 @@ void ColorPicker::_html_submitted(const String &p_html) { } Color new_color = Color::from_string(p_html.strip_edges(), color); + String html_no_prefix = p_html.strip_edges().trim_prefix("#"); + if (html_no_prefix.is_valid_hex_number(false)) { + // Convert invalid HTML color codes that software like Figma supports. + if (html_no_prefix.length() == 1) { + // Turn `#1` into `#111111`. + html_no_prefix = html_no_prefix.repeat(6); + } else if (html_no_prefix.length() == 2) { + // Turn `#12` into `#121212`. + html_no_prefix = html_no_prefix.repeat(3); + } else if (html_no_prefix.length() == 5) { + // Turn `#12345` into `#11223344`. + html_no_prefix = html_no_prefix.left(4); + } else if (html_no_prefix.length() == 7) { + // Turn `#1234567` into `#123456`. + html_no_prefix = html_no_prefix.left(6); + } + } + new_color = Color::from_string(html_no_prefix, new_color); if (!is_editing_alpha()) { new_color.a = color.a; @@ -1046,6 +1064,14 @@ void ColorPicker::_sample_draw() { sample->draw_rect(rect_old, old_color); + if (!old_color.is_equal_approx(color)) { + // Draw a revert indicator to indicate that the old sample can be clicked to revert to this old color. + // Adapt icon color to the background color (taking alpha checkerboard into account) so that it's always visible. + sample->draw_texture(theme_cache.sample_revert, + rect_old.size * 0.5 - theme_cache.sample_revert->get_size() * 0.5, + Math::lerp(0.75f, old_color.get_luminance(), old_color.a) < 0.455 ? Color(1, 1, 1) : (Color(0.01, 0.01, 0.01))); + } + if (old_color.r > 1 || old_color.g > 1 || old_color.b > 1) { // Draw an indicator to denote that the old color is "overbright" and can't be displayed accurately in the preview. sample->draw_texture(theme_cache.overbright_indicator, Point2()); @@ -1744,6 +1770,7 @@ void ColorPicker::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, bar_arrow); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, sample_bg); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, sample_revert); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, overbright_indicator); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, picker_cursor); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, color_hue); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index dc547c8b0c..282926d1ff 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -237,6 +237,7 @@ private: Ref<Texture2D> bar_arrow; Ref<Texture2D> sample_bg; + Ref<Texture2D> sample_revert; Ref<Texture2D> overbright_indicator; Ref<Texture2D> picker_cursor; Ref<Texture2D> color_hue; diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 4e23db4cae..c6e66c95c6 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -30,7 +30,6 @@ #include "container.h" -#include "core/object/message_queue.h" #include "scene/scene_string_names.h" void Container::_child_minsize_changed() { @@ -138,7 +137,7 @@ void Container::queue_sort() { return; } - MessageQueue::get_singleton()->push_callable(callable_mp(this, &Container::_sort_children)); + callable_mp(this, &Container::_sort_children).call_deferred(); pending_sort = true; } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 84ca6bac5b..349102fafb 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -33,7 +33,6 @@ #include "container.h" #include "core/config/project_settings.h" #include "core/math/geometry_2d.h" -#include "core/object/message_queue.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/string/print_string.h" @@ -205,7 +204,7 @@ void Control::set_root_layout_direction(int p_root_dir) { void Control::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { ERR_READ_THREAD_GUARD; - Node::get_argument_options(p_function, p_idx, r_options); + CanvasItem::get_argument_options(p_function, p_idx, r_options); if (p_idx == 0) { List<StringName> sn; @@ -1631,7 +1630,7 @@ void Control::update_minimum_size() { } data.updating_last_minimum_size = true; - MessageQueue::get_singleton()->push_callable(callable_mp(this, &Control::_update_minimum_size)); + callable_mp(this, &Control::_update_minimum_size).call_deferred(); } void Control::set_block_minimum_size_adjust(bool p_block) { diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 3e827e76dc..8339d34f83 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -129,7 +129,7 @@ void AcceptDialog::_cancel_pressed() { parent_visible = nullptr; } - call_deferred(SNAME("hide")); + callable_mp((Window *)this, &Window::hide).call_deferred(); emit_signal(SNAME("canceled")); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index d721ee3ec3..5d770c2eb2 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -89,7 +89,7 @@ void FileDialog::set_visible(bool p_visible) { void FileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter) { if (p_ok) { if (p_files.size() > 0) { - String f = p_files[0]; + const String &f = p_files[0]; if (mode == FILE_MODE_OPEN_FILES) { emit_signal(SNAME("files_selected"), p_files); } else { diff --git a/scene/gui/graph_edit_arranger.cpp b/scene/gui/graph_edit_arranger.cpp index 3f2007f7e0..29c3056b3b 100644 --- a/scene/gui/graph_edit_arranger.cpp +++ b/scene/gui/graph_edit_arranger.cpp @@ -287,13 +287,13 @@ Vector<StringName> GraphEditArranger::_split(const Vector<StringName> &r_layer, return Vector<StringName>(); } - StringName p = r_layer[Math::random(0, r_layer.size() - 1)]; + const StringName &p = r_layer[Math::random(0, r_layer.size() - 1)]; Vector<StringName> left; Vector<StringName> right; for (int i = 0; i < r_layer.size(); i++) { if (p != r_layer[i]) { - StringName q = r_layer[i]; + const StringName &q = r_layer[i]; int cross_pq = r_crossings[p][q]; int cross_qp = r_crossings[q][p]; if (cross_pq > cross_qp) { @@ -326,9 +326,9 @@ void GraphEditArranger::_horizontal_alignment(Dictionary &r_root, Dictionary &r_ for (int j = 0; j < lower_layer.size(); j++) { Vector<Pair<int, StringName>> up; - StringName current_node = lower_layer[j]; + const StringName ¤t_node = lower_layer[j]; for (int k = 0; k < upper_layer.size(); k++) { - StringName adjacent_neighbour = upper_layer[k]; + const StringName &adjacent_neighbour = upper_layer[k]; if (r_upper_neighbours[current_node].has(adjacent_neighbour)) { up.push_back(Pair<int, StringName>(k, adjacent_neighbour)); } @@ -360,12 +360,12 @@ void GraphEditArranger::_crossing_minimisation(HashMap<int, Vector<StringName>> HashMap<StringName, Dictionary> c; for (int j = 0; j < lower_layer.size(); j++) { - StringName p = lower_layer[j]; + const StringName &p = lower_layer[j]; Dictionary d; for (int k = 0; k < lower_layer.size(); k++) { unsigned int crossings = 0; - StringName q = lower_layer[k]; + const StringName &q = lower_layer[k]; if (j != k) { for (int h = 1; h < upper_layer.size(); h++) { @@ -421,7 +421,7 @@ void GraphEditArranger::_calculate_inner_shifts(Dictionary &r_inner_shifts, cons } } -float GraphEditArranger::_calculate_threshold(StringName p_v, StringName p_w, const Dictionary &r_node_names, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_inner_shift, real_t p_current_threshold, const HashMap<StringName, Vector2> &r_node_positions) { +float GraphEditArranger::_calculate_threshold(const StringName &p_v, const StringName &p_w, const Dictionary &r_node_names, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_inner_shift, real_t p_current_threshold, const HashMap<StringName, Vector2> &r_node_positions) { #define MAX_ORDER 2147483647 #define ORDER(node, layers) \ for (unsigned int i = 0; i < layers.size(); i++) { \ @@ -503,7 +503,7 @@ float GraphEditArranger::_calculate_threshold(StringName p_v, StringName p_w, co return threshold; } -void GraphEditArranger::_place_block(StringName p_v, float p_delta, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_node_name, const Dictionary &r_inner_shift, Dictionary &r_sink, Dictionary &r_shift, HashMap<StringName, Vector2> &r_node_positions) { +void GraphEditArranger::_place_block(const StringName &p_v, float p_delta, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_node_name, const Dictionary &r_inner_shift, Dictionary &r_sink, Dictionary &r_shift, HashMap<StringName, Vector2> &r_node_positions) { #define PRED(node, layers) \ for (unsigned int i = 0; i < layers.size(); i++) { \ int index = layers[i].find(node); \ diff --git a/scene/gui/graph_edit_arranger.h b/scene/gui/graph_edit_arranger.h index e79944e5dd..925b58d428 100644 --- a/scene/gui/graph_edit_arranger.h +++ b/scene/gui/graph_edit_arranger.h @@ -54,8 +54,8 @@ class GraphEditArranger : public RefCounted { void _horizontal_alignment(Dictionary &r_root, Dictionary &r_align, const HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, HashSet<StringName>> &r_upper_neighbours, const HashSet<StringName> &r_selected_nodes); void _crossing_minimisation(HashMap<int, Vector<StringName>> &r_layers, const HashMap<StringName, HashSet<StringName>> &r_upper_neighbours); void _calculate_inner_shifts(Dictionary &r_inner_shifts, const Dictionary &r_root, const Dictionary &r_node_names, const Dictionary &r_align, const HashSet<StringName> &r_block_heads, const HashMap<StringName, Pair<int, int>> &r_port_info); - float _calculate_threshold(StringName p_v, StringName p_w, const Dictionary &r_node_names, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_inner_shift, real_t p_current_threshold, const HashMap<StringName, Vector2> &r_node_positions); - void _place_block(StringName p_v, float p_delta, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_node_name, const Dictionary &r_inner_shift, Dictionary &r_sink, Dictionary &r_shift, HashMap<StringName, Vector2> &r_node_positions); + float _calculate_threshold(const StringName &p_v, const StringName &p_w, const Dictionary &r_node_names, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_inner_shift, real_t p_current_threshold, const HashMap<StringName, Vector2> &r_node_positions); + void _place_block(const StringName &p_v, float p_delta, const HashMap<int, Vector<StringName>> &r_layers, const Dictionary &r_root, const Dictionary &r_align, const Dictionary &r_node_name, const Dictionary &r_inner_shift, Dictionary &r_sink, Dictionary &r_shift, HashMap<StringName, Vector2> &r_node_positions); public: void arrange_nodes(); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 3b1c1a153f..1b960a9b62 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -482,6 +482,27 @@ Color GraphNode::get_slot_color_left(int p_slot_index) const { return slot_table[p_slot_index].color_left; } +void GraphNode::set_slot_custom_icon_left(int p_slot_index, const Ref<Texture2D> &p_custom_icon) { + ERR_FAIL_COND_MSG(!slot_table.has(p_slot_index), vformat("Cannot set custom_port_icon_left for the slot with index '%d' because it hasn't been enabled.", p_slot_index)); + + if (slot_table[p_slot_index].custom_port_icon_left == p_custom_icon) { + return; + } + + slot_table[p_slot_index].custom_port_icon_left = p_custom_icon; + queue_redraw(); + port_pos_dirty = true; + + emit_signal(SNAME("slot_updated"), p_slot_index); +} + +Ref<Texture2D> GraphNode::get_slot_custom_icon_left(int p_slot_index) const { + if (!slot_table.has(p_slot_index)) { + return Ref<Texture2D>(); + } + return slot_table[p_slot_index].custom_port_icon_left; +} + bool GraphNode::is_slot_enabled_right(int p_slot_index) const { if (!slot_table.has(p_slot_index)) { return false; @@ -545,6 +566,27 @@ Color GraphNode::get_slot_color_right(int p_slot_index) const { return slot_table[p_slot_index].color_right; } +void GraphNode::set_slot_custom_icon_right(int p_slot_index, const Ref<Texture2D> &p_custom_icon) { + ERR_FAIL_COND_MSG(!slot_table.has(p_slot_index), vformat("Cannot set custom_port_icon_right for the slot with index '%d' because it hasn't been enabled.", p_slot_index)); + + if (slot_table[p_slot_index].custom_port_icon_right == p_custom_icon) { + return; + } + + slot_table[p_slot_index].custom_port_icon_right = p_custom_icon; + queue_redraw(); + port_pos_dirty = true; + + emit_signal(SNAME("slot_updated"), p_slot_index); +} + +Ref<Texture2D> GraphNode::get_slot_custom_icon_right(int p_slot_index) const { + if (!slot_table.has(p_slot_index)) { + return Ref<Texture2D>(); + } + return slot_table[p_slot_index].custom_port_icon_right; +} + bool GraphNode::is_slot_draw_stylebox(int p_slot_index) const { if (!slot_table.has(p_slot_index)) { return false; @@ -797,6 +839,9 @@ void GraphNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_slot_color_left", "slot_index", "color"), &GraphNode::set_slot_color_left); ClassDB::bind_method(D_METHOD("get_slot_color_left", "slot_index"), &GraphNode::get_slot_color_left); + ClassDB::bind_method(D_METHOD("set_slot_custom_icon_left", "slot_index", "custom_icon"), &GraphNode::set_slot_custom_icon_left); + ClassDB::bind_method(D_METHOD("get_slot_custom_icon_left", "slot_index"), &GraphNode::get_slot_custom_icon_left); + ClassDB::bind_method(D_METHOD("is_slot_enabled_right", "slot_index"), &GraphNode::is_slot_enabled_right); ClassDB::bind_method(D_METHOD("set_slot_enabled_right", "slot_index", "enable"), &GraphNode::set_slot_enabled_right); @@ -806,6 +851,9 @@ void GraphNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_slot_color_right", "slot_index", "color"), &GraphNode::set_slot_color_right); ClassDB::bind_method(D_METHOD("get_slot_color_right", "slot_index"), &GraphNode::get_slot_color_right); + ClassDB::bind_method(D_METHOD("set_slot_custom_icon_right", "slot_index", "custom_icon"), &GraphNode::set_slot_custom_icon_right); + ClassDB::bind_method(D_METHOD("get_slot_custom_icon_right", "slot_index"), &GraphNode::get_slot_custom_icon_right); + ClassDB::bind_method(D_METHOD("is_slot_draw_stylebox", "slot_index"), &GraphNode::is_slot_draw_stylebox); ClassDB::bind_method(D_METHOD("set_slot_draw_stylebox", "slot_index", "enable"), &GraphNode::set_slot_draw_stylebox); diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index 04ca9e7cb4..a0610b37fb 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -129,6 +129,9 @@ public: void set_slot_color_left(int p_slot_index, const Color &p_color); Color get_slot_color_left(int p_slot_index) const; + void set_slot_custom_icon_left(int p_slot_index, const Ref<Texture2D> &p_custom_icon); + Ref<Texture2D> get_slot_custom_icon_left(int p_slot_index) const; + bool is_slot_enabled_right(int p_slot_index) const; void set_slot_enabled_right(int p_slot_index, bool p_enable); @@ -138,6 +141,9 @@ public: void set_slot_color_right(int p_slot_index, const Color &p_color); Color get_slot_color_right(int p_slot_index) const; + void set_slot_custom_icon_right(int p_slot_index, const Ref<Texture2D> &p_custom_icon); + Ref<Texture2D> get_slot_custom_icon_right(int p_slot_index) const; + bool is_slot_draw_stylebox(int p_slot_index) const; void set_slot_draw_stylebox(int p_slot_index, bool p_enable); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 02d44caa1c..e9d34fae3b 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -44,7 +44,7 @@ void ItemList::_shape_text(int p_idx) { } else { item.text_buf->set_direction((TextServer::Direction)item.text_direction); } - item.text_buf->add_string(item.text, theme_cache.font, theme_cache.font_size, item.language); + item.text_buf->add_string(item.xl_text, theme_cache.font, theme_cache.font_size, item.language); if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) { item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES); } else { @@ -58,6 +58,7 @@ int ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bo Item item; item.icon = p_texture; item.text = p_item; + item.xl_text = atr(p_item); item.selectable = p_selectable; items.push_back(item); int item_id = items.size() - 1; @@ -94,6 +95,7 @@ void ItemList::set_item_text(int p_idx, const String &p_text) { } items.write[p_idx].text = p_text; + items.write[p_idx].xl_text = atr(p_text); _shape_text(p_idx); queue_redraw(); shape_changed = true; @@ -1001,7 +1003,6 @@ void ItemList::_notification(int p_what) { } break; case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: - case NOTIFICATION_TRANSLATION_CHANGED: case NOTIFICATION_THEME_CHANGED: { for (int i = 0; i < items.size(); i++) { _shape_text(i); @@ -1009,6 +1010,14 @@ void ItemList::_notification(int p_what) { shape_changed = true; queue_redraw(); } break; + case NOTIFICATION_TRANSLATION_CHANGED: { + for (int i = 0; i < items.size(); i++) { + items.write[i].xl_text = atr(items[i].text); + _shape_text(i); + } + shape_changed = true; + queue_redraw(); + } break; case NOTIFICATION_DRAW: { force_update_list_size(); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 796e0eb687..28f9012058 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -57,6 +57,7 @@ private: Color icon_modulate = Color(1, 1, 1, 1); Ref<Texture2D> tag_icon; String text; + String xl_text; Ref<TextParagraph> text_buf; String language; TextDirection text_direction = TEXT_DIRECTION_AUTO; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 1b1905e793..56da1332e7 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -813,6 +813,19 @@ Size2 Label::get_minimum_size() const { } } +#ifndef DISABLE_DEPRECATED +bool Label::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == SNAME("valign")) { + set_vertical_alignment((VerticalAlignment)p_value.operator int()); + return true; + } else if (p_name == SNAME("align")) { + set_horizontal_alignment((HorizontalAlignment)p_value.operator int()); + return true; + } + return false; +} +#endif + int Label::get_line_count() const { if (!is_inside_tree()) { return 1; diff --git a/scene/gui/label.h b/scene/gui/label.h index 9306033dd0..4bd0e53605 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -91,6 +91,9 @@ private: protected: void _notification(int p_what); static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); +#endif public: virtual Size2 get_minimum_size() const override; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 5cca09bcf6..a6109a3925 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -31,7 +31,6 @@ #include "line_edit.h" #include "core/input/input_map.h" -#include "core/object/message_queue.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/string/print_string.h" @@ -270,7 +269,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { if (!text_changed_dirty) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_text_changed"); + callable_mp(this, &LineEdit::_text_changed).call_deferred(); } text_changed_dirty = true; } @@ -624,7 +623,12 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { int prev_len = text.length(); insert_text_at_caret(ucodestr); if (text.length() != prev_len) { - _text_changed(); + if (!text_changed_dirty) { + if (is_inside_tree()) { + callable_mp(this, &LineEdit::_text_changed).call_deferred(); + } + text_changed_dirty = true; + } } accept_event(); return; @@ -709,7 +713,7 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { select(caret_column_tmp, caret_column); if (!text_changed_dirty) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_text_changed"); + callable_mp(this, &LineEdit::_text_changed).call_deferred(); } text_changed_dirty = true; } @@ -1185,7 +1189,7 @@ void LineEdit::paste_text() { if (!text_changed_dirty) { if (is_inside_tree() && text.length() != prev_len) { - MessageQueue::get_singleton()->push_call(this, "_text_changed"); + callable_mp(this, &LineEdit::_text_changed).call_deferred(); } text_changed_dirty = true; } @@ -1223,9 +1227,10 @@ void LineEdit::undo() { TextOperation op = undo_stack_pos->get(); text = op.text; scroll_offset = op.scroll_offset; - set_caret_column(op.caret_column); _shape(); + set_caret_column(op.caret_column); + _emit_text_change(); } @@ -1247,9 +1252,10 @@ void LineEdit::redo() { TextOperation op = undo_stack_pos->get(); text = op.text; scroll_offset = op.scroll_offset; - set_caret_column(op.caret_column); _shape(); + set_caret_column(op.caret_column); + _emit_text_change(); } @@ -1499,7 +1505,7 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { if (!text_changed_dirty) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_text_changed"); + callable_mp(this, &LineEdit::_text_changed).call_deferred(); } text_changed_dirty = true; } @@ -1713,6 +1719,12 @@ void LineEdit::set_caret_column(int p_column) { } else if (MAX(primary_caret_offset.x, primary_caret_offset.y) >= ofs_max) { scroll_offset += ofs_max - MAX(primary_caret_offset.x, primary_caret_offset.y); } + + // Scroll to show as much text as possible + if (text_width + scroll_offset + x_ofs < ofs_max) { + scroll_offset = ofs_max - x_ofs - text_width; + } + scroll_offset = MIN(0, scroll_offset); queue_redraw(); @@ -2501,8 +2513,6 @@ void LineEdit::_validate_property(PropertyInfo &p_property) const { } void LineEdit::_bind_methods() { - ClassDB::bind_method(D_METHOD("_text_changed"), &LineEdit::_text_changed); - ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &LineEdit::set_horizontal_alignment); ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &LineEdit::get_horizontal_alignment); diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index f9740b1217..6386bb20c3 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -159,7 +159,7 @@ void OptionButton::_notification(int p_what) { bool OptionButton::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0] == "popup") { - String property = components[2]; + const String &property = components[2]; if (property != "text" && property != "icon" && property != "id" && property != "disabled" && property != "separator") { return false; } @@ -186,7 +186,7 @@ bool OptionButton::_set(const StringName &p_name, const Variant &p_value) { bool OptionButton::_get(const StringName &p_name, Variant &r_ret) const { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0] == "popup") { - String property = components[2]; + const String &property = components[2]; if (property != "text" && property != "icon" && property != "id" && property != "disabled" && property != "separator") { return false; } diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 8369bedda9..0c5a882044 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -123,7 +123,7 @@ void Popup::_close_pressed() { _deinitialize_visible_parents(); - call_deferred(SNAME("hide")); + callable_mp((Window *)this, &Window::hide).call_deferred(); } void Popup::_post_popup() { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index d9c633b238..2414278e52 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -42,6 +42,21 @@ HashMap<String, PopupMenu *> PopupMenu::system_menus; +bool PopupMenu::_set_item_accelerator(int p_index, const Ref<InputEventKey> &p_ie) { + DisplayServer *ds = DisplayServer::get_singleton(); + if (p_ie->get_physical_keycode() == Key::NONE && p_ie->get_keycode() == Key::NONE && p_ie->get_key_label() != Key::NONE) { + ds->global_menu_set_item_accelerator(global_menu_name, p_index, p_ie->get_key_label_with_modifiers()); + return true; + } else if (p_ie->get_keycode() != Key::NONE) { + ds->global_menu_set_item_accelerator(global_menu_name, p_index, p_ie->get_keycode_with_modifiers()); + return true; + } else if (p_ie->get_physical_keycode() != Key::NONE) { + ds->global_menu_set_item_accelerator(global_menu_name, p_index, ds->keyboard_get_keycode_from_physical(p_ie->get_physical_keycode_with_modifiers())); + return true; + } + return false; +} + String PopupMenu::bind_global_menu() { #ifdef TOOLS_ENABLED if (is_part_of_edited_scene()) { @@ -76,7 +91,7 @@ String PopupMenu::bind_global_menu() { if (item.separator) { ds->global_menu_add_separator(global_menu_name); } else { - int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), i); + int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), item.shortcut_is_global ? callable_mp(this, &PopupMenu::activate_item) : Callable(), i); if (!item.submenu.is_empty()) { PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(item.submenu)); if (pm) { @@ -101,8 +116,7 @@ String PopupMenu::bind_global_menu() { Array events = item.shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(index, ie)) { break; } } @@ -273,8 +287,7 @@ int PopupMenu::_get_items_total_height() const { items_total_height += _get_item_height(i) + theme_cache.v_separation; } - // Subtract a separator which is not needed for the last item. - return items_total_height - theme_cache.v_separation; + return items_total_height; } int PopupMenu::_get_mouse_over(const Point2 &p_over) const { @@ -283,14 +296,14 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const { } // Accounts for margin in the margin container - Point2 ofs = theme_cache.panel_style->get_offset() + Point2(0, theme_cache.v_separation / 2); + Point2 ofs = theme_cache.panel_style->get_offset(); if (ofs.y > p_over.y) { return -1; } for (int i = 0; i < items.size(); i++) { - ofs.y += i > 0 ? theme_cache.v_separation : (float)theme_cache.v_separation / 2; + ofs.y += theme_cache.v_separation; ofs.y += _get_item_height(i); @@ -780,9 +793,7 @@ void PopupMenu::_draw_items() { } } - Color icon_color(1, 1, 1, items[i].disabled && !items[i].separator ? 0.5 : 1); - - icon_color *= items[i].icon_modulate; + Color icon_color = items[i].icon_modulate; // For non-separator items, add some padding for the content. if (!items[i].separator) { @@ -1363,13 +1374,12 @@ void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_g if (!global_menu_name.is_empty()) { DisplayServer *ds = DisplayServer::get_singleton(); - int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1); + int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), p_global ? callable_mp(this, &PopupMenu::activate_item) : Callable(), items.size() - 1); if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) { Array events = item.shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(index, ie)) { break; } } @@ -1392,13 +1402,12 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortc if (!global_menu_name.is_empty()) { DisplayServer *ds = DisplayServer::get_singleton(); - int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1); + int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), p_global ? callable_mp(this, &PopupMenu::activate_item) : Callable(), items.size() - 1); if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) { Array events = item.shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(index, ie)) { break; } } @@ -1422,13 +1431,12 @@ void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bo if (!global_menu_name.is_empty()) { DisplayServer *ds = DisplayServer::get_singleton(); - int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1); + int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), p_global ? callable_mp(this, &PopupMenu::activate_item) : Callable(), items.size() - 1); if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) { Array events = item.shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(index, ie)) { break; } } @@ -1453,13 +1461,12 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref< if (!global_menu_name.is_empty()) { DisplayServer *ds = DisplayServer::get_singleton(); - int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1); + int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), p_global ? callable_mp(this, &PopupMenu::activate_item) : Callable(), items.size() - 1); if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) { Array events = item.shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(index, ie)) { break; } } @@ -1484,13 +1491,12 @@ void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_ if (!global_menu_name.is_empty()) { DisplayServer *ds = DisplayServer::get_singleton(); - int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1); + int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), p_global ? callable_mp(this, &PopupMenu::activate_item) : Callable(), items.size() - 1); if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) { Array events = item.shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(index, ie)) { break; } } @@ -1515,13 +1521,12 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons if (!global_menu_name.is_empty()) { DisplayServer *ds = DisplayServer::get_singleton(); - int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1); + int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), p_global ? callable_mp(this, &PopupMenu::activate_item) : Callable(), items.size() - 1); if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) { Array events = item.shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(index, ie)) { break; } } @@ -2045,11 +2050,15 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo Array events = items[p_idx].shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, p_idx, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(p_idx, ie)) { break; } } + if (p_global) { + ds->global_menu_set_item_key_callback(global_menu_name, p_idx, callable_mp(this, &PopupMenu::activate_item)); + } else { + ds->global_menu_set_item_key_callback(global_menu_name, p_idx, Callable()); + } } } @@ -2116,8 +2125,7 @@ void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) { Array events = items[p_idx].shortcut->get_events(); for (int j = 0; j < events.size(); j++) { Ref<InputEventKey> ie = events[j]; - if (ie.is_valid()) { - ds->global_menu_set_item_accelerator(global_menu_name, p_idx, ie->get_keycode_with_modifiers()); + if (ie.is_valid() && _set_item_accelerator(p_idx, ie)) { break; } } @@ -2416,7 +2424,8 @@ void PopupMenu::clear(bool p_free_submenus) { } if (!global_menu_name.is_empty()) { - for (int i = 0; i < items.size(); i++) { + DisplayServer *ds = DisplayServer::get_singleton(); + for (int i = items.size() - 1; i >= 0; i--) { Item &item = items.write[i]; if (!item.submenu.is_empty()) { PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(item.submenu)); @@ -2425,8 +2434,8 @@ void PopupMenu::clear(bool p_free_submenus) { } item.submenu_bound = false; } + ds->global_menu_remove_item(global_menu_name, i); } - DisplayServer::get_singleton()->global_menu_clear(global_menu_name); } items.clear(); @@ -2535,7 +2544,7 @@ bool PopupMenu::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("item_") && components[0].trim_prefix("item_").is_valid_int()) { int item_index = components[0].trim_prefix("item_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "text") { set_item_text(item_index, p_value); return true; @@ -2614,7 +2623,7 @@ bool PopupMenu::_get(const StringName &p_name, Variant &r_ret) const { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("item_") && components[0].trim_prefix("item_").is_valid_int()) { int item_index = components[0].trim_prefix("item_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "text") { r_ret = get_item_text(item_index); return true; diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index c1ab9544ea..9783f9d57b 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -194,6 +194,7 @@ class PopupMenu : public Popup { void _close_pressed(); void _menu_changed(); void _input_from_window_internal(const Ref<InputEvent> &p_event); + bool _set_item_accelerator(int p_index, const Ref<InputEventKey> &p_ie); protected: virtual void add_child_notify(Node *p_child) override; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index fbc374e89e..fd481e1067 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2805,7 +2805,7 @@ void RichTextLabel::_thread_function(void *p_userdata) { set_current_thread_safe_for_nodes(true); _process_line_caches(); updating.store(false); - call_deferred(SNAME("thread_end")); + callable_mp(this, &RichTextLabel::_thread_end).call_deferred(); } void RichTextLabel::_thread_end() { @@ -3151,7 +3151,7 @@ void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline) queue_redraw(); } -void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_subitem_line) { +void RichTextLabel::_remove_item(Item *p_item, const int p_line) { int size = p_item->subitems.size(); if (size == 0) { p_item->parent->subitems.erase(p_item); @@ -3160,7 +3160,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub current_frame->lines.remove_at(p_line); if (p_line < (int)current_frame->lines.size() && current_frame->lines[p_line].from) { for (List<Item *>::Element *E = current_frame->lines[p_line].from->E; E; E = E->next()) { - if (E->get()->line > p_subitem_line) { + if (E->get()->line > p_line) { E->get()->line--; } } @@ -3169,7 +3169,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub } else { // First, remove all child items for the provided item. while (p_item->subitems.size()) { - _remove_item(p_item->subitems.front()->get(), p_line, p_subitem_line); + _remove_item(p_item->subitems.front()->get(), p_line); } // Then remove the provided item itself. p_item->parent->subitems.erase(p_item); @@ -3377,7 +3377,10 @@ bool RichTextLabel::remove_paragraph(const int p_paragraph) { for (int i = subitem_to_remove.size() - 1; i >= 0; i--) { List<Item *>::Element *subitem = subitem_to_remove[i]; had_newline = had_newline || subitem->get()->type == ITEM_NEWLINE; - _remove_item(subitem->get(), subitem->get()->line, p_paragraph); + if (subitem->get() == current) { + pop(); + } + _remove_item(subitem->get(), p_paragraph); } if (!had_newline) { @@ -4532,7 +4535,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { if (subtag_a.size() == 2) { if (subtag_a[0] == "font" || subtag_a[0] == "f") { - String fnt = subtag_a[1]; + const String &fnt = subtag_a[1]; Ref<Font> font = ResourceLoader::load(fnt, "Font"); if (font.is_valid()) { f = font; @@ -4776,7 +4779,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { if (subtag_a.size() == 2) { if (subtag_a[0] == "name" || subtag_a[0] == "n") { - String fnt = subtag_a[1]; + const String &fnt = subtag_a[1]; Ref<Font> font_data = ResourceLoader::load(fnt, "Font"); if (font_data.is_valid()) { font = font_data; @@ -5945,8 +5948,6 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("is_menu_visible"), &RichTextLabel::is_menu_visible); ClassDB::bind_method(D_METHOD("menu_option", "option"), &RichTextLabel::menu_option); - ClassDB::bind_method(D_METHOD("_thread_end"), &RichTextLabel::_thread_end); - #ifndef DISABLE_DEPRECATED ClassDB::bind_compatibility_method(D_METHOD("push_font", "font", "font_size"), &RichTextLabel::push_font); ClassDB::bind_compatibility_method(D_METHOD("set_table_column_expand", "column", "expand", "ratio"), &RichTextLabel::set_table_column_expand); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 2f48600583..5c8585565d 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -461,7 +461,7 @@ private: _FORCE_INLINE_ float _update_scroll_exceeds(float p_total_height, float p_ctrl_height, float p_width, int p_idx, float p_old_scroll, float p_text_rect_height); void _add_item(Item *p_item, bool p_enter = false, bool p_ensure_newline = false); - void _remove_item(Item *p_item, const int p_line, const int p_subitem_line); + void _remove_item(Item *p_item, const int p_line); String language; TextDirection text_direction = TEXT_DIRECTION_AUTO; diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index b4e28a1f1b..89d308de3f 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -346,7 +346,7 @@ void ScrollContainer::_notification(int p_what) { case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { _updating_scrollbars = true; - call_deferred(SNAME("_update_scrollbar_position")); + callable_mp(this, &ScrollContainer::_update_scrollbar_position).call_deferred(); } break; case NOTIFICATION_READY: { @@ -573,8 +573,6 @@ VScrollBar *ScrollContainer::get_v_scroll_bar() { } void ScrollContainer::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_scrollbar_position"), &ScrollContainer::_update_scrollbar_position); - ClassDB::bind_method(D_METHOD("set_h_scroll", "value"), &ScrollContainer::set_h_scroll); ClassDB::bind_method(D_METHOD("get_h_scroll"), &ScrollContainer::get_h_scroll); diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 586334a0b4..69d281e373 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -64,6 +64,8 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) { } grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x; + grab.value_before_dragging = get_as_ratio(); + emit_signal(SNAME("drag_started")); double grab_width = (double)grabber->get_width(); double grab_height = (double)grabber->get_height(); @@ -78,12 +80,11 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) { grab.active = true; grab.uvalue = get_as_ratio(); - emit_signal(SNAME("drag_started")); _notify_shared_value_changed(); } else { grab.active = false; - const bool value_changed = !Math::is_equal_approx((double)grab.uvalue, get_as_ratio()); + const bool value_changed = !Math::is_equal_approx((double)grab.value_before_dragging, get_as_ratio()); emit_signal(SNAME("drag_ended"), value_changed); } } else if (scrollable) { diff --git a/scene/gui/slider.h b/scene/gui/slider.h index 05766fa742..07c1d23e32 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -38,7 +38,8 @@ class Slider : public Range { struct Grab { int pos = 0; - double uvalue = 0.0; + double uvalue = 0.0; // Value at `pos`. + double value_before_dragging = 0.0; bool active = false; } grab; diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index bd549a6e4a..d482495ca0 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -280,8 +280,8 @@ void SpinBox::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - call_deferred(SNAME("update_minimum_size")); - get_line_edit()->call_deferred(SNAME("update_minimum_size")); + callable_mp((Control *)this, &Control::update_minimum_size).call_deferred(); + callable_mp((Control *)get_line_edit(), &Control::update_minimum_size).call_deferred(); } break; case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 06b32b548f..5f4586a6d5 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -39,7 +39,7 @@ void SplitContainerDragger::gui_input(const Ref<InputEvent> &p_event) { SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent()); - if (sc->collapsed || !sc->_getch(0) || !sc->_getch(1) || sc->dragger_visibility != SplitContainer::DRAGGER_VISIBLE) { + if (sc->collapsed || !sc->get_containable_child(0) || !sc->get_containable_child(1) || sc->dragger_visibility != SplitContainer::DRAGGER_VISIBLE) { return; } @@ -122,7 +122,7 @@ void SplitContainerDragger::_notification(int p_what) { } } -Control *SplitContainer::_getch(int p_idx) const { +Control *SplitContainer::get_containable_child(int p_idx) const { int idx = 0; for (int i = 0; i < get_child_count(false); i++) { @@ -157,8 +157,8 @@ Ref<Texture2D> SplitContainer::_get_grabber_icon() const { } void SplitContainer::_compute_middle_sep(bool p_clamp) { - Control *first = _getch(0); - Control *second = _getch(1); + Control *first = get_containable_child(0); + Control *second = get_containable_child(1); // Determine expanded children. bool first_expanded = (vertical ? first->get_v_size_flags() : first->get_h_size_flags()) & SIZE_EXPAND; @@ -199,8 +199,8 @@ void SplitContainer::_compute_middle_sep(bool p_clamp) { } void SplitContainer::_resort() { - Control *first = _getch(0); - Control *second = _getch(1); + Control *first = get_containable_child(0); + Control *second = get_containable_child(1); // If we have only one element. if (!first || !second) { @@ -261,7 +261,7 @@ Size2 SplitContainer::get_minimum_size() const { int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? g->get_height() : g->get_width()) : 0; for (int i = 0; i < 2; i++) { - if (!_getch(i)) { + if (!get_containable_child(i)) { break; } @@ -273,7 +273,7 @@ Size2 SplitContainer::get_minimum_size() const { } } - Size2 ms = _getch(i)->get_combined_minimum_size(); + Size2 ms = get_containable_child(i)->get_combined_minimum_size(); if (vertical) { minimum.height += ms.height; @@ -325,7 +325,7 @@ int SplitContainer::get_split_offset() const { } void SplitContainer::clamp_split_offset() { - if (!_getch(0) || !_getch(1)) { + if (!get_containable_child(0) || !get_containable_child(1)) { return; } diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index f008d2678b..0f45ef166d 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -79,8 +79,6 @@ private: Ref<Texture2D> grabber_icon_v; } theme_cache; - Control *_getch(int p_idx) const; - Ref<Texture2D> _get_grabber_icon() const; void _compute_middle_sep(bool p_clamp); void _resort(); @@ -88,6 +86,8 @@ private: protected: bool is_fixed = false; + Control *get_containable_child(int p_idx) const; + void _notification(int p_what); void _validate_property(PropertyInfo &p_property) const; static void _bind_methods(); diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index e9fbdbb312..c153f8bd7d 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -30,7 +30,6 @@ #include "tab_bar.h" -#include "core/object/message_queue.h" #include "core/string/translation.h" #include "scene/gui/box_container.h" #include "scene/gui/label.h" @@ -516,7 +515,13 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in bool rtl = is_layout_rtl(); Rect2 sb_rect = Rect2(p_x, 0, tabs[p_index].size_cache, get_size().height); + if (tab_style_v_flip) { + draw_set_transform(Point2(0.0, p_tab_style->get_draw_rect(sb_rect).size.y), 0.0, Size2(1.0, -1.0)); + } p_tab_style->draw(ci, sb_rect); + if (tab_style_v_flip) { + draw_set_transform(Point2(), 0.0, Size2(1.0, 1.0)); + } if (p_focus) { Ref<StyleBox> focus_style = theme_cache.tab_focus_style; focus_style->draw(ci, sb_rect); @@ -1367,6 +1372,10 @@ bool TabBar::get_clip_tabs() const { return clip_tabs; } +void TabBar::set_tab_style_v_flip(bool p_tab_style_v_flip) { + tab_style_v_flip = p_tab_style_v_flip; +} + void TabBar::move_tab(int p_from, int p_to) { if (p_from == p_to) { return; @@ -1657,7 +1666,7 @@ bool TabBar::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("tab_") && components[0].trim_prefix("tab_").is_valid_int()) { int tab_index = components[0].trim_prefix("tab_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "title") { set_tab_title(tab_index, p_value); return true; @@ -1676,7 +1685,7 @@ bool TabBar::_get(const StringName &p_name, Variant &r_ret) const { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("tab_") && components[0].trim_prefix("tab_").is_valid_int()) { int tab_index = components[0].trim_prefix("tab_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "title") { r_ret = get_tab_title(tab_index); return true; diff --git a/scene/gui/tab_bar.h b/scene/gui/tab_bar.h index 28e3411f3d..9674187fb3 100644 --- a/scene/gui/tab_bar.h +++ b/scene/gui/tab_bar.h @@ -91,6 +91,7 @@ private: bool clip_tabs = true; int rb_hover = -1; bool rb_pressing = false; + bool tab_style_v_flip = false; bool select_with_rmb = false; @@ -210,6 +211,8 @@ public: void set_clip_tabs(bool p_clip_tabs); bool get_clip_tabs() const; + void set_tab_style_v_flip(bool p_tab_style_v_flip); + void move_tab(int p_from, int p_to); void set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 0f461f4865..ef01d9ec5d 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -35,7 +35,7 @@ #include "scene/gui/texture_rect.h" #include "scene/theme/theme_db.h" -int TabContainer::_get_top_margin() const { +int TabContainer::_get_tab_height() const { int height = 0; if (tabs_visible && get_tab_count() > 0) { height = tab_bar->get_minimum_size().height; @@ -54,31 +54,33 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Point2 pos = mb->get_position(); Size2 size = get_size(); + real_t content_height = size.height - _get_tab_height(); // Click must be on tabs in the tab header area. - if (pos.y > _get_top_margin()) { + if (tabs_position == POSITION_TOP && pos.y > _get_tab_height()) { + return; + } + if (tabs_position == POSITION_BOTTOM && pos.y < content_height) { return; } // Handle menu button. - if (is_layout_rtl()) { - if (popup && pos.x < theme_cache.menu_icon->get_width()) { - emit_signal(SNAME("pre_popup_pressed")); - - Vector2 popup_pos = get_screen_position(); - popup_pos.y += theme_cache.menu_icon->get_height(); - - popup->set_position(popup_pos); - popup->popup(); - return; - } - } else { - if (popup && pos.x > size.width - theme_cache.menu_icon->get_width()) { + if (popup) { + if (is_layout_rtl() ? pos.x < theme_cache.menu_icon->get_width() : pos.x > size.width - theme_cache.menu_icon->get_width()) { emit_signal(SNAME("pre_popup_pressed")); Vector2 popup_pos = get_screen_position(); - popup_pos.x += size.width - popup->get_size().width; - popup_pos.y += theme_cache.menu_icon->get_height(); + if (!is_layout_rtl()) { + popup_pos.x += size.width - popup->get_size().width; + } + popup_pos.y += _get_tab_height() / 2.0; + if (tabs_position == POSITION_BOTTOM) { + popup_pos.y += content_height; + popup_pos.y -= popup->get_size().height; + popup_pos.y -= theme_cache.menu_icon->get_height() / 2.0; + } else { + popup_pos.y += theme_cache.menu_icon->get_height() / 2.0; + } popup->set_position(popup_pos); popup->popup(); @@ -94,7 +96,14 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) { Size2 size = get_size(); // Mouse must be on tabs in the tab header area. - if (pos.y > _get_top_margin()) { + if (tabs_position == POSITION_TOP && pos.y > _get_tab_height()) { + if (menu_hovered) { + menu_hovered = false; + queue_redraw(); + } + return; + } + if (tabs_position == POSITION_BOTTOM && pos.y < size.height - _get_tab_height()) { if (menu_hovered) { menu_hovered = false; queue_redraw(); @@ -165,21 +174,22 @@ void TabContainer::_notification(int p_what) { return; } - int header_height = _get_top_margin(); + int header_height = _get_tab_height(); + int header_voffset = int(tabs_position == POSITION_BOTTOM) * (size.height - header_height); // Draw background for the tabbar. - theme_cache.tabbar_style->draw(canvas, Rect2(0, 0, size.width, header_height)); + theme_cache.tabbar_style->draw(canvas, Rect2(0, header_voffset, size.width, header_height)); // Draw the background for the tab's content. - theme_cache.panel_style->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height)); + theme_cache.panel_style->draw(canvas, Rect2(0, int(tabs_position == POSITION_TOP) * header_height, size.width, size.height - header_height)); // Draw the popup menu. if (get_popup()) { int x = is_layout_rtl() ? 0 : get_size().width - theme_cache.menu_icon->get_width(); if (menu_hovered) { - theme_cache.menu_hl_icon->draw(get_canvas_item(), Point2(x, (header_height - theme_cache.menu_hl_icon->get_height()) / 2)); + theme_cache.menu_hl_icon->draw(get_canvas_item(), Point2(x, header_voffset + (header_height - theme_cache.menu_hl_icon->get_height()) / 2)); } else { - theme_cache.menu_icon->draw(get_canvas_item(), Point2(x, (header_height - theme_cache.menu_icon->get_height()) / 2)); + theme_cache.menu_icon->draw(get_canvas_item(), Point2(x, header_voffset + (header_height - theme_cache.menu_icon->get_height()) / 2)); } } } break; @@ -243,6 +253,12 @@ void TabContainer::_repaint() { Vector<Control *> controls = _get_tab_controls(); int current = get_current_tab(); + if (tabs_position == POSITION_BOTTOM) { + tab_bar->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE); + } else { + tab_bar->set_anchors_and_offsets_preset(PRESET_TOP_WIDE); + } + for (int i = 0; i < controls.size(); i++) { Control *c = controls[i]; @@ -251,7 +267,11 @@ void TabContainer::_repaint() { c->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); if (tabs_visible) { - c->set_offset(SIDE_TOP, _get_top_margin()); + if (tabs_position == POSITION_BOTTOM) { + c->set_offset(SIDE_BOTTOM, -_get_tab_height()); + } else { + c->set_offset(SIDE_TOP, _get_tab_height()); + } } c->set_offset(SIDE_TOP, c->get_offset(SIDE_TOP) + theme_cache.panel_style->get_margin(SIDE_TOP)); @@ -263,6 +283,7 @@ void TabContainer::_repaint() { } } + _update_margins(); update_minimum_size(); } @@ -609,6 +630,23 @@ TabBar::AlignmentMode TabContainer::get_tab_alignment() const { return tab_bar->get_tab_alignment(); } +void TabContainer::set_tabs_position(TabPosition p_tabs_position) { + ERR_FAIL_INDEX(p_tabs_position, POSITION_MAX); + if (p_tabs_position == tabs_position) { + return; + } + tabs_position = p_tabs_position; + + tab_bar->set_tab_style_v_flip(tabs_position == POSITION_BOTTOM); + + callable_mp(this, &TabContainer::_repaint).call_deferred(); + queue_redraw(); +} + +TabContainer::TabPosition TabContainer::get_tabs_position() const { + return tabs_position; +} + void TabContainer::set_tab_focus_mode(Control::FocusMode p_focus_mode) { tab_bar->set_focus_mode(p_focus_mode); } @@ -633,18 +671,8 @@ void TabContainer::set_tabs_visible(bool p_visible) { tabs_visible = p_visible; tab_bar->set_visible(tabs_visible); - Vector<Control *> controls = _get_tab_controls(); - for (int i = 0; i < controls.size(); i++) { - Control *c = controls[i]; - if (tabs_visible) { - c->set_offset(SIDE_TOP, _get_top_margin()); - } else { - c->set_offset(SIDE_TOP, 0); - } - } - + callable_mp(this, &TabContainer::_repaint).call_deferred(); queue_redraw(); - update_minimum_size(); } bool TabContainer::are_tabs_visible() const { @@ -890,6 +918,8 @@ void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tab_control", "tab_idx"), &TabContainer::get_tab_control); ClassDB::bind_method(D_METHOD("set_tab_alignment", "alignment"), &TabContainer::set_tab_alignment); ClassDB::bind_method(D_METHOD("get_tab_alignment"), &TabContainer::get_tab_alignment); + ClassDB::bind_method(D_METHOD("set_tabs_position", "tabs_position"), &TabContainer::set_tabs_position); + ClassDB::bind_method(D_METHOD("get_tabs_position"), &TabContainer::get_tabs_position); ClassDB::bind_method(D_METHOD("set_clip_tabs", "clip_tabs"), &TabContainer::set_clip_tabs); ClassDB::bind_method(D_METHOD("get_clip_tabs"), &TabContainer::get_clip_tabs); ClassDB::bind_method(D_METHOD("set_tabs_visible", "visible"), &TabContainer::set_tabs_visible); @@ -931,6 +961,7 @@ void TabContainer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1"), "set_current_tab", "get_current_tab"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "tabs_position", PROPERTY_HINT_ENUM, "Top,Bottom"), "set_tabs_position", "get_tabs_position"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), "set_tabs_visible", "are_tabs_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "all_tabs_in_front"), "set_all_tabs_in_front", "is_all_tabs_in_front"); @@ -939,6 +970,10 @@ void TabContainer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hidden_tabs_for_min_size"), "set_use_hidden_tabs_for_min_size", "get_use_hidden_tabs_for_min_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_tab_focus_mode", "get_tab_focus_mode"); + BIND_ENUM_CONSTANT(POSITION_TOP); + BIND_ENUM_CONSTANT(POSITION_BOTTOM); + BIND_ENUM_CONSTANT(POSITION_MAX); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, side_margin); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, panel_style, "panel"); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 450143cd0c..0c645b4598 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -38,9 +38,18 @@ class TabContainer : public Container { GDCLASS(TabContainer, Container); +public: + enum TabPosition { + POSITION_TOP, + POSITION_BOTTOM, + POSITION_MAX, + }; + +private: TabBar *tab_bar = nullptr; bool tabs_visible = true; bool all_tabs_in_front = false; + TabPosition tabs_position = POSITION_TOP; bool menu_hovered = false; mutable ObjectID popup_obj_id; bool use_hidden_tabs_for_min_size = false; @@ -86,7 +95,7 @@ class TabContainer : public Container { int tab_font_size; } theme_cache; - int _get_top_margin() const; + int _get_tab_height() const; Vector<Control *> _get_tab_controls() const; void _on_theme_changed(); void _repaint(); @@ -124,6 +133,9 @@ public: void set_tab_alignment(TabBar::AlignmentMode p_alignment); TabBar::AlignmentMode get_tab_alignment() const; + void set_tabs_position(TabPosition p_tab_position); + TabPosition get_tabs_position() const; + void set_tab_focus_mode(FocusMode p_focus_mode); FocusMode get_tab_focus_mode() const; @@ -185,4 +197,6 @@ public: TabContainer(); }; +VARIANT_ENUM_CAST(TabContainer::TabPosition); + #endif // TAB_CONTAINER_H diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index cd1450b879..540c999131 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -33,7 +33,6 @@ #include "core/config/project_settings.h" #include "core/input/input.h" #include "core/input/input_map.h" -#include "core/object/message_queue.h" #include "core/object/script_language.h" #include "core/os/keyboard.h" #include "core/os/os.h" @@ -428,10 +427,10 @@ void TextEdit::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { _update_caches(); if (caret_pos_dirty) { - MessageQueue::get_singleton()->push_call(this, "_emit_caret_changed"); + callable_mp(this, &TextEdit::_emit_caret_changed).call_deferred(); } if (text_changed_dirty) { - MessageQueue::get_singleton()->push_call(this, "_text_changed_emit"); + callable_mp(this, &TextEdit::_text_changed_emit).call_deferred(); } _update_wrap_at_column(true); } break; @@ -443,8 +442,8 @@ void TextEdit::_notification(int p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { if (is_visible()) { - call_deferred(SNAME("_update_scrollbars")); - call_deferred(SNAME("_update_wrap_at_column")); + callable_mp(this, &TextEdit::_update_scrollbars).call_deferred(); + callable_mp(this, &TextEdit::_update_wrap_at_column).call_deferred(false); } } break; @@ -989,18 +988,6 @@ void TextEdit::_notification(int p_what) { RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); } } - - // Give visual indication of empty selected line. - for (int c = 0; c < carets.size(); c++) { - if (has_selection(c) && line >= get_selection_from_line(c) && line <= get_selection_to_line(c) && char_margin >= xmargin_beg) { - float char_w = theme_cache.font->get_char_size(' ', theme_cache.font_size).width; - if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_beg - ofs_x - char_w, ofs_y, char_w, row_height), theme_cache.selection_color); - } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, char_w, row_height), theme_cache.selection_color); - } - } - } } else { // If it has text, then draw current line marker in the margin, as line number etc will draw over it, draw the rest of line marker later. if (caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index) && highlight_current_line) { @@ -1093,13 +1080,26 @@ void TextEdit::_notification(int p_what) { char_margin = size.width - char_margin - TS->shaped_text_get_size(rid).x; } + // Draw selections. + float char_w = theme_cache.font->get_char_size(' ', theme_cache.font_size).width; for (int c = 0; c < carets.size(); c++) { - if (!clipped && has_selection(c) && line >= get_selection_from_line(c) && line <= get_selection_to_line(c)) { // Selection + if (!clipped && has_selection(c) && line >= get_selection_from_line(c) && line <= get_selection_to_line(c)) { int sel_from = (line > get_selection_from_line(c)) ? TS->shaped_text_get_range(rid).x : get_selection_from_column(c); int sel_to = (line < get_selection_to_line(c)) ? TS->shaped_text_get_range(rid).y : get_selection_to_column(c); Vector<Vector2> sel = TS->shaped_text_get_selection(rid, sel_from, sel_to); + + // Show selection at the end of line. + if (line < get_selection_to_line(c)) { + if (rtl) { + sel.push_back(Vector2(-char_w, 0)); + } else { + float line_end = TS->shaped_text_get_size(rid).width; + sel.push_back(Vector2(line_end, line_end + char_w)); + } + } + for (int j = 0; j < sel.size(); j++) { - Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height); + Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, Math::ceil(sel[j].y - sel[j].x), row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { continue; } @@ -4007,7 +4007,7 @@ void TextEdit::undo() { if (dirty_carets && !caret_pos_dirty) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_emit_caret_changed"); + callable_mp(this, &TextEdit::_emit_caret_changed).call_deferred(); } caret_pos_dirty = true; } @@ -4062,7 +4062,7 @@ void TextEdit::redo() { if (dirty_carets && !caret_pos_dirty) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_emit_caret_changed"); + callable_mp(this, &TextEdit::_emit_caret_changed).call_deferred(); } caret_pos_dirty = true; } @@ -4868,7 +4868,7 @@ void TextEdit::set_caret_line(int p_line, bool p_adjust_viewport, bool p_can_be_ if (caret_moved && !caret_pos_dirty) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_emit_caret_changed"); + callable_mp(this, &TextEdit::_emit_caret_changed).call_deferred(); } caret_pos_dirty = true; } @@ -4899,7 +4899,7 @@ void TextEdit::set_caret_column(int p_col, bool p_adjust_viewport, int p_caret) if (caret_moved && !caret_pos_dirty) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_emit_caret_changed"); + callable_mp(this, &TextEdit::_emit_caret_changed).call_deferred(); } caret_pos_dirty = true; } @@ -6026,10 +6026,6 @@ Color TextEdit::get_font_color() const { } void TextEdit::_bind_methods() { - /* Internal. */ - - ClassDB::bind_method(D_METHOD("_text_changed_emit"), &TextEdit::_text_changed_emit); - /* Text */ // Text properties ClassDB::bind_method(D_METHOD("has_ime_text"), &TextEdit::has_ime_text); @@ -6200,9 +6196,6 @@ void TextEdit::_bind_methods() { BIND_ENUM_CONSTANT(CARET_TYPE_LINE); BIND_ENUM_CONSTANT(CARET_TYPE_BLOCK); - // Internal. - ClassDB::bind_method(D_METHOD("_emit_caret_changed"), &TextEdit::_emit_caret_changed); - ClassDB::bind_method(D_METHOD("set_caret_type", "type"), &TextEdit::set_caret_type); ClassDB::bind_method(D_METHOD("get_caret_type"), &TextEdit::get_caret_type); @@ -6290,9 +6283,6 @@ void TextEdit::_bind_methods() { BIND_ENUM_CONSTANT(LINE_WRAPPING_NONE); BIND_ENUM_CONSTANT(LINE_WRAPPING_BOUNDARY); - // Internal. - ClassDB::bind_method(D_METHOD("_update_wrap_at_column", "force"), &TextEdit::_update_wrap_at_column, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("set_line_wrapping_mode", "mode"), &TextEdit::set_line_wrapping_mode); ClassDB::bind_method(D_METHOD("get_line_wrapping_mode"), &TextEdit::get_line_wrapping_mode); @@ -7826,7 +7816,7 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i if (!text_changed_dirty && !setting_text) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_text_changed_emit"); + callable_mp(this, &TextEdit::_text_changed_emit).call_deferred(); } text_changed_dirty = true; } @@ -7872,7 +7862,7 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li if (!text_changed_dirty && !setting_text) { if (is_inside_tree()) { - MessageQueue::get_singleton()->push_call(this, "_text_changed_emit"); + callable_mp(this, &TextEdit::_text_changed_emit).call_deferred(); } text_changed_dirty = true; } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6936bcb441..c67c3cd98d 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -4784,7 +4784,7 @@ void Tree::ensure_cursor_is_visible() { if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet. v_scroll->set_value(y_offset); } else if (y_offset + cell_h > v_scroll->get_value() + screen_h) { - v_scroll->call_deferred(SNAME("set_value"), y_offset - screen_h + cell_h); + callable_mp((Range *)v_scroll, &Range::set_value).call_deferred(y_offset - screen_h + cell_h); } else if (y_offset < v_scroll->get_value()) { v_scroll->set_value(y_offset); } @@ -4802,7 +4802,7 @@ void Tree::ensure_cursor_is_visible() { if (cell_w > screen_w) { h_scroll->set_value(x_offset); } else if (x_offset + cell_w > h_scroll->get_value() + screen_w) { - h_scroll->call_deferred(SNAME("set_value"), x_offset - screen_w + cell_w); + callable_mp((Range *)h_scroll, &Range::set_value).call_deferred(x_offset - screen_w + cell_w); } else if (x_offset < h_scroll->get_value()) { h_scroll->set_value(x_offset); } diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 4ee81e5cb0..7fff2f90fb 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -30,7 +30,6 @@ #include "canvas_item.h" -#include "core/object/message_queue.h" #include "scene/2d/canvas_group.h" #include "scene/main/canvas_layer.h" #include "scene/main/window.h" @@ -278,6 +277,8 @@ void CanvasItem::_notification(int p_what) { ERR_MAIN_THREAD_GUARD; ERR_FAIL_COND(!is_inside_tree()); + _set_global_invalid(true); + Node *parent = get_parent(); if (parent) { CanvasItem *ci = Object::cast_to<CanvasItem>(parent); @@ -315,6 +316,7 @@ void CanvasItem::_notification(int p_what) { } } + _set_global_invalid(true); _enter_canvas(); RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, is_visible_in_tree()); // The visibility of the parent may change. @@ -407,7 +409,7 @@ void CanvasItem::queue_redraw() { pending_update = true; - MessageQueue::get_singleton()->push_callable(callable_mp(this, &CanvasItem::_redraw_callback)); + callable_mp(this, &CanvasItem::_redraw_callback).call_deferred(); } void CanvasItem::move_to_front() { @@ -904,7 +906,7 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) { get_tree()->xform_change_list.add(&p_node->xform_change); } else { // Should be rare, but still needs to be handled. - MessageQueue::get_singleton()->push_callable(callable_mp(p_node, &CanvasItem::_notify_transform_deferred)); + callable_mp(p_node, &CanvasItem::_notify_transform_deferred).call_deferred(); } } } diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 36f0e17924..ce1dbce6c3 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -237,7 +237,7 @@ public: Color get_modulate() const; Color get_modulate_in_tree() const; - void set_self_modulate(const Color &p_self_modulate); + virtual void set_self_modulate(const Color &p_self_modulate); Color get_self_modulate() const; void set_visibility_layer(uint32_t p_visibility_layer); @@ -248,7 +248,7 @@ public: /* ORDERING */ - void set_z_index(int p_z); + virtual void set_z_index(int p_z); int get_z_index() const; int get_effective_z_index() const; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index ddc694f894..fa14ad5b3c 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -472,7 +472,7 @@ bool HTTPRequest::_update_connection() { } void HTTPRequest::_defer_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data) { - call_deferred(SNAME("_request_done"), p_status, p_code, p_headers, p_data); + callable_mp(this, &HTTPRequest::_request_done).call_deferred(p_status, p_code, p_headers, p_data); } void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data) { @@ -503,7 +503,9 @@ void HTTPRequest::_notification(int p_what) { void HTTPRequest::set_use_threads(bool p_use) { ERR_FAIL_COND(get_http_client_status() != HTTPClient::STATUS_DISCONNECTED); +#ifdef THREADS_ENABLED use_threads.set_to(p_use); +#endif } bool HTTPRequest::is_using_threads() const { @@ -621,8 +623,6 @@ void HTTPRequest::_bind_methods() { ClassDB::bind_method(D_METHOD("get_downloaded_bytes"), &HTTPRequest::get_downloaded_bytes); ClassDB::bind_method(D_METHOD("get_body_size"), &HTTPRequest::get_body_size); - ClassDB::bind_method(D_METHOD("_request_done"), &HTTPRequest::_request_done); - ClassDB::bind_method(D_METHOD("set_timeout", "timeout"), &HTTPRequest::set_timeout); ClassDB::bind_method(D_METHOD("get_timeout"), &HTTPRequest::get_timeout); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 3cb06e769f..f7d695bf31 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1736,8 +1736,40 @@ void Node::reparent(Node *p_parent, bool p_keep_global_transform) { return; } + bool preserve_owner = data.owner && (data.owner == p_parent || data.owner->is_ancestor_of(p_parent)); + Node *owner_temp = data.owner; + LocalVector<Node *> common_parents; + + // If the new parent is related to the owner, find all children of the reparented node who have the same owner so that we can reassign them. + if (preserve_owner) { + LocalVector<Node *> to_visit; + + to_visit.push_back(this); + common_parents.push_back(this); + + while (to_visit.size() > 0) { + Node *check = to_visit[to_visit.size() - 1]; + to_visit.resize(to_visit.size() - 1); + + for (int i = 0; i < check->get_child_count(); i++) { + Node *child = check->get_child(i, false); + to_visit.push_back(child); + if (child->data.owner == owner_temp) { + common_parents.push_back(child); + } + } + } + } + data.parent->remove_child(this); p_parent->add_child(this); + + // Reassign the old owner to those found nodes. + if (preserve_owner) { + for (Node *E : common_parents) { + E->set_owner(owner_temp); + } + } } Node *Node::get_parent() const { @@ -1925,7 +1957,7 @@ void Node::set_owner(Node *p_owner) { return; } - Node *check = this->get_parent(); + Node *check = get_parent(); bool owner_valid = false; while (check) { @@ -2311,11 +2343,7 @@ void Node::set_editor_description(const String &p_editor_description) { } data.editor_description = p_editor_description; - - if (Engine::get_singleton()->is_editor_hint() && is_inside_tree()) { - // Update tree so the tooltip in the Scene tree dock is also updated in the editor. - get_tree()->tree_changed(); - } + emit_signal(SNAME("editor_description_changed"), this); } String Node::get_editor_description() const { @@ -2832,7 +2860,7 @@ void Node::replace_by(Node *p_node, bool p_keep_groups) { } Node *parent = data.parent; - int index_in_parent = get_index(); + int index_in_parent = get_index(false); if (data.parent) { parent->remove_child(this); @@ -3060,6 +3088,10 @@ static void _add_nodes_to_options(const Node *p_base, const Node *p_node, List<S if (p_node != p_base && !p_node->get_owner()) { return; } + if (p_node->is_unique_name_in_owner() && p_node->get_owner() == p_base) { + String n = "%" + p_node->get_name(); + r_options->push_back(n.quote()); + } String n = p_base->get_path_to(p_node); r_options->push_back(n.quote()); for (int i = 0; i < p_node->get_child_count(); i++) { @@ -3069,7 +3101,7 @@ static void _add_nodes_to_options(const Node *p_base, const Node *p_node, List<S void Node::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { String pf = p_function; - if (p_idx == 0 && (pf == "has_node" || pf == "get_node")) { + if (p_idx == 0 && (pf == "has_node" || pf == "get_node" || pf == "get_node_or_null")) { _add_nodes_to_options(this, this, r_options); } else if (p_idx == 0 && (pf == "add_to_group" || pf == "remove_from_group" || pf == "is_in_group")) { HashMap<StringName, String> global_groups = ProjectSettings::get_singleton()->get_global_groups_list(); @@ -3536,6 +3568,7 @@ void Node::_bind_methods() { ADD_SIGNAL(MethodInfo("child_order_changed")); ADD_SIGNAL(MethodInfo("replacing_by", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "Node"))); + ADD_SIGNAL(MethodInfo("editor_description_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "Node"))); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_name", "get_name"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "unique_name_in_owner", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_unique_name_in_owner", "is_unique_name_in_owner"); diff --git a/scene/main/node.h b/scene/main/node.h index cd1c31d784..8130c61a34 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -558,7 +558,9 @@ public: _FORCE_INLINE_ bool is_readable_from_caller_thread() const { if (current_process_thread_group == nullptr) { // No thread processing. - return is_current_thread_safe_for_nodes(); + // Only accessible if node is outside the scene tree + // or access will happen from a node-safe thread. + return !data.inside_tree || is_current_thread_safe_for_nodes(); } else { // Thread processing. return true; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index b6fbd70e14..ee0e7721a0 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1728,6 +1728,7 @@ void SceneTree::get_argument_options(const StringName &p_function, int p_idx, Li } } } + MainLoop::get_argument_options(p_function, p_idx, r_options); } void SceneTree::set_disable_node_threading(bool p_disable) { diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 89ec5636ab..fe02d97586 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -32,7 +32,6 @@ #include "core/config/project_settings.h" #include "core/debugger/engine_debugger.h" -#include "core/object/message_queue.h" #include "core/string/translation.h" #include "core/templates/pair.h" #include "core/templates/sort_array.h" @@ -1054,7 +1053,7 @@ void Viewport::canvas_parent_mark_dirty(Node *p_node) { bool request_update = gui.canvas_parents_with_dirty_order.is_empty(); gui.canvas_parents_with_dirty_order.insert(p_node->get_instance_id()); if (request_update) { - MessageQueue::get_singleton()->push_callable(callable_mp(this, &Viewport::_process_dirty_canvas_parent_orders)); + callable_mp(this, &Viewport::_process_dirty_canvas_parent_orders).call_deferred(); } } @@ -2073,7 +2072,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Window *w = Object::cast_to<Window>(ObjectDB::get_instance(object_under)); if (w) { viewport_under = w; - viewport_pos = screen_mouse_pos - w->get_position(); + viewport_pos = w->get_final_transform().affine_inverse().xform(screen_mouse_pos - w->get_position()); } } } @@ -2700,7 +2699,7 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus void Viewport::_gui_grab_click_focus(Control *p_control) { gui.mouse_click_grabber = p_control; - call_deferred(SNAME("_post_gui_grab_click_focus")); + callable_mp(this, &Viewport::_post_gui_grab_click_focus).call_deferred(); } void Viewport::_post_gui_grab_click_focus() { @@ -2748,7 +2747,7 @@ void Viewport::_post_gui_grab_click_focus() { mb->set_button_index(MouseButton(i + 1)); mb->set_pressed(true); mb->set_device(InputEvent::DEVICE_ID_INTERNAL); - MessageQueue::get_singleton()->push_callable(callable_mp(gui.mouse_focus, &Control::_call_gui_input), mb); + callable_mp(gui.mouse_focus, &Control::_call_gui_input).call_deferred(mb); } } } @@ -3853,7 +3852,66 @@ Viewport *Viewport::get_parent_viewport() const { void Viewport::set_embedding_subwindows(bool p_embed) { ERR_THREAD_GUARD; - gui.embed_subwindows_hint = p_embed; + if (gui.embed_subwindows_hint == p_embed) { + return; + } + + bool allow_change = true; + + if (!is_inside_tree()) { + // Change can happen since no child window is displayed. + } else if (gui.embed_subwindows_hint) { + if (!gui.sub_windows.is_empty()) { + // Prevent change when this viewport has embedded windows. + allow_change = false; + } + } else { + Viewport *vp = this; + while (true) { + if (!vp->get_parent()) { + // Root window reached. + break; + } + vp = vp->get_parent()->get_viewport(); + if (vp->is_embedding_subwindows()) { + for (int i = 0; i < vp->gui.sub_windows.size(); i++) { + if (is_ancestor_of(vp->gui.sub_windows[i].window)) { + // Prevent change when this viewport has child windows that are displayed in an ancestor viewport. + allow_change = false; + break; + } + } + } + } + + if (allow_change) { + Vector<int> wl = DisplayServer::get_singleton()->get_window_list(); + for (int index = 0; index < wl.size(); index++) { + DisplayServer::WindowID wid = wl[index]; + if (wid == DisplayServer::INVALID_WINDOW_ID) { + continue; + } + + ObjectID woid = DisplayServer::get_singleton()->window_get_attached_instance_id(wid); + if (woid.is_null()) { + continue; + } + + Window *w = Object::cast_to<Window>(ObjectDB::get_instance(woid)); + if (w && is_ancestor_of(w)) { + // Prevent change when this viewport has child windows that are displayed as native windows. + allow_change = false; + break; + } + } + } + } + + if (allow_change) { + gui.embed_subwindows_hint = p_embed; + } else { + WARN_PRINT("Can't change \"gui_embed_subwindows\" while a child window is displayed. Consider hiding all child windows before changing this value."); + } } bool Viewport::is_embedding_subwindows() const { @@ -4568,7 +4626,6 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled); ClassDB::bind_method(D_METHOD("_gui_remove_focus_for_window"), &Viewport::_gui_remove_focus_for_window); - ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus); ClassDB::bind_method(D_METHOD("set_positional_shadow_atlas_size", "size"), &Viewport::set_positional_shadow_atlas_size); ClassDB::bind_method(D_METHOD("get_positional_shadow_atlas_size"), &Viewport::get_positional_shadow_atlas_size); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index eb431445ed..70b70b8928 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -520,15 +520,12 @@ void Window::request_attention() { } } +#ifndef DISABLE_DEPRECATED void Window::move_to_foreground() { - ERR_MAIN_THREAD_GUARD; - if (embedder) { - embedder->_sub_window_grab_focus(this); - - } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { - DisplayServer::get_singleton()->window_move_to_foreground(window_id); - } + WARN_DEPRECATED_MSG(R"*(The "move_to_foreground()" method is deprecated, use "grab_focus()" instead.)*"); + grab_focus(); } +#endif // DISABLE_DEPRECATED bool Window::can_draw() const { ERR_READ_THREAD_GUARD_V(false); @@ -573,6 +570,10 @@ bool Window::is_in_edited_scene_root() const { void Window::_make_window() { ERR_FAIL_COND(window_id != DisplayServer::INVALID_WINDOW_ID); + if (transient && transient_to_focused) { + _make_transient(); + } + uint32_t f = 0; for (int i = 0; i < FLAG_MAX; i++) { if (flags[i]) { @@ -665,6 +666,10 @@ void Window::_clear_window() { _update_viewport_size(); RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); + + if (transient && transient_to_focused) { + _clear_transient(); + } } void Window::_rect_changed_callback(const Rect2i &p_callback) { @@ -864,18 +869,29 @@ void Window::_make_transient() { return; } //find transient parent - Viewport *vp = get_parent()->get_viewport(); + Window *window = nullptr; - while (vp) { - window = Object::cast_to<Window>(vp); - if (window) { - break; - } - if (!vp->get_parent()) { - break; + + if (!is_embedded() && transient_to_focused) { + DisplayServer::WindowID focused_window_id = DisplayServer::get_singleton()->get_focused_window(); + if (focused_window_id != DisplayServer::INVALID_WINDOW_ID) { + window = Object::cast_to<Window>(ObjectDB::get_instance(DisplayServer::get_singleton()->window_get_attached_instance_id(focused_window_id))); } + } - vp = vp->get_parent()->get_viewport(); + if (!window) { + Viewport *vp = get_parent()->get_viewport(); + while (vp) { + window = Object::cast_to<Window>(vp); + if (window) { + break; + } + if (!vp->get_parent()) { + break; + } + + vp = vp->get_parent()->get_viewport(); + } } if (window) { @@ -919,17 +935,32 @@ void Window::set_transient(bool p_transient) { } if (transient) { - _make_transient(); + if (!transient_to_focused) { + _make_transient(); + } } else { _clear_transient(); } } bool Window::is_transient() const { - ERR_READ_THREAD_GUARD_V(false); return transient; } +void Window::set_transient_to_focused(bool p_transient_to_focused) { + ERR_MAIN_THREAD_GUARD; + if (transient_to_focused == p_transient_to_focused) { + return; + } + + transient_to_focused = p_transient_to_focused; +} + +bool Window::is_transient_to_focused() const { + ERR_READ_THREAD_GUARD_V(false); + return transient_to_focused; +} + void Window::set_exclusive(bool p_exclusive) { ERR_MAIN_THREAD_GUARD; if (exclusive == p_exclusive) { @@ -1160,7 +1191,10 @@ void Window::_update_viewport_size() { } } - notification(NOTIFICATION_WM_SIZE_CHANGED); + if (old_size != size) { + old_size = size; + notification(NOTIFICATION_WM_SIZE_CHANGED); + } if (embedder) { embedder->_sub_window_update(this); @@ -1259,7 +1293,7 @@ void Window::_notification(int p_what) { } } - if (transient) { + if (transient && !transient_to_focused) { _make_transient(); } if (visible) { @@ -1513,7 +1547,7 @@ void Window::child_controls_changed() { } updating_child_controls = true; - call_deferred(SNAME("_update_child_controls")); + callable_mp(this, &Window::_update_child_controls).call_deferred(); } void Window::_update_child_controls() { @@ -1994,7 +2028,7 @@ void Window::_update_theme_item_cache() { // Updating without a delay can cause a lot of lag. if (!wrap_controls) { updating_embedded_window = true; - call_deferred(SNAME("_update_embedded_window")); + callable_mp(this, &Window::_update_embedded_window).call_deferred(); } else { child_controls_changed(); } @@ -2742,7 +2776,9 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("request_attention"), &Window::request_attention); +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("move_to_foreground"), &Window::move_to_foreground); +#endif // DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Window::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &Window::is_visible); @@ -2753,6 +2789,9 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_transient", "transient"), &Window::set_transient); ClassDB::bind_method(D_METHOD("is_transient"), &Window::is_transient); + ClassDB::bind_method(D_METHOD("set_transient_to_focused", "enable"), &Window::set_transient_to_focused); + ClassDB::bind_method(D_METHOD("is_transient_to_focused"), &Window::is_transient_to_focused); + ClassDB::bind_method(D_METHOD("set_exclusive", "exclusive"), &Window::set_exclusive); ClassDB::bind_method(D_METHOD("is_exclusive"), &Window::is_exclusive); @@ -2797,9 +2836,6 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("is_wrapping_controls"), &Window::is_wrapping_controls); ClassDB::bind_method(D_METHOD("child_controls_changed"), &Window::child_controls_changed); - ClassDB::bind_method(D_METHOD("_update_child_controls"), &Window::_update_child_controls); - ClassDB::bind_method(D_METHOD("_update_embedded_window"), &Window::_update_embedded_window); - ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme); ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme); @@ -2884,6 +2920,7 @@ void Window::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_controls"), "set_wrap_controls", "is_wrapping_controls"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient"), "set_transient", "is_transient"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient_to_focused"), "set_transient_to_focused", "is_transient_to_focused"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclusive"), "set_exclusive", "is_exclusive"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unresizable"), "set_flag", "get_flag", FLAG_RESIZE_DISABLED); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "borderless"), "set_flag", "get_flag", FLAG_BORDERLESS); diff --git a/scene/main/window.h b/scene/main/window.h index 0682abc3c7..4ae535848a 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -117,6 +117,7 @@ private: mutable Size2i size = Size2i(DEFAULT_WINDOW_SIZE, DEFAULT_WINDOW_SIZE); mutable Size2i min_size; mutable Size2i max_size; + mutable Size2i old_size = size; mutable Vector<Vector2> mpath; mutable Mode mode = MODE_WINDOWED; mutable bool flags[FLAG_MAX] = {}; @@ -126,6 +127,7 @@ private: bool use_font_oversampling = false; bool transient = false; + bool transient_to_focused = false; bool exclusive = false; bool wrap_controls = false; bool updating_child_controls = false; @@ -300,7 +302,9 @@ public: bool is_maximize_allowed() const; void request_attention(); +#ifndef DISABLE_DEPRECATED void move_to_foreground(); +#endif // DISABLE_DEPRECATED virtual void set_visible(bool p_visible); bool is_visible() const; @@ -313,6 +317,9 @@ public: void set_transient(bool p_transient); bool is_transient() const; + void set_transient_to_focused(bool p_transient_to_focused); + bool is_transient_to_focused() const; + void set_exclusive(bool p_exclusive); bool is_exclusive() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index baaa78f9f2..111d6447a0 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -78,7 +78,6 @@ #include "scene/animation/animation_node_state_machine.h" #include "scene/animation/animation_player.h" #include "scene/animation/animation_tree.h" -#include "scene/animation/root_motion_view.h" #include "scene/animation/tween.h" #include "scene/audio/audio_stream_player.h" #include "scene/debugger/scene_debugger.h" @@ -273,6 +272,7 @@ #include "scene/3d/voxel_gi.h" #include "scene/3d/world_environment.h" #include "scene/3d/xr_nodes.h" +#include "scene/animation/root_motion_view.h" #include "scene/resources/environment.h" #include "scene/resources/fog_material.h" #include "scene/resources/importer_mesh.h" diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 52850cac4a..e503c79bed 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -979,6 +979,7 @@ Animation::TrackType Animation::track_get_type(int p_track) const { void Animation::track_set_path(int p_track, const NodePath &p_path) { ERR_FAIL_INDEX(p_track, tracks.size()); tracks[p_track]->path = p_path; + _track_update_hash(p_track); emit_changed(); } @@ -996,6 +997,27 @@ int Animation::find_track(const NodePath &p_path, const TrackType p_type) const return -1; }; +Animation::TrackType Animation::get_cache_type(TrackType p_type) { + if (p_type == Animation::TYPE_BEZIER) { + return Animation::TYPE_VALUE; + } + if (p_type == Animation::TYPE_ROTATION_3D || p_type == Animation::TYPE_SCALE_3D) { + return Animation::TYPE_POSITION_3D; // Reference them as position3D tracks, even if they modify rotation or scale. + } + return p_type; +} + +void Animation::_track_update_hash(int p_track) { + NodePath track_path = tracks[p_track]->path; + TrackType track_cache_type = get_cache_type(tracks[p_track]->type); + tracks[p_track]->thash = StringName(String(track_path.get_concatenated_names()) + String(track_path.get_concatenated_subnames()) + itos(track_cache_type)).hash(); +} + +Animation::TypeHash Animation::track_get_type_hash(int p_track) const { + ERR_FAIL_INDEX_V(p_track, tracks.size(), 0); + return tracks[p_track]->thash; +} + void Animation::track_set_interpolation_type(int p_track, InterpolationType p_interp) { ERR_FAIL_INDEX(p_track, tracks.size()); tracks[p_track]->interpolation = p_interp; @@ -2394,79 +2416,7 @@ Quaternion Animation::_cubic_interpolate_in_time(const Quaternion &p_pre_a, cons } Variant Animation::_cubic_interpolate_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { - Variant::Type type_a = p_a.get_type(); - Variant::Type type_b = p_b.get_type(); - Variant::Type type_pa = p_pre_a.get_type(); - Variant::Type type_pb = p_post_b.get_type(); - - //make int and real play along - - uint32_t vformat = 1 << type_a; - vformat |= 1 << type_b; - vformat |= 1 << type_pa; - vformat |= 1 << type_pb; - - if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) { - //mix of real and int - real_t a = p_a; - real_t b = p_b; - real_t pa = p_pre_a; - real_t pb = p_post_b; - - return Math::cubic_interpolate_in_time(a, b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t); - } else if ((vformat & (vformat - 1))) { - return p_a; //can't interpolate, mix of types - } - - switch (type_a) { - case Variant::VECTOR2: { - Vector2 a = p_a; - Vector2 b = p_b; - Vector2 pa = p_pre_a; - Vector2 pb = p_post_b; - - return a.cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t); - } - case Variant::RECT2: { - Rect2 a = p_a; - Rect2 b = p_b; - Rect2 pa = p_pre_a; - Rect2 pb = p_post_b; - - return Rect2( - a.position.cubic_interpolate_in_time(b.position, pa.position, pb.position, p_c, p_b_t, p_pre_a_t, p_post_b_t), - a.size.cubic_interpolate_in_time(b.size, pa.size, pb.size, p_c, p_b_t, p_pre_a_t, p_post_b_t)); - } - case Variant::VECTOR3: { - Vector3 a = p_a; - Vector3 b = p_b; - Vector3 pa = p_pre_a; - Vector3 pb = p_post_b; - - return a.cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t); - } - case Variant::QUATERNION: { - Quaternion a = p_a; - Quaternion b = p_b; - Quaternion pa = p_pre_a; - Quaternion pb = p_post_b; - - return a.spherical_cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t); - } - case Variant::AABB: { - AABB a = p_a; - AABB b = p_b; - AABB pa = p_pre_a; - AABB pb = p_post_b; - - return AABB( - a.position.cubic_interpolate_in_time(b.position, pa.position, pb.position, p_c, p_b_t, p_pre_a_t, p_post_b_t), - a.size.cubic_interpolate_in_time(b.size, pa.size, pb.size, p_c, p_b_t, p_pre_a_t, p_post_b_t)); - } - default: { - return _interpolate(p_a, p_b, p_c); - } - } + return cubic_interpolate_in_time_variant(p_pre_a, p_a, p_b, p_post_b, p_c, p_pre_a_t, p_b_t, p_post_b_t); } real_t Animation::_cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { @@ -2489,7 +2439,7 @@ Variant Animation::_cubic_interpolate_angle_in_time(const Variant &p_pre_a, cons real_t pb = p_post_b; return Math::fposmod((float)Math::cubic_interpolate_angle_in_time(a, b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t), (float)Math_TAU); } - return _interpolate(p_a, p_b, p_c); + return _cubic_interpolate_in_time(p_pre_a, p_a, p_b, p_post_b, p_c, p_pre_a_t, p_b_t, p_post_b_t); } template <class T> @@ -5972,8 +5922,7 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float return Variant(); } break; case Variant::FLOAT: { - const double va = a.operator double(); - return va + ((b.operator double()) - va) * c; + return Math::lerp(a.operator double(), b.operator double(), (double)c); } break; case Variant::VECTOR2: { return (a.operator Vector2()).lerp(b.operator Vector2(), c); @@ -5992,7 +5941,7 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float case Variant::PLANE: { const Plane pa = a.operator Plane(); const Plane pb = b.operator Plane(); - return Plane(pa.normal.lerp(pb.normal, c), pa.d + (pb.d - pa.d) * c); + return Plane(pa.normal.lerp(pb.normal, c), Math::lerp((double)pa.d, (double)pb.d, (double)c)); } break; case Variant::COLOR: { return (a.operator Color()).lerp(b.operator Color(), c); @@ -6102,6 +6051,194 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float return c < 0.5 ? a : b; } +Variant Animation::cubic_interpolate_in_time_variant(const Variant &pre_a, const Variant &a, const Variant &b, const Variant &post_b, float c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t, bool p_snap_array_element) { + if (pre_a.get_type() != a.get_type() || pre_a.get_type() != b.get_type() || pre_a.get_type() != post_b.get_type()) { + if (pre_a.is_num() && a.is_num() && b.is_num() && post_b.is_num()) { + return cubic_interpolate_in_time_variant(cast_to_blendwise(pre_a), cast_to_blendwise(a), cast_to_blendwise(b), cast_to_blendwise(post_b), c, p_pre_a_t, p_b_t, p_post_b_t, p_snap_array_element); + } else if (!a.is_array()) { + return a; + } + } + + switch (a.get_type()) { + case Variant::NIL: { + return Variant(); + } break; + case Variant::FLOAT: { + return Math::cubic_interpolate_in_time(a.operator double(), b.operator double(), pre_a.operator double(), post_b.operator double(), (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t); + } break; + case Variant::VECTOR2: { + return (a.operator Vector2()).cubic_interpolate_in_time(b.operator Vector2(), pre_a.operator Vector2(), post_b.operator Vector2(), c, p_b_t, p_pre_a_t, p_post_b_t); + } break; + case Variant::RECT2: { + const Rect2 rpa = pre_a.operator Rect2(); + const Rect2 ra = a.operator Rect2(); + const Rect2 rb = b.operator Rect2(); + const Rect2 rpb = post_b.operator Rect2(); + return Rect2( + ra.position.cubic_interpolate_in_time(rb.position, rpa.position, rpb.position, c, p_b_t, p_pre_a_t, p_post_b_t), + ra.size.cubic_interpolate_in_time(rb.size, rpa.size, rpb.size, c, p_b_t, p_pre_a_t, p_post_b_t)); + } break; + case Variant::VECTOR3: { + return (a.operator Vector3()).cubic_interpolate_in_time(b.operator Vector3(), pre_a.operator Vector3(), post_b.operator Vector3(), c, p_b_t, p_pre_a_t, p_post_b_t); + } break; + case Variant::VECTOR4: { + return (a.operator Vector4()).cubic_interpolate_in_time(b.operator Vector4(), pre_a.operator Vector4(), post_b.operator Vector4(), c, p_b_t, p_pre_a_t, p_post_b_t); + } break; + case Variant::PLANE: { + const Plane ppa = pre_a.operator Plane(); + const Plane pa = a.operator Plane(); + const Plane pb = b.operator Plane(); + const Plane ppb = post_b.operator Plane(); + return Plane( + pa.normal.cubic_interpolate_in_time(pb.normal, ppa.normal, ppb.normal, c, p_b_t, p_pre_a_t, p_post_b_t), + Math::cubic_interpolate_in_time((double)pa.d, (double)pb.d, (double)ppa.d, (double)ppb.d, (double)c, (double)p_b_t, (double)p_pre_a_t, (double)p_post_b_t)); + } break; + case Variant::COLOR: { + const Color cpa = pre_a.operator Color(); + const Color ca = a.operator Color(); + const Color cb = b.operator Color(); + const Color cpb = post_b.operator Color(); + return Color( + Math::cubic_interpolate_in_time((double)ca.r, (double)cb.r, (double)cpa.r, (double)cpb.r, (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t), + Math::cubic_interpolate_in_time((double)ca.g, (double)cb.g, (double)cpa.g, (double)cpb.g, (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t), + Math::cubic_interpolate_in_time((double)ca.b, (double)cb.b, (double)cpa.b, (double)cpb.b, (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t), + Math::cubic_interpolate_in_time((double)ca.a, (double)cb.a, (double)cpa.a, (double)cpb.a, (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t)); + } break; + case Variant::AABB: { + const ::AABB apa = pre_a.operator ::AABB(); + const ::AABB aa = a.operator ::AABB(); + const ::AABB ab = b.operator ::AABB(); + const ::AABB apb = post_b.operator ::AABB(); + return AABB( + aa.position.cubic_interpolate_in_time(ab.position, apa.position, apb.position, c, p_b_t, p_pre_a_t, p_post_b_t), + aa.size.cubic_interpolate_in_time(ab.size, apa.size, apb.size, c, p_b_t, p_pre_a_t, p_post_b_t)); + } break; + case Variant::BASIS: { + const Basis bpa = pre_a.operator Basis(); + const Basis ba = a.operator Basis(); + const Basis bb = b.operator Basis(); + const Basis bpb = post_b.operator Basis(); + return Basis( + ba.rows[0].cubic_interpolate_in_time(bb.rows[0], bpa.rows[0], bpb.rows[0], c, p_pre_a_t, p_b_t, p_post_b_t), + ba.rows[1].cubic_interpolate_in_time(bb.rows[1], bpa.rows[1], bpb.rows[1], c, p_pre_a_t, p_b_t, p_post_b_t), + ba.rows[2].cubic_interpolate_in_time(bb.rows[2], bpa.rows[2], bpb.rows[2], c, p_pre_a_t, p_b_t, p_post_b_t)); + } break; + case Variant::QUATERNION: { + return (a.operator Quaternion()).spherical_cubic_interpolate_in_time(b.operator Quaternion(), pre_a.operator Quaternion(), post_b.operator Quaternion(), c, p_b_t, p_pre_a_t, p_post_b_t); + } break; + case Variant::TRANSFORM2D: { + const Transform2D tpa = pre_a.operator Transform2D(); + const Transform2D ta = a.operator Transform2D(); + const Transform2D tb = b.operator Transform2D(); + const Transform2D tpb = post_b.operator Transform2D(); + // TODO: May cause unintended skew, we needs spherical_cubic_interpolate_in_time() for angle and Transform2D::cubic_interpolate_with(). + return Transform2D( + ta[0].cubic_interpolate_in_time(tb[0], tpa[0], tpb[0], c, p_pre_a_t, p_b_t, p_post_b_t), + ta[1].cubic_interpolate_in_time(tb[1], tpa[1], tpb[1], c, p_pre_a_t, p_b_t, p_post_b_t), + ta[2].cubic_interpolate_in_time(tb[2], tpa[2], tpb[2], c, p_pre_a_t, p_b_t, p_post_b_t)); + } break; + case Variant::TRANSFORM3D: { + const Transform3D tpa = pre_a.operator Transform3D(); + const Transform3D ta = a.operator Transform3D(); + const Transform3D tb = b.operator Transform3D(); + const Transform3D tpb = post_b.operator Transform3D(); + // TODO: May cause unintended skew, we needs Transform3D::cubic_interpolate_with(). + return Transform3D( + ta.basis.rows[0].cubic_interpolate_in_time(tb.basis.rows[0], tpa.basis.rows[0], tpb.basis.rows[0], c, p_pre_a_t, p_b_t, p_post_b_t), + ta.basis.rows[1].cubic_interpolate_in_time(tb.basis.rows[1], tpa.basis.rows[1], tpb.basis.rows[1], c, p_pre_a_t, p_b_t, p_post_b_t), + ta.basis.rows[2].cubic_interpolate_in_time(tb.basis.rows[2], tpa.basis.rows[2], tpb.basis.rows[2], c, p_pre_a_t, p_b_t, p_post_b_t), + ta.origin.cubic_interpolate_in_time(tb.origin, tpa.origin, tpb.origin, c, p_pre_a_t, p_b_t, p_post_b_t)); + } break; + case Variant::BOOL: + case Variant::INT: + case Variant::RECT2I: + case Variant::VECTOR2I: + case Variant::VECTOR3I: + case Variant::VECTOR4I: + case Variant::PACKED_INT32_ARRAY: + case Variant::PACKED_INT64_ARRAY: { + // Fallback the interpolatable value which needs casting. + return cast_from_blendwise(cubic_interpolate_in_time_variant(cast_to_blendwise(pre_a), cast_to_blendwise(a), cast_to_blendwise(b), cast_to_blendwise(post_b), c, p_pre_a_t, p_b_t, p_post_b_t, p_snap_array_element), a.get_type()); + } break; + case Variant::STRING: + case Variant::STRING_NAME: { + // TODO: + // String interpolation works on both the character array size and the character code, to apply cubic interpolation neatly, + // we need to figure out how to interpolate well in cases where there are fewer than 4 keys. So, for now, fallback to linear interpolation. + return interpolate_variant(a, b, c); + } break; + case Variant::PACKED_BYTE_ARRAY: { + // Skip. + } break; + default: { + if (a.is_array()) { + const Array arr_pa = pre_a.operator Array(); + const Array arr_a = a.operator Array(); + const Array arr_b = b.operator Array(); + const Array arr_pb = post_b.operator Array(); + + int min_size = arr_a.size(); + int max_size = arr_b.size(); + bool is_a_larger = inform_variant_array(min_size, max_size); + + Array result; + result.set_typed(MAX(arr_a.get_typed_builtin(), arr_b.get_typed_builtin()), StringName(), Variant()); + result.resize(min_size); + + if (min_size == 0 && max_size == 0) { + return result; + } + + Variant vz; + if (is_a_larger) { + vz = arr_a[0]; + } else { + vz = arr_b[0]; + } + vz.zero(); + Variant pre_last = arr_pa.size() ? arr_pa[arr_pa.size() - 1] : vz; + Variant post_last = arr_pb.size() ? arr_pb[arr_pb.size() - 1] : vz; + + int i = 0; + for (; i < min_size; i++) { + result[i] = cubic_interpolate_in_time_variant(i >= arr_pa.size() ? pre_last : arr_pa[i], arr_a[i], arr_b[i], i >= arr_pb.size() ? post_last : arr_pb[i], c, p_pre_a_t, p_b_t, p_post_b_t); + } + if (min_size != max_size) { + // Process with last element of the lesser array. + // This is pretty funny and bizarre, but artists like to use it for polygon animation. + Variant lesser_last = vz; + if (is_a_larger && !Math::is_equal_approx(c, 1.0f)) { + result.resize(max_size); + if (p_snap_array_element) { + c = 0; + } + if (i > 0) { + lesser_last = arr_b[i - 1]; + } + for (; i < max_size; i++) { + result[i] = cubic_interpolate_in_time_variant(i >= arr_pa.size() ? pre_last : arr_pa[i], arr_a[i], lesser_last, i >= arr_pb.size() ? post_last : arr_pb[i], c, p_pre_a_t, p_b_t, p_post_b_t); + } + } else if (!is_a_larger && !Math::is_zero_approx(c)) { + result.resize(max_size); + if (p_snap_array_element) { + c = 1; + } + if (i > 0) { + lesser_last = arr_a[i - 1]; + } + for (; i < max_size; i++) { + result[i] = cubic_interpolate_in_time_variant(i >= arr_pa.size() ? pre_last : arr_pa[i], lesser_last, arr_b[i], i >= arr_pb.size() ? post_last : arr_pb[i], c, p_pre_a_t, p_b_t, p_post_b_t); + } + } + } + return result; + } + } break; + } + return c < 0.5 ? a : b; +} + bool Animation::inform_variant_array(int &r_min, int &r_max) { if (r_min <= r_max) { return false; diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 2579b6c8ce..6c31bbcd29 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -41,6 +41,8 @@ class Animation : public Resource { RES_BASE_EXTENSION("anim"); public: + typedef uint32_t TypeHash; + enum TrackType { TYPE_VALUE, ///< Set a value in a property, can be interpolated. TYPE_POSITION_3D, ///< Position 3D track @@ -104,7 +106,8 @@ private: TrackType type = TrackType::TYPE_ANIMATION; InterpolationType interpolation = INTERPOLATION_LINEAR; bool loop_wrap = true; - NodePath path; // path to something + NodePath path; // Path to something. + TypeHash thash = 0; // Hash by Path + SubPath + TrackType. bool imported = false; bool enabled = true; Track() {} @@ -268,6 +271,8 @@ private: real_t step = 0.1; LoopMode loop_mode = LOOP_NONE; + void _track_update_hash(int p_track); + /* Animation compression page format (version 1): * * Animation uses bitwidth based compression separated into small pages. The intention is that pages fit easily in the cache, so decoding is cache efficient. @@ -386,6 +391,8 @@ public: NodePath track_get_path(int p_track) const; int find_track(const NodePath &p_path, const TrackType p_type) const; + TypeHash track_get_type_hash(int p_track) const; + void track_move_up(int p_track); void track_move_down(int p_track); void track_move_to(int p_track, int p_to_index); @@ -502,6 +509,9 @@ public: static Variant subtract_variant(const Variant &a, const Variant &b); static Variant blend_variant(const Variant &a, const Variant &b, float c); static Variant interpolate_variant(const Variant &a, const Variant &b, float c, bool p_snap_array_element = false); + static Variant cubic_interpolate_in_time_variant(const Variant &pre_a, const Variant &a, const Variant &b, const Variant &post_b, float c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t, bool p_snap_array_element = false); + + static TrackType get_cache_type(TrackType p_type); Animation(); ~Animation(); diff --git a/scene/resources/animation_library.cpp b/scene/resources/animation_library.cpp index 436bf88ec9..fac72a3150 100644 --- a/scene/resources/animation_library.cpp +++ b/scene/resources/animation_library.cpp @@ -143,6 +143,18 @@ Dictionary AnimationLibrary::_get_data() const { return ret; } +void AnimationLibrary::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + String pf = p_function; + if (p_idx == 0 && (pf == "get_animation" || pf == "has_animation" || pf == "rename_animation" || pf == "remove_animation")) { + List<StringName> names; + get_animation_list(&names); + for (const StringName &E : names) { + r_options->push_back(E.operator String().quote()); + } + } + Resource::get_argument_options(p_function, p_idx, r_options); +} + void AnimationLibrary::_bind_methods() { ClassDB::bind_method(D_METHOD("add_animation", "name", "animation"), &AnimationLibrary::add_animation); ClassDB::bind_method(D_METHOD("remove_animation", "name"), &AnimationLibrary::remove_animation); diff --git a/scene/resources/animation_library.h b/scene/resources/animation_library.h index b2152fd7c5..c1d78068bb 100644 --- a/scene/resources/animation_library.h +++ b/scene/resources/animation_library.h @@ -62,6 +62,8 @@ public: Ref<Animation> get_animation(const StringName &p_name) const; void get_animation_list(List<StringName> *p_animations) const; + virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; + AnimationLibrary(); }; diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index dd20dc1c66..653a4f4949 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -39,7 +39,7 @@ void BitMap::create(const Size2i &p_size) { ERR_FAIL_COND(static_cast<int64_t>(p_size.width) * static_cast<int64_t>(p_size.height) > INT32_MAX); - Error err = bitmask.resize((((p_size.width * p_size.height) - 1) / 8) + 1); + Error err = bitmask.resize(Math::division_round_up(p_size.width * p_size.height, 8)); ERR_FAIL_COND(err != OK); width = p_size.width; diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp index 5363b8ec79..97e3af726a 100644 --- a/scene/resources/bone_map.cpp +++ b/scene/resources/bone_map.cpp @@ -77,22 +77,22 @@ void BoneMap::set_profile(const Ref<SkeletonProfile> &p_profile) { notify_property_list_changed(); } -StringName BoneMap::get_skeleton_bone_name(StringName p_profile_bone_name) const { +StringName BoneMap::get_skeleton_bone_name(const StringName &p_profile_bone_name) const { ERR_FAIL_COND_V(!bone_map.has(p_profile_bone_name), StringName()); return bone_map.get(p_profile_bone_name); } -void BoneMap::_set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name) { +void BoneMap::_set_skeleton_bone_name(const StringName &p_profile_bone_name, const StringName &p_skeleton_bone_name) { ERR_FAIL_COND(!bone_map.has(p_profile_bone_name)); bone_map.insert(p_profile_bone_name, p_skeleton_bone_name); } -void BoneMap::set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name) { +void BoneMap::set_skeleton_bone_name(const StringName &p_profile_bone_name, const StringName &p_skeleton_bone_name) { _set_skeleton_bone_name(p_profile_bone_name, p_skeleton_bone_name); emit_signal("bone_map_updated"); } -StringName BoneMap::find_profile_bone_name(StringName p_skeleton_bone_name) const { +StringName BoneMap::find_profile_bone_name(const StringName &p_skeleton_bone_name) const { StringName profile_bone_name; HashMap<StringName, StringName>::ConstIterator E = bone_map.begin(); while (E) { @@ -105,7 +105,7 @@ StringName BoneMap::find_profile_bone_name(StringName p_skeleton_bone_name) cons return profile_bone_name; } -int BoneMap::get_skeleton_bone_name_count(const StringName p_skeleton_bone_name) const { +int BoneMap::get_skeleton_bone_name_count(const StringName &p_skeleton_bone_name) const { int count = 0; HashMap<StringName, StringName>::ConstIterator E = bone_map.begin(); while (E) { diff --git a/scene/resources/bone_map.h b/scene/resources/bone_map.h index 983a3b7b5a..fbd2f92dee 100644 --- a/scene/resources/bone_map.h +++ b/scene/resources/bone_map.h @@ -53,13 +53,13 @@ public: Ref<SkeletonProfile> get_profile() const; void set_profile(const Ref<SkeletonProfile> &p_profile); - int get_skeleton_bone_name_count(const StringName p_skeleton_bone_name) const; + int get_skeleton_bone_name_count(const StringName &p_skeleton_bone_name) const; - StringName get_skeleton_bone_name(StringName p_profile_bone_name) const; - void set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name); - void _set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name); // Avoid to emit signal for editor. + StringName get_skeleton_bone_name(const StringName &p_profile_bone_name) const; + void set_skeleton_bone_name(const StringName &p_profile_bone_name, const StringName &p_skeleton_bone_name); + void _set_skeleton_bone_name(const StringName &p_profile_bone_name, const StringName &p_skeleton_bone_name); // Avoid to emit signal for editor. - StringName find_profile_bone_name(StringName p_skeleton_bone_name) const; + StringName find_profile_bone_name(const StringName &p_skeleton_bone_name) const; BoneMap(); ~BoneMap(); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index d2aabf7d5c..2b54acef75 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -527,7 +527,7 @@ bool Curve::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { int point_index = components[0].trim_prefix("point_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "position") { Vector2 position = p_value.operator Vector2(); set_point_offset(point_index, position.x); @@ -556,7 +556,7 @@ bool Curve::_get(const StringName &p_name, Variant &r_ret) const { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { int point_index = components[0].trim_prefix("point_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "position") { r_ret = get_point_position(point_index); return true; @@ -977,7 +977,7 @@ Transform2D Curve2D::_sample_posture(Interval p_interval) const { const Vector2 forward = forward_begin.slerp(forward_end, frac).normalized(); const Vector2 side = Vector2(-forward.y, forward.x); - return Transform2D(side, forward, Vector2(0.0, 0.0)); + return Transform2D(forward, side, Vector2(0.0, 0.0)); } Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const { @@ -1046,6 +1046,10 @@ real_t Curve2D::get_bake_interval() const { return bake_interval; } +PackedVector2Array Curve2D::get_points() const { + return _get_data()["points"]; +} + Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const { // Brute force method. @@ -1255,7 +1259,7 @@ bool Curve2D::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { int point_index = components[0].trim_prefix("point_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "position") { set_point_position(point_index, p_value); return true; @@ -1274,7 +1278,7 @@ bool Curve2D::_get(const StringName &p_name, Variant &r_ret) const { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { int point_index = components[0].trim_prefix("point_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "position") { r_ret = get_point_position(point_index); return true; @@ -2220,7 +2224,7 @@ bool Curve3D::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { int point_index = components[0].trim_prefix("point_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "position") { set_point_position(point_index, p_value); return true; @@ -2242,7 +2246,7 @@ bool Curve3D::_get(const StringName &p_name, Variant &r_ret) const { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { int point_index = components[0].trim_prefix("point_").to_int(); - String property = components[1]; + const String &property = components[1]; if (property == "position") { r_ret = get_point_position(point_index); return true; diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 440e4466f5..e085dfedbd 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -237,6 +237,7 @@ public: real_t get_baked_length() const; Vector2 sample_baked(real_t p_offset, bool p_cubic = false) const; Transform2D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false) const; + PackedVector2Array get_points() const; PackedVector2Array get_baked_points() const; //useful for going through Vector2 get_closest_point(const Vector2 &p_to_point) const; real_t get_closest_offset(const Vector2 &p_to_point) const; diff --git a/scene/resources/curve_texture.cpp b/scene/resources/curve_texture.cpp index 3578b46308..488a527bbb 100644 --- a/scene/resources/curve_texture.cpp +++ b/scene/resources/curve_texture.cpp @@ -41,8 +41,6 @@ void CurveTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture_mode", "texture_mode"), &CurveTexture::set_texture_mode); ClassDB::bind_method(D_METHOD("get_texture_mode"), &CurveTexture::get_texture_mode); - ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update); - ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096,suffix:px"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "RGB,Red"), "set_texture_mode", "get_texture_mode"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve"); @@ -190,8 +188,6 @@ void CurveXYZTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_curve_z", "curve"), &CurveXYZTexture::set_curve_z); ClassDB::bind_method(D_METHOD("get_curve_z"), &CurveXYZTexture::get_curve_z); - ClassDB::bind_method(D_METHOD("_update"), &CurveXYZTexture::_update); - ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096,suffix:px"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_x", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_x", "get_curve_x"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_y", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_y", "get_curve_y"); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 13b22ae12c..60c3816020 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -1118,11 +1118,11 @@ bool FontFile::_set(const StringName &p_name, const Variant &p_value) { #endif // DISABLE_DEPRECATED if (tokens.size() == 2 && tokens[0] == "language_support_override") { - String lang_code = tokens[1]; + const String &lang_code = tokens[1]; set_language_support_override(lang_code, p_value); return true; } else if (tokens.size() == 2 && tokens[0] == "script_support_override") { - String script_code = tokens[1]; + const String &script_code = tokens[1]; set_script_support_override(script_code, p_value); return true; } else if (tokens.size() >= 3 && tokens[0] == "cache") { @@ -1209,11 +1209,11 @@ bool FontFile::_set(const StringName &p_name, const Variant &p_value) { bool FontFile::_get(const StringName &p_name, Variant &r_ret) const { Vector<String> tokens = p_name.operator String().split("/"); if (tokens.size() == 2 && tokens[0] == "language_support_override") { - String lang_code = tokens[1]; + const String &lang_code = tokens[1]; r_ret = get_language_support_override(lang_code); return true; } else if (tokens.size() == 2 && tokens[0] == "script_support_override") { - String script_code = tokens[1]; + const String &script_code = tokens[1]; r_ret = get_script_support_override(script_code); return true; } else if (tokens.size() >= 3 && tokens[0] == "cache") { diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 1b74063ff4..74b1157e5f 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -468,7 +468,7 @@ void ShaderMaterial::get_argument_options(const StringName &p_function, int p_id } } } - Resource::get_argument_options(p_function, p_idx, r_options); + Material::get_argument_options(p_function, p_idx, r_options); } bool ShaderMaterial::_can_do_next_pass() const { @@ -1947,7 +1947,7 @@ Ref<Texture2D> BaseMaterial3D::get_texture(TextureParam p_param) const { return textures[p_param]; } -Ref<Texture2D> BaseMaterial3D::get_texture_by_name(StringName p_name) const { +Ref<Texture2D> BaseMaterial3D::get_texture_by_name(const StringName &p_name) const { for (int i = 0; i < (int)BaseMaterial3D::TEXTURE_MAX; i++) { TextureParam param = TextureParam(i); if (p_name == shader_names->texture_names[param]) { diff --git a/scene/resources/material.h b/scene/resources/material.h index 1c698cb104..06522e6470 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -682,7 +682,7 @@ public: void set_texture(TextureParam p_param, const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture(TextureParam p_param) const; // Used only for shader material conversion - Ref<Texture2D> get_texture_by_name(StringName p_name) const; + Ref<Texture2D> get_texture_by_name(const StringName &p_name) const; void set_texture_filter(TextureFilter p_filter); TextureFilter get_texture_filter() const; diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index 82b5c6257c..dd2e7ef268 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -127,7 +127,7 @@ NavigationMesh::SourceGeometryMode NavigationMesh::get_source_geometry_mode() co return source_geometry_mode; } -void NavigationMesh::set_source_group_name(StringName p_group_name) { +void NavigationMesh::set_source_group_name(const StringName &p_group_name) { source_group_name = p_group_name; } diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h index 8b9b810038..cb8880eb94 100644 --- a/scene/resources/navigation_mesh.h +++ b/scene/resources/navigation_mesh.h @@ -122,7 +122,7 @@ public: void set_source_geometry_mode(SourceGeometryMode p_geometry_mode); SourceGeometryMode get_source_geometry_mode() const; - void set_source_group_name(StringName p_group_name); + void set_source_group_name(const StringName &p_group_name); StringName get_source_group_name() const; void set_cell_size(float p_value); diff --git a/scene/resources/navigation_polygon.cpp b/scene/resources/navigation_polygon.cpp index 52840eaa65..2770cb0b87 100644 --- a/scene/resources/navigation_polygon.cpp +++ b/scene/resources/navigation_polygon.cpp @@ -393,7 +393,7 @@ NavigationPolygon::SourceGeometryMode NavigationPolygon::get_source_geometry_mod return source_geometry_mode; } -void NavigationPolygon::set_source_geometry_group_name(StringName p_group_name) { +void NavigationPolygon::set_source_geometry_group_name(const StringName &p_group_name) { source_geometry_group_name = p_group_name; } diff --git a/scene/resources/navigation_polygon.h b/scene/resources/navigation_polygon.h index 4a6a97e2e7..e589ad6dce 100644 --- a/scene/resources/navigation_polygon.h +++ b/scene/resources/navigation_polygon.h @@ -127,7 +127,7 @@ public: void set_source_geometry_mode(SourceGeometryMode p_geometry_mode); SourceGeometryMode get_source_geometry_mode() const; - void set_source_geometry_group_name(StringName p_group_name); + void set_source_geometry_group_name(const StringName &p_group_name); StringName get_source_geometry_group_name() const; void set_agent_radius(real_t p_value); diff --git a/scene/resources/portable_compressed_texture.cpp b/scene/resources/portable_compressed_texture.cpp index a61799c7d6..918b5c0b41 100644 --- a/scene/resources/portable_compressed_texture.cpp +++ b/scene/resources/portable_compressed_texture.cpp @@ -30,6 +30,7 @@ #include "portable_compressed_texture.h" +#include "core/config/project_settings.h" #include "core/io/marshalls.h" #include "scene/resources/bit_map.h" @@ -41,7 +42,8 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { const uint8_t *data = p_data.ptr(); uint32_t data_size = p_data.size(); ERR_FAIL_COND(data_size < 20); - compression_mode = CompressionMode(decode_uint32(data + 0)); + compression_mode = CompressionMode(decode_uint16(data)); + DataFormat data_format = DataFormat(decode_uint16(data + 2)); format = Image::Format(decode_uint32(data + 4)); uint32_t mipmap_count = decode_uint32(data + 8); size.width = decode_uint32(data + 12); @@ -56,6 +58,16 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { switch (compression_mode) { case COMPRESSION_MODE_LOSSLESS: case COMPRESSION_MODE_LOSSY: { + ImageMemLoadFunc loader_func; + if (data_format == DATA_FORMAT_UNDEFINED) { + loader_func = nullptr; + } else if (data_format == DATA_FORMAT_PNG) { + loader_func = Image::_png_mem_unpacker_func; + } else if (data_format == DATA_FORMAT_WEBP) { + loader_func = Image::_webp_mem_loader_func; + } else { + ERR_FAIL(); + } Vector<uint8_t> image_data; ERR_FAIL_COND(data_size < 4); @@ -63,8 +75,10 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { uint32_t mipsize = decode_uint32(data); data += 4; data_size -= 4; - ERR_FAIL_COND(mipsize < data_size); - Ref<Image> img = memnew(Image(data, data_size)); + ERR_FAIL_COND(mipsize > data_size); + Ref<Image> img = loader_func == nullptr + ? memnew(Image(data, data_size)) + : Ref<Image>(loader_func(data, data_size)); ERR_FAIL_COND(img->is_empty()); if (img->get_format() != format) { // May happen due to webp/png in the tiny mipmaps. img->convert(format); @@ -75,7 +89,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { data_size -= mipsize; } - image = Ref<Image>(memnew(Image(size.width, size.height, mipmap_count > 1, format, image_data))); + image = Ref<Image>(memnew(Image(size.width, size.height, mipmaps, format, image_data))); } break; case COMPRESSION_MODE_BASIS_UNIVERSAL: { @@ -86,7 +100,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { case COMPRESSION_MODE_S3TC: case COMPRESSION_MODE_ETC2: case COMPRESSION_MODE_BPTC: { - image = Ref<Image>(memnew(Image(size.width, size.height, mipmap_count > 1, format, p_data.slice(20)))); + image = Ref<Image>(memnew(Image(size.width, size.height, mipmaps, format, p_data.slice(20)))); } break; } ERR_FAIL_COND(image.is_null()); @@ -99,6 +113,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { } image_stored = true; + size_override = size; RenderingServer::get_singleton()->texture_set_size_override(texture, size_override.width, size_override.height); alpha_cache.unref(); @@ -122,7 +137,8 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C Vector<uint8_t> buffer; buffer.resize(20); - encode_uint32(p_compression_mode, buffer.ptrw()); + encode_uint16(p_compression_mode, buffer.ptrw()); + encode_uint16(DATA_FORMAT_UNDEFINED, buffer.ptrw() + 2); encode_uint32(p_image->get_format(), buffer.ptrw() + 4); encode_uint32(p_image->get_mipmap_count() + 1, buffer.ptrw() + 8); encode_uint32(p_image->get_width(), buffer.ptrw() + 12); @@ -131,12 +147,22 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C switch (p_compression_mode) { case COMPRESSION_MODE_LOSSLESS: case COMPRESSION_MODE_LOSSY: { + bool lossless_force_png = GLOBAL_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. for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) { Vector<uint8_t> data; if (p_compression_mode == COMPRESSION_MODE_LOSSY) { data = Image::webp_lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality); + encode_uint16(DATA_FORMAT_WEBP, buffer.ptrw() + 2); } else { - data = Image::webp_lossless_packer(p_image->get_image_from_mipmap(i)); + if (use_webp) { + data = Image::webp_lossless_packer(p_image->get_image_from_mipmap(i)); + encode_uint16(DATA_FORMAT_WEBP, buffer.ptrw() + 2); + } else { + data = Image::png_packer(p_image->get_image_from_mipmap(i)); + encode_uint16(DATA_FORMAT_PNG, buffer.ptrw() + 2); + } } int data_len = data.size(); buffer.resize(buffer.size() + 4); @@ -145,6 +171,7 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C } } break; case COMPRESSION_MODE_BASIS_UNIVERSAL: { + encode_uint16(DATA_FORMAT_BASIS_UNIVERSAL, buffer.ptrw() + 2); Image::UsedChannels uc = p_image->detect_used_channels(p_normal_map ? Image::COMPRESS_SOURCE_NORMAL : Image::COMPRESS_SOURCE_GENERIC); Vector<uint8_t> budata = Image::basis_universal_packer(p_image, uc); buffer.append_array(budata); @@ -153,6 +180,7 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C case COMPRESSION_MODE_S3TC: case COMPRESSION_MODE_ETC2: case COMPRESSION_MODE_BPTC: { + encode_uint16(DATA_FORMAT_IMAGE, buffer.ptrw() + 2); Ref<Image> copy = p_image->duplicate(); switch (p_compression_mode) { case COMPRESSION_MODE_S3TC: diff --git a/scene/resources/portable_compressed_texture.h b/scene/resources/portable_compressed_texture.h index 86d80e39f7..3103c2daba 100644 --- a/scene/resources/portable_compressed_texture.h +++ b/scene/resources/portable_compressed_texture.h @@ -39,6 +39,14 @@ class PortableCompressedTexture2D : public Texture2D { GDCLASS(PortableCompressedTexture2D, Texture2D); public: + enum DataFormat { + DATA_FORMAT_UNDEFINED, + DATA_FORMAT_IMAGE, + DATA_FORMAT_PNG, + DATA_FORMAT_WEBP, + DATA_FORMAT_BASIS_UNIVERSAL, + }; + enum CompressionMode { COMPRESSION_MODE_LOSSLESS, COMPRESSION_MODE_LOSSY, diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 8ad9eec25f..eb28c9e601 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -232,8 +232,6 @@ RID PrimitiveMesh::get_rid() const { } void PrimitiveMesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update"), &PrimitiveMesh::_update); - ClassDB::bind_method(D_METHOD("set_material", "material"), &PrimitiveMesh::set_material); ClassDB::bind_method(D_METHOD("get_material"), &PrimitiveMesh::get_material); @@ -1478,15 +1476,15 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; prevrow = 0; for (j = 0; j <= (subdivide_h + 1); j++) { - float scale = (y - start_pos.y) / size.y; + float scale = j / (subdivide_h + 1.0); float scaled_size_x = size.x * scale; float start_x = start_pos.x + (1.0 - scale) * size.x * left_to_right; float offset_front = (1.0 - scale) * onethird * left_to_right; float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right); float v = j; - float v2 = j / (subdivide_h + 1.0); - v /= (2.0 * (subdivide_h + 1.0)); + float v2 = scale; + v /= 2.0 * (subdivide_h + 1.0); x = 0.0; for (i = 0; i <= (subdivide_w + 1); i++) { @@ -1568,16 +1566,16 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; prevrow = 0; for (j = 0; j <= (subdivide_h + 1); j++) { - float v = j; - float v2 = j / (subdivide_h + 1.0); - v /= (2.0 * (subdivide_h + 1.0)); - float left, right; - float scale = (y - start_pos.y) / size.y; + float scale = j / (subdivide_h + 1.0); left = start_pos.x + (size.x * (1.0 - scale) * left_to_right); right = left + (size.x * scale); + float v = j; + float v2 = scale; + v /= 2.0 * (subdivide_h + 1.0); + z = start_pos.z; for (i = 0; i <= (subdivide_d + 1); i++) { float u = i; @@ -3342,7 +3340,6 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &TextMesh::set_uppercase); ClassDB::bind_method(D_METHOD("is_uppercase"), &TextMesh::is_uppercase); - ClassDB::bind_method(D_METHOD("_font_changed"), &TextMesh::_font_changed); ClassDB::bind_method(D_METHOD("_request_update"), &TextMesh::_request_update); ADD_GROUP("Text", ""); @@ -3446,14 +3443,16 @@ void TextMesh::_font_changed() { void TextMesh::set_font(const Ref<Font> &p_font) { if (font_override != p_font) { + const Callable font_changed = callable_mp(this, &TextMesh::_font_changed); + if (font_override.is_valid()) { - font_override->disconnect_changed(Callable(this, "_font_changed")); + font_override->disconnect_changed(font_changed); } font_override = p_font; dirty_font = true; dirty_cache = true; if (font_override.is_valid()) { - font_override->connect_changed(Callable(this, "_font_changed")); + font_override->connect_changed(font_changed); } _request_update(); } diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 037cd32f10..a97ff5054d 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -281,7 +281,7 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars if (error == ERR_FILE_MISSING_DEPENDENCIES) { // Resource loading error, just skip it. } else if (error != ERR_FILE_EOF) { - _printerr(); + ERR_PRINT(vformat("Parse Error: %s. [Resource file %s:%d]", error_names[error], res_path, lines)); return Ref<PackedScene>(); } else { error = OK; @@ -2289,10 +2289,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso } String connstr = "[connection"; - connstr += " signal=\"" + String(state->get_connection_signal(i)) + "\""; - connstr += " from=\"" + String(state->get_connection_source(i).simplified()) + "\""; - connstr += " to=\"" + String(state->get_connection_target(i).simplified()) + "\""; - connstr += " method=\"" + String(state->get_connection_method(i)) + "\""; + connstr += " signal=\"" + String(state->get_connection_signal(i)).c_escape() + "\""; + connstr += " from=\"" + String(state->get_connection_source(i).simplified()).c_escape() + "\""; + connstr += " to=\"" + String(state->get_connection_target(i).simplified()).c_escape() + "\""; + connstr += " method=\"" + String(state->get_connection_method(i)).c_escape() + "\""; int flags = state->get_connection_flags(i); if (flags != Object::CONNECT_PERSIST) { connstr += " flags=" + itos(flags); @@ -2319,7 +2319,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso if (i == 0) { f->store_line(""); } - f->store_line("[editable path=\"" + editable_instances[i].operator String() + "\"]"); + f->store_line("[editable path=\"" + editable_instances[i].operator String().c_escape() + "\"]"); } } diff --git a/scene/resources/skeleton_profile.cpp b/scene/resources/skeleton_profile.cpp index da4b1f7311..24ed480289 100644 --- a/scene/resources/skeleton_profile.cpp +++ b/scene/resources/skeleton_profile.cpp @@ -180,7 +180,7 @@ StringName SkeletonProfile::get_root_bone() { return root_bone; } -void SkeletonProfile::set_root_bone(StringName p_bone_name) { +void SkeletonProfile::set_root_bone(const StringName &p_bone_name) { if (is_read_only) { return; } @@ -191,7 +191,7 @@ StringName SkeletonProfile::get_scale_base_bone() { return scale_base_bone; } -void SkeletonProfile::set_scale_base_bone(StringName p_bone_name) { +void SkeletonProfile::set_scale_base_bone(const StringName &p_bone_name) { if (is_read_only) { return; } @@ -217,7 +217,7 @@ StringName SkeletonProfile::get_group_name(int p_group_idx) const { return groups[p_group_idx].group_name; } -void SkeletonProfile::set_group_name(int p_group_idx, const StringName p_group_name) { +void SkeletonProfile::set_group_name(int p_group_idx, const StringName &p_group_name) { if (is_read_only) { return; } @@ -254,7 +254,7 @@ void SkeletonProfile::set_bone_size(int p_size) { notify_property_list_changed(); } -int SkeletonProfile::find_bone(StringName p_bone_name) const { +int SkeletonProfile::find_bone(const StringName &p_bone_name) const { if (p_bone_name == StringName()) { return -1; } @@ -271,7 +271,7 @@ StringName SkeletonProfile::get_bone_name(int p_bone_idx) const { return bones[p_bone_idx].bone_name; } -void SkeletonProfile::set_bone_name(int p_bone_idx, const StringName p_bone_name) { +void SkeletonProfile::set_bone_name(int p_bone_idx, const StringName &p_bone_name) { if (is_read_only) { return; } @@ -285,7 +285,7 @@ StringName SkeletonProfile::get_bone_parent(int p_bone_idx) const { return bones[p_bone_idx].bone_parent; } -void SkeletonProfile::set_bone_parent(int p_bone_idx, const StringName p_bone_parent) { +void SkeletonProfile::set_bone_parent(int p_bone_idx, const StringName &p_bone_parent) { if (is_read_only) { return; } @@ -314,7 +314,7 @@ StringName SkeletonProfile::get_bone_tail(int p_bone_idx) const { return bones[p_bone_idx].bone_tail; } -void SkeletonProfile::set_bone_tail(int p_bone_idx, const StringName p_bone_tail) { +void SkeletonProfile::set_bone_tail(int p_bone_idx, const StringName &p_bone_tail) { if (is_read_only) { return; } @@ -356,7 +356,7 @@ StringName SkeletonProfile::get_group(int p_bone_idx) const { return bones[p_bone_idx].group; } -void SkeletonProfile::set_group(int p_bone_idx, const StringName p_group) { +void SkeletonProfile::set_group(int p_bone_idx, const StringName &p_group) { if (is_read_only) { return; } @@ -379,7 +379,7 @@ void SkeletonProfile::set_require(int p_bone_idx, const bool p_require) { emit_signal("profile_updated"); } -bool SkeletonProfile::has_bone(StringName p_bone_name) { +bool SkeletonProfile::has_bone(const StringName &p_bone_name) { bool is_found = false; for (int i = 0; i < bones.size(); i++) { if (bones[i].bone_name == p_bone_name) { diff --git a/scene/resources/skeleton_profile.h b/scene/resources/skeleton_profile.h index 418a051976..143f495c61 100644 --- a/scene/resources/skeleton_profile.h +++ b/scene/resources/skeleton_profile.h @@ -78,16 +78,16 @@ protected: public: StringName get_root_bone(); - void set_root_bone(StringName p_bone_name); + void set_root_bone(const StringName &p_bone_name); StringName get_scale_base_bone(); - void set_scale_base_bone(StringName p_bone_name); + void set_scale_base_bone(const StringName &p_bone_name); int get_group_size(); void set_group_size(int p_size); StringName get_group_name(int p_group_idx) const; - void set_group_name(int p_group_idx, const StringName p_group_name); + void set_group_name(int p_group_idx, const StringName &p_group_name); Ref<Texture2D> get_texture(int p_group_idx) const; void set_texture(int p_group_idx, const Ref<Texture2D> &p_texture); @@ -95,19 +95,19 @@ public: int get_bone_size(); void set_bone_size(int p_size); - int find_bone(const StringName p_bone_name) const; + int find_bone(const StringName &p_bone_name) const; StringName get_bone_name(int p_bone_idx) const; - void set_bone_name(int p_bone_idx, const StringName p_bone_name); + void set_bone_name(int p_bone_idx, const StringName &p_bone_name); StringName get_bone_parent(int p_bone_idx) const; - void set_bone_parent(int p_bone_idx, const StringName p_bone_parent); + void set_bone_parent(int p_bone_idx, const StringName &p_bone_parent); TailDirection get_tail_direction(int p_bone_idx) const; void set_tail_direction(int p_bone_idx, const TailDirection p_tail_direction); StringName get_bone_tail(int p_bone_idx) const; - void set_bone_tail(int p_bone_idx, const StringName p_bone_tail); + void set_bone_tail(int p_bone_idx, const StringName &p_bone_tail); Transform3D get_reference_pose(int p_bone_idx) const; void set_reference_pose(int p_bone_idx, const Transform3D p_reference_pose); @@ -116,12 +116,12 @@ public: void set_handle_offset(int p_bone_idx, const Vector2 p_handle_offset); StringName get_group(int p_bone_idx) const; - void set_group(int p_bone_idx, const StringName p_group); + void set_group(int p_bone_idx, const StringName &p_group); bool is_require(int p_bone_idx) const; void set_require(int p_bone_idx, const bool p_require); - bool has_bone(StringName p_bone_name); + bool has_bone(const StringName &p_bone_name); SkeletonProfile(); ~SkeletonProfile(); diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp index 17aaf579dd..fc8bff1f25 100644 --- a/scene/resources/sprite_frames.cpp +++ b/scene/resources/sprite_frames.cpp @@ -224,6 +224,23 @@ void SpriteFrames::_set_animations(const Array &p_animations) { } } +void SpriteFrames::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + String pf = p_function; + if (p_idx == 0) { + if (pf == "has_animation" || pf == "remove_animation" || pf == "rename_animation" || + pf == "set_animation_speed" || pf == "get_animation_speed" || + pf == "set_animation_loop" || pf == "get_animation_loop" || + pf == "add_frame" || pf == "set_frame" || pf == "remove_frame" || + pf == "get_frame_count" || pf == "get_frame_texture" || pf == "get_frame_duration" || + pf == "clear") { + for (const String &E : get_animation_names()) { + r_options->push_back(E.quote()); + } + } + } + Resource::get_argument_options(p_function, p_idx, r_options); +} + void SpriteFrames::_bind_methods() { ClassDB::bind_method(D_METHOD("add_animation", "anim"), &SpriteFrames::add_animation); ClassDB::bind_method(D_METHOD("has_animation", "anim"), &SpriteFrames::has_animation); diff --git a/scene/resources/sprite_frames.h b/scene/resources/sprite_frames.h index 6de2b4a37b..dc980f8321 100644 --- a/scene/resources/sprite_frames.h +++ b/scene/resources/sprite_frames.h @@ -103,6 +103,8 @@ public: void clear(const StringName &p_anim); void clear_all(); + virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; + SpriteFrames(); }; diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index d57a0f6b38..b6cd6f6dfe 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -322,7 +322,7 @@ void Theme::clear_icon(const StringName &p_name, const StringName &p_theme_type) _emit_theme_changed(true); } -void Theme::get_icon_list(StringName p_theme_type, List<StringName> *p_list) const { +void Theme::get_icon_list(const StringName &p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); if (!icon_map.has(p_theme_type)) { @@ -432,7 +432,7 @@ void Theme::clear_stylebox(const StringName &p_name, const StringName &p_theme_t _emit_theme_changed(true); } -void Theme::get_stylebox_list(StringName p_theme_type, List<StringName> *p_list) const { +void Theme::get_stylebox_list(const StringName &p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); if (!style_map.has(p_theme_type)) { @@ -544,7 +544,7 @@ void Theme::clear_font(const StringName &p_name, const StringName &p_theme_type) _emit_theme_changed(true); } -void Theme::get_font_list(StringName p_theme_type, List<StringName> *p_list) const { +void Theme::get_font_list(const StringName &p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); if (!font_map.has(p_theme_type)) { @@ -643,7 +643,7 @@ void Theme::clear_font_size(const StringName &p_name, const StringName &p_theme_ _emit_theme_changed(true); } -void Theme::get_font_size_list(StringName p_theme_type, List<StringName> *p_list) const { +void Theme::get_font_size_list(const StringName &p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); if (!font_size_map.has(p_theme_type)) { @@ -729,7 +729,7 @@ void Theme::clear_color(const StringName &p_name, const StringName &p_theme_type _emit_theme_changed(true); } -void Theme::get_color_list(StringName p_theme_type, List<StringName> *p_list) const { +void Theme::get_color_list(const StringName &p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); if (!color_map.has(p_theme_type)) { @@ -815,7 +815,7 @@ void Theme::clear_constant(const StringName &p_name, const StringName &p_theme_t _emit_theme_changed(true); } -void Theme::get_constant_list(StringName p_theme_type, List<StringName> *p_list) const { +void Theme::get_constant_list(const StringName &p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); if (!constant_map.has(p_theme_type)) { @@ -1009,7 +1009,7 @@ void Theme::clear_theme_item(DataType p_data_type, const StringName &p_name, con } } -void Theme::get_theme_item_list(DataType p_data_type, StringName p_theme_type, List<StringName> *p_list) const { +void Theme::get_theme_item_list(DataType p_data_type, const StringName &p_theme_type, List<StringName> *p_list) const { switch (p_data_type) { case DATA_TYPE_COLOR: get_color_list(p_theme_type, p_list); @@ -1613,6 +1613,17 @@ void Theme::merge_with(const Ref<Theme> &p_other) { } } + // Defaults. + if (p_other->has_default_font()) { + set_default_font(p_other->default_font); + } + if (p_other->has_default_font_size()) { + set_default_font_size(p_other->default_font_size); + } + if (p_other->has_default_base_scale()) { + set_default_base_scale(p_other->default_base_scale); + } + _unfreeze_and_propagate_changes(); } diff --git a/scene/resources/theme.h b/scene/resources/theme.h index b26b5b5e84..73f1167c29 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -136,7 +136,7 @@ public: bool has_icon_nocheck(const StringName &p_name, const StringName &p_theme_type) const; void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); void clear_icon(const StringName &p_name, const StringName &p_theme_type); - void get_icon_list(StringName p_theme_type, List<StringName> *p_list) const; + void get_icon_list(const StringName &p_theme_type, List<StringName> *p_list) const; void add_icon_type(const StringName &p_theme_type); void remove_icon_type(const StringName &p_theme_type); void get_icon_type_list(List<StringName> *p_list) const; @@ -147,7 +147,7 @@ public: bool has_stylebox_nocheck(const StringName &p_name, const StringName &p_theme_type) const; void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); void clear_stylebox(const StringName &p_name, const StringName &p_theme_type); - void get_stylebox_list(StringName p_theme_type, List<StringName> *p_list) const; + void get_stylebox_list(const StringName &p_theme_type, List<StringName> *p_list) const; void add_stylebox_type(const StringName &p_theme_type); void remove_stylebox_type(const StringName &p_theme_type); void get_stylebox_type_list(List<StringName> *p_list) const; @@ -158,7 +158,7 @@ public: bool has_font_nocheck(const StringName &p_name, const StringName &p_theme_type) const; void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); void clear_font(const StringName &p_name, const StringName &p_theme_type); - void get_font_list(StringName p_theme_type, List<StringName> *p_list) const; + void get_font_list(const StringName &p_theme_type, List<StringName> *p_list) const; void add_font_type(const StringName &p_theme_type); void remove_font_type(const StringName &p_theme_type); void get_font_type_list(List<StringName> *p_list) const; @@ -169,7 +169,7 @@ public: bool has_font_size_nocheck(const StringName &p_name, const StringName &p_theme_type) const; void rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); void clear_font_size(const StringName &p_name, const StringName &p_theme_type); - void get_font_size_list(StringName p_theme_type, List<StringName> *p_list) const; + void get_font_size_list(const StringName &p_theme_type, List<StringName> *p_list) const; void add_font_size_type(const StringName &p_theme_type); void remove_font_size_type(const StringName &p_theme_type); void get_font_size_type_list(List<StringName> *p_list) const; @@ -180,7 +180,7 @@ public: bool has_color_nocheck(const StringName &p_name, const StringName &p_theme_type) const; void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); void clear_color(const StringName &p_name, const StringName &p_theme_type); - void get_color_list(StringName p_theme_type, List<StringName> *p_list) const; + void get_color_list(const StringName &p_theme_type, List<StringName> *p_list) const; void add_color_type(const StringName &p_theme_type); void remove_color_type(const StringName &p_theme_type); void get_color_type_list(List<StringName> *p_list) const; @@ -191,7 +191,7 @@ public: bool has_constant_nocheck(const StringName &p_name, const StringName &p_theme_type) const; void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); void clear_constant(const StringName &p_name, const StringName &p_theme_type); - void get_constant_list(StringName p_theme_type, List<StringName> *p_list) const; + void get_constant_list(const StringName &p_theme_type, List<StringName> *p_list) const; void add_constant_type(const StringName &p_theme_type); void remove_constant_type(const StringName &p_theme_type); void get_constant_type_list(List<StringName> *p_list) const; @@ -202,7 +202,7 @@ public: bool has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const; void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type); - void get_theme_item_list(DataType p_data_type, StringName p_theme_type, List<StringName> *p_list) const; + void get_theme_item_list(DataType p_data_type, const StringName &p_theme_type, List<StringName> *p_list) const; void add_theme_item_type(DataType p_data_type, const StringName &p_theme_type); void remove_theme_item_type(DataType p_data_type, const StringName &p_theme_type); void get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 2de7cce5c7..66e1b7bcf9 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -1563,6 +1563,632 @@ void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform } } +Vector2 TileSet::map_to_local(const Vector2i &p_pos) const { + // SHOULD RETURN THE CENTER OF THE CELL. + Vector2 ret = p_pos; + + if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap. + // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap. + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + switch (tile_layout) { + case TileSet::TILE_LAYOUT_STACKED: + ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 0 ? 0.0 : 0.5), ret.y); + break; + case TileSet::TILE_LAYOUT_STACKED_OFFSET: + ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 1 ? 0.0 : 0.5), ret.y); + break; + case TileSet::TILE_LAYOUT_STAIRS_RIGHT: + ret = Vector2(ret.x + ret.y / 2, ret.y); + break; + case TileSet::TILE_LAYOUT_STAIRS_DOWN: + ret = Vector2(ret.x / 2, ret.y * 2 + ret.x); + break; + case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: + ret = Vector2((ret.x + ret.y) / 2, ret.y - ret.x); + break; + case TileSet::TILE_LAYOUT_DIAMOND_DOWN: + ret = Vector2((ret.x - ret.y) / 2, ret.y + ret.x); + break; + } + } else { // TILE_OFFSET_AXIS_VERTICAL. + switch (tile_layout) { + case TileSet::TILE_LAYOUT_STACKED: + ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 0 ? 0.0 : 0.5)); + break; + case TileSet::TILE_LAYOUT_STACKED_OFFSET: + ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 1 ? 0.0 : 0.5)); + break; + case TileSet::TILE_LAYOUT_STAIRS_RIGHT: + ret = Vector2(ret.x * 2 + ret.y, ret.y / 2); + break; + case TileSet::TILE_LAYOUT_STAIRS_DOWN: + ret = Vector2(ret.x, ret.y + ret.x / 2); + break; + case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: + ret = Vector2(ret.x + ret.y, (ret.y - ret.x) / 2); + break; + case TileSet::TILE_LAYOUT_DIAMOND_DOWN: + ret = Vector2(ret.x - ret.y, (ret.y + ret.x) / 2); + break; + } + } + } + + // Multiply by the overlapping ratio. + double overlapping_ratio = 1.0; + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + overlapping_ratio = 0.5; + } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) { + overlapping_ratio = 0.75; + } + ret.y *= overlapping_ratio; + } else { // TILE_OFFSET_AXIS_VERTICAL. + if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + overlapping_ratio = 0.5; + } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) { + overlapping_ratio = 0.75; + } + ret.x *= overlapping_ratio; + } + + return (ret + Vector2(0.5, 0.5)) * tile_size; +} + +Vector2i TileSet::local_to_map(const Vector2 &p_local_position) const { + Vector2 ret = p_local_position; + ret /= tile_size; + + // Divide by the overlapping ratio. + double overlapping_ratio = 1.0; + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + overlapping_ratio = 0.5; + } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) { + overlapping_ratio = 0.75; + } + ret.y /= overlapping_ratio; + } else { // TILE_OFFSET_AXIS_VERTICAL. + if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + overlapping_ratio = 0.5; + } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) { + overlapping_ratio = 0.75; + } + ret.x /= overlapping_ratio; + } + + // For each half-offset shape, we check if we are in the corner of the tile, and thus should correct the local position accordingly. + if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap. + // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap. + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + // Smart floor of the position + Vector2 raw_pos = ret; + if (Math::posmod(Math::floor(ret.y), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) { + ret = Vector2(Math::floor(ret.x + 0.5) - 0.5, Math::floor(ret.y)); + } else { + ret = ret.floor(); + } + + // Compute the tile offset, and if we might the output for a neighbor top tile. + Vector2 in_tile_pos = raw_pos - ret; + bool in_top_left_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(-0.5, 1.0 / overlapping_ratio - 1)) <= 0; + bool in_top_right_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(0.5, 1.0 / overlapping_ratio - 1)) > 0; + + switch (tile_layout) { + case TileSet::TILE_LAYOUT_STACKED: + ret = ret.floor(); + if (in_top_left_triangle) { + ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : -1, -1); + } else if (in_top_right_triangle) { + ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 1 : 0, -1); + } + break; + case TileSet::TILE_LAYOUT_STACKED_OFFSET: + ret = ret.floor(); + if (in_top_left_triangle) { + ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? -1 : 0, -1); + } else if (in_top_right_triangle) { + ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : 1, -1); + } + break; + case TileSet::TILE_LAYOUT_STAIRS_RIGHT: + ret = Vector2(ret.x - ret.y / 2, ret.y).floor(); + if (in_top_left_triangle) { + ret += Vector2i(0, -1); + } else if (in_top_right_triangle) { + ret += Vector2i(1, -1); + } + break; + case TileSet::TILE_LAYOUT_STAIRS_DOWN: + ret = Vector2(ret.x * 2, ret.y / 2 - ret.x).floor(); + if (in_top_left_triangle) { + ret += Vector2i(-1, 0); + } else if (in_top_right_triangle) { + ret += Vector2i(1, -1); + } + break; + case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: + ret = Vector2(ret.x - ret.y / 2, ret.y / 2 + ret.x).floor(); + if (in_top_left_triangle) { + ret += Vector2i(0, -1); + } else if (in_top_right_triangle) { + ret += Vector2i(1, 0); + } + break; + case TileSet::TILE_LAYOUT_DIAMOND_DOWN: + ret = Vector2(ret.x + ret.y / 2, ret.y / 2 - ret.x).floor(); + if (in_top_left_triangle) { + ret += Vector2i(-1, 0); + } else if (in_top_right_triangle) { + ret += Vector2i(0, -1); + } + break; + } + } else { // TILE_OFFSET_AXIS_VERTICAL. + // Smart floor of the position. + Vector2 raw_pos = ret; + if (Math::posmod(Math::floor(ret.x), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) { + ret = Vector2(Math::floor(ret.x), Math::floor(ret.y + 0.5) - 0.5); + } else { + ret = ret.floor(); + } + + // Compute the tile offset, and if we might the output for a neighbor top tile. + Vector2 in_tile_pos = raw_pos - ret; + bool in_top_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, -0.5)) > 0; + bool in_bottom_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, 0.5)) <= 0; + + switch (tile_layout) { + case TileSet::TILE_LAYOUT_STACKED: + ret = ret.floor(); + if (in_top_left_triangle) { + ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : -1); + } else if (in_bottom_left_triangle) { + ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 1 : 0); + } + break; + case TileSet::TILE_LAYOUT_STACKED_OFFSET: + ret = ret.floor(); + if (in_top_left_triangle) { + ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? -1 : 0); + } else if (in_bottom_left_triangle) { + ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : 1); + } + break; + case TileSet::TILE_LAYOUT_STAIRS_RIGHT: + ret = Vector2(ret.x / 2 - ret.y, ret.y * 2).floor(); + if (in_top_left_triangle) { + ret += Vector2i(0, -1); + } else if (in_bottom_left_triangle) { + ret += Vector2i(-1, 1); + } + break; + case TileSet::TILE_LAYOUT_STAIRS_DOWN: + ret = Vector2(ret.x, ret.y - ret.x / 2).floor(); + if (in_top_left_triangle) { + ret += Vector2i(-1, 0); + } else if (in_bottom_left_triangle) { + ret += Vector2i(-1, 1); + } + break; + case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: + ret = Vector2(ret.x / 2 - ret.y, ret.y + ret.x / 2).floor(); + if (in_top_left_triangle) { + ret += Vector2i(0, -1); + } else if (in_bottom_left_triangle) { + ret += Vector2i(-1, 0); + } + break; + case TileSet::TILE_LAYOUT_DIAMOND_DOWN: + ret = Vector2(ret.x / 2 + ret.y, ret.y - ret.x / 2).floor(); + if (in_top_left_triangle) { + ret += Vector2i(-1, 0); + } else if (in_bottom_left_triangle) { + ret += Vector2i(0, 1); + } + break; + } + } + } else { + ret = (ret + Vector2(0.00005, 0.00005)).floor(); + } + return Vector2i(ret); +} + +bool TileSet::is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const { + if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { + return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER; + + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; + } else { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; + } else { + return p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE || + p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE; + } + } +} + +Vector2i TileSet::get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const { + if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { + switch (p_cell_neighbor) { + case TileSet::CELL_NEIGHBOR_RIGHT_SIDE: + return p_coords + Vector2i(1, 0); + case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: + return p_coords + Vector2i(1, 1); + case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE: + return p_coords + Vector2i(0, 1); + case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER: + return p_coords + Vector2i(-1, 1); + case TileSet::CELL_NEIGHBOR_LEFT_SIDE: + return p_coords + Vector2i(-1, 0); + case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER: + return p_coords + Vector2i(-1, -1); + case TileSet::CELL_NEIGHBOR_TOP_SIDE: + return p_coords + Vector2i(0, -1); + case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER: + return p_coords + Vector2i(1, -1); + default: + ERR_FAIL_V(p_coords); + } + } else { // Half-offset shapes (square and hexagon). + switch (tile_layout) { + case TileSet::TILE_LAYOUT_STACKED: { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + bool is_offset = p_coords.y % 2; + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { + return p_coords + Vector2i(1, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(is_offset ? 1 : 0, 1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { + return p_coords + Vector2i(0, 2); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(is_offset ? 0 : -1, 1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { + return p_coords + Vector2i(-1, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(is_offset ? 0 : -1, -1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { + return p_coords + Vector2i(0, -2); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(is_offset ? 1 : 0, -1); + } else { + ERR_FAIL_V(p_coords); + } + } else { + bool is_offset = p_coords.x % 2; + + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { + return p_coords + Vector2i(0, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(1, is_offset ? 1 : 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { + return p_coords + Vector2i(2, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(1, is_offset ? 0 : -1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { + return p_coords + Vector2i(0, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(-1, is_offset ? 0 : -1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { + return p_coords + Vector2i(-2, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(-1, is_offset ? 1 : 0); + } else { + ERR_FAIL_V(p_coords); + } + } + } break; + case TileSet::TILE_LAYOUT_STACKED_OFFSET: { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + bool is_offset = p_coords.y % 2; + + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { + return p_coords + Vector2i(1, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(is_offset ? 0 : 1, 1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { + return p_coords + Vector2i(0, 2); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(is_offset ? -1 : 0, 1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { + return p_coords + Vector2i(-1, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(is_offset ? -1 : 0, -1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { + return p_coords + Vector2i(0, -2); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(is_offset ? 0 : 1, -1); + } else { + ERR_FAIL_V(p_coords); + } + } else { + bool is_offset = p_coords.x % 2; + + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { + return p_coords + Vector2i(0, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(1, is_offset ? 0 : 1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { + return p_coords + Vector2i(2, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(1, is_offset ? -1 : 0); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { + return p_coords + Vector2i(0, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(-1, is_offset ? -1 : 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { + return p_coords + Vector2i(-2, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(-1, is_offset ? 0 : 1); + } else { + ERR_FAIL_V(p_coords); + } + } + } break; + case TileSet::TILE_LAYOUT_STAIRS_RIGHT: + case TileSet::TILE_LAYOUT_STAIRS_DOWN: { + if ((tile_layout == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { + return p_coords + Vector2i(1, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(0, 1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { + return p_coords + Vector2i(-1, 2); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(-1, 1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { + return p_coords + Vector2i(-1, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(0, -1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { + return p_coords + Vector2i(1, -2); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(1, -1); + } else { + ERR_FAIL_V(p_coords); + } + + } else { + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { + return p_coords + Vector2i(0, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(1, 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { + return p_coords + Vector2i(2, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(1, -1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { + return p_coords + Vector2i(0, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(-1, 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { + return p_coords + Vector2i(-2, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(-1, 1); + } else { + ERR_FAIL_V(p_coords); + } + } + } else { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { + return p_coords + Vector2i(2, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(1, 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { + return p_coords + Vector2i(0, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(-1, 1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { + return p_coords + Vector2i(-2, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(-1, 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { + return p_coords + Vector2i(0, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(1, -1); + } else { + ERR_FAIL_V(p_coords); + } + + } else { + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { + return p_coords + Vector2i(-1, 2); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(0, 1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { + return p_coords + Vector2i(1, 0); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(1, -1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { + return p_coords + Vector2i(1, -2); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(0, -1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { + return p_coords + Vector2i(-1, 0); + + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(-1, 1); + } else { + ERR_FAIL_V(p_coords); + } + } + } + } break; + case TileSet::TILE_LAYOUT_DIAMOND_RIGHT: + case TileSet::TILE_LAYOUT_DIAMOND_DOWN: { + if ((tile_layout == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { + return p_coords + Vector2i(1, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(0, 1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { + return p_coords + Vector2i(-1, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(-1, 0); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { + return p_coords + Vector2i(-1, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(0, -1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { + return p_coords + Vector2i(1, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(1, 0); + } else { + ERR_FAIL_V(p_coords); + } + + } else { + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { + return p_coords + Vector2i(1, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(1, 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { + return p_coords + Vector2i(1, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(0, -1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { + return p_coords + Vector2i(-1, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(-1, 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { + return p_coords + Vector2i(-1, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(0, 1); + } else { + ERR_FAIL_V(p_coords); + } + } + } else { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) { + return p_coords + Vector2i(1, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(1, 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) { + return p_coords + Vector2i(1, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(0, 1); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) { + return p_coords + Vector2i(-1, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(-1, 0); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) { + return p_coords + Vector2i(-1, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(0, -1); + } else { + ERR_FAIL_V(p_coords); + } + + } else { + if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) { + return p_coords + Vector2i(-1, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) { + return p_coords + Vector2i(0, 1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) { + return p_coords + Vector2i(1, 1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) { + return p_coords + Vector2i(1, 0); + } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) || + (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) { + return p_coords + Vector2i(1, -1); + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) { + return p_coords + Vector2i(0, -1); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) { + return p_coords + Vector2i(-1, -1); + + } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) { + return p_coords + Vector2i(-1, 0); + } else { + ERR_FAIL_V(p_coords); + } + } + } + } break; + default: + ERR_FAIL_V(p_coords); + } + } +} + +Vector2i TileSet::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) { + ERR_FAIL_COND_V(p_pattern.is_null(), Vector2i()); + ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i()); + + Vector2i output = p_position_in_tilemap + p_coords_in_pattern; + if (tile_shape != TileSet::TILE_SHAPE_SQUARE) { + if (tile_layout == TileSet::TILE_LAYOUT_STACKED) { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) { + output.x += 1; + } else if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) { + output.y += 1; + } + } else if (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET) { + if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) { + output.x -= 1; + } else if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) { + output.y -= 1; + } + } + } + + return output; +} + Vector<Point2> TileSet::get_terrain_polygon(int p_terrain_set) { if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { return _get_square_terrain_polygon(tile_size); @@ -4675,7 +5301,6 @@ void TileSetAtlasSource::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tile_texture_region", "atlas_coords", "frame"), &TileSetAtlasSource::get_tile_texture_region, DEFVAL(0)); // Getters for texture and tile region (padded or not) - ClassDB::bind_method(D_METHOD("_update_padded_texture"), &TileSetAtlasSource::_update_padded_texture); ClassDB::bind_method(D_METHOD("get_runtime_texture"), &TileSetAtlasSource::get_runtime_texture); ClassDB::bind_method(D_METHOD("get_runtime_tile_texture_region", "atlas_coords", "frame"), &TileSetAtlasSource::get_runtime_tile_texture_region); @@ -4761,7 +5386,7 @@ void TileSetAtlasSource::_create_coords_mapping_cache(Vector2i p_atlas_coords) { void TileSetAtlasSource::_queue_update_padded_texture() { padded_texture_needs_update = true; - call_deferred(SNAME("_update_padded_texture")); + callable_mp(this, &TileSetAtlasSource::_update_padded_texture).call_deferred(); } Ref<ImageTexture> TileSetAtlasSource::_create_padded_image_texture(const Ref<Texture2D> &p_source) { diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index a71982cd56..0a6d879047 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -530,6 +530,13 @@ public: Vector<Vector2> get_tile_shape_polygon(); void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>()); + // Used by TileMap/TileMapLayer + Vector2 map_to_local(const Vector2i &p_pos) const; + Vector2i local_to_map(const Vector2 &p_pos) const; + bool is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const; + Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const; + Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern); + Vector<Point2> get_terrain_polygon(int p_terrain_set); Vector<Point2> get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit); void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, const TileData *p_tile_data); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 9fb6b364a7..8ff5b54fbe 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -3139,7 +3139,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "UV" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, @@ -3166,7 +3166,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec3(1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Canvas Item, Light @@ -3176,7 +3176,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Particles @@ -3189,7 +3189,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { // Sky - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "UV" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Fog diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp index 09fb5aba0d..005a88d391 100644 --- a/scene/theme/default_theme.cpp +++ b/scene/theme/default_theme.cpp @@ -78,7 +78,7 @@ static Ref<StyleBoxFlat> sb_expand(Ref<StyleBoxFlat> p_sbox, float p_left, float return p_sbox; } -// See also `editor_generate_icon()` in `editor/editor_themes.cpp`. +// See also `editor_generate_icon()` in `editor/themes/editor_icons.cpp`. static Ref<ImageTexture> generate_icon(int p_index) { Ref<Image> img = memnew(Image); @@ -299,13 +299,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("focus", "CheckBox", cbx_focus); theme->set_icon("checked", "CheckBox", icons["checked"]); - theme->set_icon("checked_disabled", "CheckBox", icons["checked"]); + theme->set_icon("checked_disabled", "CheckBox", icons["checked_disabled"]); theme->set_icon("unchecked", "CheckBox", icons["unchecked"]); - theme->set_icon("unchecked_disabled", "CheckBox", icons["unchecked"]); + theme->set_icon("unchecked_disabled", "CheckBox", icons["unchecked_disabled"]); theme->set_icon("radio_checked", "CheckBox", icons["radio_checked"]); - theme->set_icon("radio_checked_disabled", "CheckBox", icons["radio_checked"]); + theme->set_icon("radio_checked_disabled", "CheckBox", icons["radio_checked_disabled"]); theme->set_icon("radio_unchecked", "CheckBox", icons["radio_unchecked"]); - theme->set_icon("radio_unchecked_disabled", "CheckBox", icons["radio_unchecked"]); + theme->set_icon("radio_unchecked_disabled", "CheckBox", icons["radio_unchecked_disabled"]); theme->set_font("font", "CheckBox", Ref<Font>()); theme->set_font_size("font_size", "CheckBox", -1); @@ -685,13 +685,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("labeled_separator_right", "PopupMenu", separator_horizontal); theme->set_icon("checked", "PopupMenu", icons["checked"]); - theme->set_icon("checked_disabled", "PopupMenu", icons["checked"]); + theme->set_icon("checked_disabled", "PopupMenu", icons["checked_disabled"]); theme->set_icon("unchecked", "PopupMenu", icons["unchecked"]); - theme->set_icon("unchecked_disabled", "PopupMenu", icons["unchecked"]); + theme->set_icon("unchecked_disabled", "PopupMenu", icons["unchecked_disabled"]); theme->set_icon("radio_checked", "PopupMenu", icons["radio_checked"]); - theme->set_icon("radio_checked_disabled", "PopupMenu", icons["radio_checked"]); + theme->set_icon("radio_checked_disabled", "PopupMenu", icons["radio_checked_disabled"]); theme->set_icon("radio_unchecked", "PopupMenu", icons["radio_unchecked"]); - theme->set_icon("radio_unchecked_disabled", "PopupMenu", icons["radio_unchecked"]); + theme->set_icon("radio_unchecked_disabled", "PopupMenu", icons["radio_unchecked_disabled"]); theme->set_icon("submenu", "PopupMenu", icons["popup_menu_arrow_right"]); theme->set_icon("submenu_mirrored", "PopupMenu", icons["popup_menu_arrow_left"]); @@ -958,6 +958,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("shape_rect_wheel", "ColorPicker", icons["picker_shape_rectangle_wheel"]); theme->set_icon("add_preset", "ColorPicker", icons["add"]); theme->set_icon("sample_bg", "ColorPicker", icons["mini_checkerboard"]); + theme->set_icon("sample_revert", "ColorPicker", icons["reload"]); theme->set_icon("overbright_indicator", "ColorPicker", icons["color_picker_overbright"]); theme->set_icon("bar_arrow", "ColorPicker", icons["color_picker_bar_arrow"]); theme->set_icon("picker_cursor", "ColorPicker", icons["color_picker_cursor"]); diff --git a/scene/theme/default_theme_builders.py b/scene/theme/default_theme_builders.py index 0455d6d246..b8bb579d1c 100644 --- a/scene/theme/default_theme_builders.py +++ b/scene/theme/default_theme_builders.py @@ -1,8 +1,10 @@ -"""Functions used to generate source files during build time +""" +Functions used to generate source files during build time All such functions are invoked in a subprocess on Windows to prevent build flakiness. """ + import os import os.path from platform_methods import subprocess_main diff --git a/scene/theme/icons/default_theme_icons_builders.py b/scene/theme/icons/default_theme_icons_builders.py index c4d132294c..c915c52cbd 100644 --- a/scene/theme/icons/default_theme_icons_builders.py +++ b/scene/theme/icons/default_theme_icons_builders.py @@ -1,4 +1,5 @@ -"""Functions used to generate source files during build time +""" +Functions used to generate source files during build time All such functions are invoked in a subprocess on Windows to prevent build flakiness. diff --git a/scene/theme/theme_owner.cpp b/scene/theme/theme_owner.cpp index 2852a64e39..b559c8c58d 100644 --- a/scene/theme/theme_owner.cpp +++ b/scene/theme/theme_owner.cpp @@ -249,7 +249,7 @@ void ThemeOwner::get_theme_type_dependencies(const Node *p_for_node, const Strin ThemeDB::get_singleton()->get_native_type_dependencies(p_theme_type, r_list); } -Variant ThemeOwner::get_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { +Variant ThemeOwner::get_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, const List<StringName> &p_theme_types) { ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, Variant(), "At least one theme type must be specified."); // First, look through each control or window node in the branch, until no valid parent can be found. @@ -285,7 +285,7 @@ Variant ThemeOwner::get_theme_item_in_types(Theme::DataType p_data_type, const S return global_context->get_fallback_theme()->get_theme_item(p_data_type, p_name, StringName()); } -bool ThemeOwner::has_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { +bool ThemeOwner::has_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, const List<StringName> &p_theme_types) { ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, false, "At least one theme type must be specified."); // First, look through each control or window node in the branch, until no valid parent can be found. diff --git a/scene/theme/theme_owner.h b/scene/theme/theme_owner.h index 4923ccb00b..7e19279c2a 100644 --- a/scene/theme/theme_owner.h +++ b/scene/theme/theme_owner.h @@ -71,8 +71,8 @@ public: void get_theme_type_dependencies(const Node *p_for_node, const StringName &p_theme_type, List<StringName> *r_list) const; - Variant get_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types); - bool has_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types); + Variant get_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, const List<StringName> &p_theme_types); + bool has_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, const List<StringName> &p_theme_types); float get_theme_default_base_scale(); Ref<Font> get_theme_default_font(); diff --git a/scu_builders.py b/scu_builders.py index 71427eb717..56effb393c 100644 --- a/scu_builders.py +++ b/scu_builders.py @@ -277,6 +277,7 @@ def generate_scu_files(max_includes_per_scu): process_folder(["editor/export"]) process_folder(["editor/gui"]) process_folder(["editor/import"]) + process_folder(["editor/import/3d"]) process_folder(["editor/plugins"]) process_folder(["editor/plugins/gizmos"]) process_folder(["editor/plugins/tiles"]) diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 65d88a0eba..3e3a7d2381 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -80,6 +80,16 @@ void AudioStreamPlayback::tag_used_streams() { GDVIRTUAL_CALL(_tag_used_streams); } +void AudioStreamPlayback::set_parameter(const StringName &p_name, const Variant &p_value) { + GDVIRTUAL_CALL(_set_parameter, p_name, p_value); +} + +Variant AudioStreamPlayback::get_parameter(const StringName &p_name) const { + Variant ret; + GDVIRTUAL_CALL(_get_parameter, p_name, ret); + return ret; +} + void AudioStreamPlayback::_bind_methods() { GDVIRTUAL_BIND(_start, "from_pos") GDVIRTUAL_BIND(_stop) @@ -89,6 +99,8 @@ void AudioStreamPlayback::_bind_methods() { GDVIRTUAL_BIND(_seek, "position") GDVIRTUAL_BIND(_mix, "buffer", "rate_scale", "frames"); GDVIRTUAL_BIND(_tag_used_streams); + GDVIRTUAL_BIND(_set_parameter, "name", "value"); + GDVIRTUAL_BIND(_get_parameter, "name"); } ////////////////////////////// @@ -249,6 +261,16 @@ float AudioStream::get_tagged_frame_offset(int p_index) const { return tagged_offsets[p_index]; } +void AudioStream::get_parameter_list(List<Parameter> *r_parameters) { + TypedArray<Dictionary> ret; + GDVIRTUAL_CALL(_get_parameter_list, ret); + for (int i = 0; i < ret.size(); i++) { + Dictionary d = ret[i]; + ERR_CONTINUE(!d.has("default_value")); + r_parameters->push_back(Parameter(PropertyInfo::from_dict(d), d["default_value"])); + } +} + void AudioStream::_bind_methods() { ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length); ClassDB::bind_method(D_METHOD("is_monophonic"), &AudioStream::is_monophonic); @@ -259,6 +281,9 @@ void AudioStream::_bind_methods() { GDVIRTUAL_BIND(_is_monophonic); GDVIRTUAL_BIND(_get_bpm) GDVIRTUAL_BIND(_get_beat_count) + GDVIRTUAL_BIND(_get_parameter_list) + + ADD_SIGNAL(MethodInfo("parameter_list_changed")); } //////////////////////////////// diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 015e89fc8e..f8123fbe15 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -38,6 +38,7 @@ #include "core/object/gdvirtual.gen.inc" #include "core/variant/native_ptr.h" +#include "core/variant/typed_array.h" class AudioStream; @@ -54,6 +55,9 @@ protected: GDVIRTUAL1(_seek, double) GDVIRTUAL3R(int, _mix, GDExtensionPtr<AudioFrame>, float, int) GDVIRTUAL0(_tag_used_streams) + GDVIRTUAL2(_set_parameter, const StringName &, const Variant &) + GDVIRTUAL1RC(Variant, _get_parameter, const StringName &) + public: virtual void start(double p_from_pos = 0.0); virtual void stop(); @@ -66,6 +70,9 @@ public: virtual void tag_used_streams(); + virtual void set_parameter(const StringName &p_name, const Variant &p_value); + virtual Variant get_parameter(const StringName &p_name) const; + virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); }; @@ -124,6 +131,7 @@ protected: GDVIRTUAL0RC(bool, _has_loop) GDVIRTUAL0RC(int, _get_bar_beats) GDVIRTUAL0RC(int, _get_beat_count) + GDVIRTUAL0RC(TypedArray<Dictionary>, _get_parameter_list) public: virtual Ref<AudioStreamPlayback> instantiate_playback(); @@ -141,6 +149,17 @@ public: uint64_t get_tagged_frame() const; uint32_t get_tagged_frame_count() const; float get_tagged_frame_offset(int p_index) const; + + struct Parameter { + PropertyInfo property; + Variant default_value; + Parameter(const PropertyInfo &p_info = PropertyInfo(), const Variant &p_default_value = Variant()) { + property = p_info; + default_value = p_default_value; + } + }; + + virtual void get_parameter_list(List<Parameter> *r_parameters); }; // Microphone diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 511a8b3122..86bdd13c80 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -122,8 +122,10 @@ int AudioDriver::_get_configured_mix_rate() { // In the case of invalid mix rate, let's default to a sensible value.. if (mix_rate <= 0) { +#ifndef WEB_ENABLED WARN_PRINT(vformat("Invalid mix rate of %d, consider reassigning setting \'%s\'. \nDefaulting mix rate to value %d.", mix_rate, audio_driver_setting, AudioDriverManager::DEFAULT_MIX_RATE)); +#endif mix_rate = AudioDriverManager::DEFAULT_MIX_RATE; } @@ -199,8 +201,8 @@ int AudioDriverManager::get_driver_count() { void AudioDriverManager::initialize(int p_driver) { GLOBAL_DEF_RST("audio/driver/enable_input", false); - GLOBAL_DEF_RST("audio/driver/mix_rate", DEFAULT_MIX_RATE); - GLOBAL_DEF_RST("audio/driver/mix_rate.web", 0); // Safer default output_latency for web (use browser default). + GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/driver/mix_rate", PROPERTY_HINT_RANGE, "11025,192000,1,or_greater,suffix:Hz"), DEFAULT_MIX_RATE); + GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "audio/driver/mix_rate.web", PROPERTY_HINT_RANGE, "0,192000,1,or_greater,suffix:Hz"), 0); // Safer default output_latency for web (use browser default). int failed_driver = -1; @@ -1118,7 +1120,7 @@ float AudioServer::get_playback_speed_scale() const { return playback_speed_scale; } -void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time, float p_pitch_scale) { +void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, const StringName &p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time, float p_pitch_scale) { ERR_FAIL_COND(p_playback.is_null()); HashMap<StringName, Vector<AudioFrame>> map; @@ -1127,7 +1129,7 @@ void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Str start_playback_stream(p_playback, map, p_start_time, p_pitch_scale); } -void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) { +void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, const HashMap<StringName, Vector<AudioFrame>> &p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) { ERR_FAIL_COND(p_playback.is_null()); AudioStreamPlaybackListNode *playback_node = new AudioStreamPlaybackListNode(); @@ -1147,6 +1149,7 @@ void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Has for (int channel_idx = 0; channel_idx < MAX_CHANNELS_PER_BUS; channel_idx++) { new_bus_details->volume[idx][channel_idx] = pair.value[channel_idx]; } + idx++; } playback_node->bus_details = new_bus_details; playback_node->prev_bus_details = new AudioStreamPlaybackBusDetails(); @@ -1185,7 +1188,7 @@ void AudioServer::stop_playback_stream(Ref<AudioStreamPlayback> p_playback) { } while (!playback_node->state.compare_exchange_strong(old_state, new_state)); } -void AudioServer::set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes) { +void AudioServer::set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, const StringName &p_bus, Vector<AudioFrame> p_volumes) { ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS); HashMap<StringName, Vector<AudioFrame>> map; @@ -1194,7 +1197,7 @@ void AudioServer::set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback set_playback_bus_volumes_linear(p_playback, map); } -void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes) { +void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, const HashMap<StringName, Vector<AudioFrame>> &p_bus_volumes) { ERR_FAIL_COND(p_bus_volumes.size() > MAX_BUSES_PER_PLAYBACK); AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback); diff --git a/servers/audio_server.h b/servers/audio_server.h index 9ffa95bc00..4606299c47 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -372,13 +372,13 @@ public: float get_playback_speed_scale() const; // Convenience method. - void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0, float p_pitch_scale = 1); + void start_playback_stream(Ref<AudioStreamPlayback> p_playback, const StringName &p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0, float p_pitch_scale = 1); // Expose all parameters. - void start_playback_stream(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0); + void start_playback_stream(Ref<AudioStreamPlayback> p_playback, const HashMap<StringName, Vector<AudioFrame>> &p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0); void stop_playback_stream(Ref<AudioStreamPlayback> p_playback); - void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes); - void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes); + void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, const StringName &p_bus, Vector<AudioFrame> p_volumes); + void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, const HashMap<StringName, Vector<AudioFrame>> &p_bus_volumes); void set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Vector<AudioFrame> p_volumes); void set_playback_pitch_scale(Ref<AudioStreamPlayback> p_playback, float p_pitch_scale); void set_playback_paused(Ref<AudioStreamPlayback> p_playback, bool p_paused); diff --git a/servers/display_server.cpp b/servers/display_server.cpp index bb28bc0eb8..a587f72d02 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -596,6 +596,10 @@ DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window) return VSyncMode::VSYNC_ENABLED; } +DisplayServer::WindowID DisplayServer::get_focused_window() const { + return MAIN_WINDOW_ID; // Proper value for single windows. +} + void DisplayServer::set_context(Context p_context) { } diff --git a/servers/display_server.h b/servers/display_server.h index 4450677f71..92a4a4a699 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -436,6 +436,8 @@ public: virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) = 0; virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const = 0; + virtual WindowID get_focused_window() const; + virtual void window_set_window_buttons_offset(const Vector2i &p_offset, WindowID p_window = MAIN_WINDOW_ID) {} virtual Vector3i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const { return Vector3i(); } diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 258a799d34..412b12e145 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -213,12 +213,12 @@ NavigationServer3D::NavigationServer3D() { ERR_FAIL_COND(singleton != nullptr); singleton = this; - GLOBAL_DEF_BASIC("navigation/2d/default_cell_size", 1.0); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::FLOAT, "navigation/2d/default_cell_size", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater"), 1.0); GLOBAL_DEF("navigation/2d/use_edge_connections", true); GLOBAL_DEF_BASIC("navigation/2d/default_edge_connection_margin", 1.0); GLOBAL_DEF_BASIC("navigation/2d/default_link_connection_radius", 4.0); - GLOBAL_DEF_BASIC("navigation/3d/default_cell_size", 0.25); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::FLOAT, "navigation/3d/default_cell_size", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater"), 0.25); GLOBAL_DEF_BASIC("navigation/3d/default_cell_height", 0.25); GLOBAL_DEF("navigation/3d/default_up", Vector3(0, 1, 0)); GLOBAL_DEF("navigation/3d/use_edge_connections", true); @@ -286,7 +286,7 @@ void NavigationServer3D::set_debug_enabled(bool p_enabled) { debug_enabled = p_enabled; if (debug_dirty) { - call_deferred("_emit_navigation_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_navigation_debug_changed_signal).call_deferred(); } #endif // DEBUG_ENABLED } @@ -693,7 +693,7 @@ Color NavigationServer3D::get_debug_navigation_agent_path_color() const { void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) { debug_navigation_enable_edge_connections = p_value; navigation_debug_dirty = true; - call_deferred("_emit_navigation_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_navigation_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_navigation_enable_edge_connections() const { @@ -714,7 +714,7 @@ bool NavigationServer3D::get_debug_navigation_enable_edge_connections_xray() con void NavigationServer3D::set_debug_navigation_enable_edge_lines(const bool p_value) { debug_navigation_enable_edge_lines = p_value; navigation_debug_dirty = true; - call_deferred("_emit_navigation_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_navigation_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_navigation_enable_edge_lines() const { @@ -735,7 +735,7 @@ bool NavigationServer3D::get_debug_navigation_enable_edge_lines_xray() const { void NavigationServer3D::set_debug_navigation_enable_geometry_face_random_color(const bool p_value) { debug_navigation_enable_geometry_face_random_color = p_value; navigation_debug_dirty = true; - call_deferred("_emit_navigation_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_navigation_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_navigation_enable_geometry_face_random_color() const { @@ -745,7 +745,7 @@ bool NavigationServer3D::get_debug_navigation_enable_geometry_face_random_color( void NavigationServer3D::set_debug_navigation_enable_link_connections(const bool p_value) { debug_navigation_enable_link_connections = p_value; navigation_debug_dirty = true; - call_deferred("_emit_navigation_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_navigation_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_navigation_enable_link_connections() const { @@ -766,7 +766,7 @@ bool NavigationServer3D::get_debug_navigation_enable_link_connections_xray() con void NavigationServer3D::set_debug_navigation_avoidance_enable_agents_radius(const bool p_value) { debug_navigation_avoidance_enable_agents_radius = p_value; avoidance_debug_dirty = true; - call_deferred("_emit_avoidance_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_avoidance_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_navigation_avoidance_enable_agents_radius() const { @@ -776,7 +776,7 @@ bool NavigationServer3D::get_debug_navigation_avoidance_enable_agents_radius() c void NavigationServer3D::set_debug_navigation_avoidance_enable_obstacles_radius(const bool p_value) { debug_navigation_avoidance_enable_obstacles_radius = p_value; avoidance_debug_dirty = true; - call_deferred("_emit_avoidance_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_avoidance_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_navigation_avoidance_enable_obstacles_radius() const { @@ -786,7 +786,7 @@ bool NavigationServer3D::get_debug_navigation_avoidance_enable_obstacles_radius( void NavigationServer3D::set_debug_navigation_avoidance_enable_obstacles_static(const bool p_value) { debug_navigation_avoidance_enable_obstacles_static = p_value; avoidance_debug_dirty = true; - call_deferred("_emit_avoidance_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_avoidance_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_navigation_avoidance_enable_obstacles_static() const { @@ -867,7 +867,7 @@ void NavigationServer3D::set_debug_navigation_enable_agent_paths(const bool p_va debug_navigation_enable_agent_paths = p_value; if (debug_dirty) { - call_deferred("_emit_navigation_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_navigation_debug_changed_signal).call_deferred(); } } @@ -892,7 +892,7 @@ bool NavigationServer3D::get_debug_navigation_enable_agent_paths_xray() const { void NavigationServer3D::set_debug_navigation_enabled(bool p_enabled) { debug_navigation_enabled = p_enabled; navigation_debug_dirty = true; - call_deferred("_emit_navigation_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_navigation_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_navigation_enabled() const { @@ -902,7 +902,7 @@ bool NavigationServer3D::get_debug_navigation_enabled() const { void NavigationServer3D::set_debug_avoidance_enabled(bool p_enabled) { debug_avoidance_enabled = p_enabled; avoidance_debug_dirty = true; - call_deferred("_emit_avoidance_debug_changed_signal"); + callable_mp(this, &NavigationServer3D::_emit_avoidance_debug_changed_signal).call_deferred(); } bool NavigationServer3D::get_debug_avoidance_enabled() const { diff --git a/servers/physics_2d/godot_area_pair_2d.cpp b/servers/physics_2d/godot_area_pair_2d.cpp index bd1540bac8..ca12e30c29 100644 --- a/servers/physics_2d/godot_area_pair_2d.cpp +++ b/servers/physics_2d/godot_area_pair_2d.cpp @@ -66,6 +66,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) { if (colliding) { if (has_space_override) { + body_has_attached_area = true; body->add_area(area); } @@ -74,6 +75,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) { } } else { if (has_space_override) { + body_has_attached_area = false; body->remove_area(area); } @@ -103,7 +105,8 @@ GodotAreaPair2D::GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotAre GodotAreaPair2D::~GodotAreaPair2D() { if (colliding) { - if (has_space_override) { + if (body_has_attached_area) { + body_has_attached_area = false; body->remove_area(area); } if (area->has_monitor_callback()) { diff --git a/servers/physics_2d/godot_area_pair_2d.h b/servers/physics_2d/godot_area_pair_2d.h index 938b9813b4..eb091288a9 100644 --- a/servers/physics_2d/godot_area_pair_2d.h +++ b/servers/physics_2d/godot_area_pair_2d.h @@ -43,6 +43,7 @@ class GodotAreaPair2D : public GodotConstraint2D { bool colliding = false; bool has_space_override = false; bool process_collision = false; + bool body_has_attached_area = false; public: virtual bool setup(real_t p_step) override; diff --git a/servers/physics_2d/godot_shape_2d.cpp b/servers/physics_2d/godot_shape_2d.cpp index dadd8173c6..2b3f496fc0 100644 --- a/servers/physics_2d/godot_shape_2d.cpp +++ b/servers/physics_2d/godot_shape_2d.cpp @@ -373,8 +373,7 @@ void GodotCapsuleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_suppo if (h > 0 && Math::abs(n.x) > segment_is_valid_support_threshold) { // make it flat n.y = 0.0; - n.normalize(); - n *= radius; + n.x = SIGN(n.x) * radius; r_amount = 2; r_supports[0] = n; diff --git a/servers/physics_3d/godot_area_pair_3d.cpp b/servers/physics_3d/godot_area_pair_3d.cpp index 5561210f2d..aaa96f5a28 100644 --- a/servers/physics_3d/godot_area_pair_3d.cpp +++ b/servers/physics_3d/godot_area_pair_3d.cpp @@ -67,6 +67,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) { if (colliding) { if (has_space_override) { + body_has_attached_area = true; body->add_area(area); } @@ -75,6 +76,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) { } } else { if (has_space_override) { + body_has_attached_area = false; body->remove_area(area); } @@ -104,7 +106,8 @@ GodotAreaPair3D::GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotAre GodotAreaPair3D::~GodotAreaPair3D() { if (colliding) { - if (has_space_override) { + if (body_has_attached_area) { + body_has_attached_area = false; body->remove_area(area); } if (area->has_monitor_callback()) { @@ -242,6 +245,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) { if (colliding) { if (has_space_override) { + body_has_attached_area = true; soft_body->add_area(area); } @@ -250,6 +254,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) { } } else { if (has_space_override) { + body_has_attached_area = false; soft_body->remove_area(area); } @@ -276,7 +281,8 @@ GodotAreaSoftBodyPair3D::GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_soft_body, i GodotAreaSoftBodyPair3D::~GodotAreaSoftBodyPair3D() { if (colliding) { - if (has_space_override) { + if (body_has_attached_area) { + body_has_attached_area = false; soft_body->remove_area(area); } if (area->has_monitor_callback()) { diff --git a/servers/physics_3d/godot_area_pair_3d.h b/servers/physics_3d/godot_area_pair_3d.h index c11fa07827..a2c5df0f7a 100644 --- a/servers/physics_3d/godot_area_pair_3d.h +++ b/servers/physics_3d/godot_area_pair_3d.h @@ -44,6 +44,7 @@ class GodotAreaPair3D : public GodotConstraint3D { bool colliding = false; bool process_collision = false; bool has_space_override = false; + bool body_has_attached_area = false; public: virtual bool setup(real_t p_step) override; @@ -83,6 +84,7 @@ class GodotAreaSoftBodyPair3D : public GodotConstraint3D { bool colliding = false; bool process_collision = false; bool has_space_override = false; + bool body_has_attached_area = false; public: virtual bool setup(real_t p_step) override; diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp index f4682b7c14..a23bb5e701 100644 --- a/servers/physics_server_2d_wrap_mt.cpp +++ b/servers/physics_server_2d_wrap_mt.cpp @@ -120,8 +120,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool physics_server_2d = p_contained; create_thread = p_create_thread; - pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); - if (!p_create_thread) { server_thread = Thread::get_caller_id(); } else { diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index 0ae004da19..3bebe5df85 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -66,7 +66,6 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D { bool first_frame = true; Mutex alloc_mutex; - int pool_max_size = 0; public: #define ServerName PhysicsServer2D diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index d523f4b1ec..addd1a5663 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -343,7 +343,7 @@ void PhysicsShapeQueryParameters3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "set_motion", "get_motion"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform"), "set_transform", "get_transform"); diff --git a/servers/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp index 59db4617d0..feb17cad84 100644 --- a/servers/physics_server_3d_wrap_mt.cpp +++ b/servers/physics_server_3d_wrap_mt.cpp @@ -120,8 +120,6 @@ PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool physics_server_3d = p_contained; create_thread = p_create_thread; - pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); - if (!p_create_thread) { server_thread = Thread::get_caller_id(); } else { diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index 99179d8248..fc8930977d 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -65,7 +65,6 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D { bool first_frame = true; Mutex alloc_mutex; - int pool_max_size = 0; public: #define ServerName PhysicsServer3D diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 2beab44f91..0ee2984a8c 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -88,7 +88,11 @@ ShaderTypes *shader_types = nullptr; static PhysicsServer3D *_createGodotPhysics3DCallback() { +#ifdef THREADS_ENABLED bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread"); +#else + bool using_threads = false; +#endif PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads)); @@ -96,7 +100,11 @@ static PhysicsServer3D *_createGodotPhysics3DCallback() { } static PhysicsServer2D *_createGodotPhysics2DCallback() { +#ifdef THREADS_ENABLED bool using_threads = GLOBAL_GET("physics/2d/run_on_separate_thread"); +#else + bool using_threads = false; +#endif PhysicsServer2D *physics_server_2d = memnew(GodotPhysicsServer2D(using_threads)); diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h index 179c41f286..929c661009 100644 --- a/servers/rendering/dummy/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -89,6 +89,8 @@ public: void prepare_for_blitting_render_targets() override {} void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {} + void end_viewport(bool p_swap_buffers) override {} + void end_frame(bool p_swap_buffers) override { if (p_swap_buffers) { DisplayServer::get_singleton()->swap_buffers(); diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index cc51d44042..caeac5cd95 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -37,17 +37,17 @@ #include "rendering_server_globals.h" #include "servers/rendering/storage/texture_storage.h" -void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) { +void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) { RENDER_TIMESTAMP("Cull CanvasItem Tree"); memset(z_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); for (int i = 0; i < p_child_item_count; i++) { - _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask); + _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask); } if (p_canvas_item) { - _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask); + _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask); } RendererCanvasRender::Item *list = nullptr; @@ -114,29 +114,29 @@ void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_Owner<Renderer } while (ysort_owner && ysort_owner->sort_y); } -void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform) { +void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &p_transform, const Rect2 &p_clip_rect, Rect2 p_global_rect, const Color &p_modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *r_canvas_group_from) { if (ci->copy_back_buffer) { - ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect); + ci->copy_back_buffer->screen_rect = p_transform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect); } if (p_use_canvas_group) { int zidx = p_z - RS::CANVAS_ITEM_Z_MIN; - if (canvas_group_from == nullptr) { + if (r_canvas_group_from == nullptr) { // no list before processing this item, means must put stuff in group from the beginning of list. - canvas_group_from = r_z_list[zidx]; + r_canvas_group_from = r_z_list[zidx]; } else { // there was a list before processing, so begin group from this one. - canvas_group_from = canvas_group_from->next; + r_canvas_group_from = r_canvas_group_from->next; } - if (canvas_group_from) { + if (r_canvas_group_from) { // Has a place to begin the group from! //compute a global rect (in global coords) for children in the same z layer Rect2 rect_accum; - RendererCanvasRender::Item *c = canvas_group_from; + RendererCanvasRender::Item *c = r_canvas_group_from; while (c) { - if (c == canvas_group_from) { + if (c == r_canvas_group_from) { rect_accum = c->global_rect_cache; } else { rect_accum = rect_accum.merge(c->global_rect_cache); @@ -161,28 +161,28 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item * RendererCanvasRender::Item::CommandRect *crect = ci->alloc_command<RendererCanvasRender::Item::CommandRect>(); crect->flags = RendererCanvasRender::CANVAS_RECT_IS_GROUP; // so we can recognize it later - crect->rect = xform.affine_inverse().xform(rect_accum); + crect->rect = p_transform.affine_inverse().xform(rect_accum); crect->modulate = Color(1, 1, 1, 1); //the global rect is used to do the copying, so update it - global_rect = rect_accum.grow(ci->canvas_group->clear_margin); //grow again by clear margin - global_rect.position += p_clip_rect.position; + p_global_rect = rect_accum.grow(ci->canvas_group->clear_margin); //grow again by clear margin + p_global_rect.position += p_clip_rect.position; } else { - global_rect.position -= p_clip_rect.position; + p_global_rect.position -= p_clip_rect.position; - global_rect = global_rect.merge(rect_accum); //must use both rects for this - global_rect = global_rect.grow(ci->canvas_group->clear_margin); //grow by clear margin + p_global_rect = p_global_rect.merge(rect_accum); //must use both rects for this + p_global_rect = p_global_rect.grow(ci->canvas_group->clear_margin); //grow by clear margin - global_rect.position += p_clip_rect.position; + p_global_rect.position += p_clip_rect.position; } // Very important that this is cleared after used in RendererCanvasRender to avoid // potential crashes. - canvas_group_from->canvas_group_owner = ci; + r_canvas_group_from->canvas_group_owner = ci; } } - if (((ci->commands != nullptr || ci->visibility_notifier) && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) { + if (((ci->commands != nullptr || ci->visibility_notifier) && p_clip_rect.intersects(p_global_rect, true)) || ci->vp_render || ci->copy_back_buffer) { //something to draw? if (ci->update_when_visible) { @@ -190,9 +190,9 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item * } if (ci->commands != nullptr || ci->copy_back_buffer) { - ci->final_transform = xform; - ci->final_modulate = modulate * ci->self_modulate; - ci->global_rect_cache = global_rect; + ci->final_transform = p_transform; + ci->final_modulate = p_modulate * ci->self_modulate; + ci->global_rect_cache = p_global_rect; ci->global_rect_cache.position -= p_clip_rect.position; ci->light_masked = false; @@ -223,14 +223,14 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item * } } -void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask) { +void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask) { Item *ci = p_canvas_item; if (!ci->visible) { return; } - if (!(ci->visibility_layer & canvas_cull_mask)) { + if (!(ci->visibility_layer & p_canvas_cull_mask)) { return; } @@ -298,7 +298,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 } if (ci->sort_y) { - if (allow_y_sort) { + if (p_allow_y_sort) { if (ci->ysort_children_count == -1) { ci->ysort_children_count = 0; _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), nullptr, ci->ysort_children_count, p_z); @@ -318,7 +318,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 sorter.sort(child_items, child_item_count); for (i = 0; i < child_item_count; i++) { - _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, canvas_cull_mask); + _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, p_canvas_cull_mask); } } else { RendererCanvasRender::Item *canvas_group_from = nullptr; @@ -328,7 +328,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 canvas_group_from = r_z_last_list[zidx]; } - _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform); + _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from); } } else { RendererCanvasRender::Item *canvas_group_from = nullptr; @@ -342,14 +342,14 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 if (!child_items[i]->behind && !use_canvas_group) { continue; } - _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask); + _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask); } - _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform); + _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from); for (int i = 0; i < child_item_count; i++) { if (child_items[i]->behind || use_canvas_group) { continue; } - _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask); + _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask); } } } @@ -2165,6 +2165,30 @@ bool RendererCanvasCull::free(RID p_rid) { return true; } +template <class T> +void RendererCanvasCull::_free_rids(T &p_owner, const char *p_type) { + List<RID> owned; + p_owner.get_owned_list(&owned); + if (owned.size()) { + if (owned.size() == 1) { + WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type)); + } else { + WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type)); + } + for (const RID &E : owned) { + free(E); + } + } +} + +void RendererCanvasCull::finalize() { + _free_rids(canvas_owner, "Canvas"); + _free_rids(canvas_item_owner, "CanvasItem"); + _free_rids(canvas_light_owner, "CanvasLight"); + _free_rids(canvas_light_occluder_owner, "CanvasLightOccluder"); + _free_rids(canvas_light_occluder_polygon_owner, "CanvasLightOccluderPolygon"); +} + RendererCanvasCull::RendererCanvasCull() { z_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *)); z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *)); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index ba013e667f..de61e28204 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -170,6 +170,9 @@ public: RID_Owner<Item, true> canvas_item_owner; RID_Owner<RendererCanvasRender::Light, true> canvas_light_owner; + template <class T> + void _free_rids(T &p_owner, const char *p_type); + bool disable_scale; bool sdf_used = false; bool snapping_2d_transforms_to_pixel = false; @@ -181,11 +184,11 @@ public: PagedAllocator<Item::VisibilityNotifierData> visibility_notifier_allocator; SelfList<Item::VisibilityNotifierData>::List visibility_notifier_list; - _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform); + _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &p_transform, const Rect2 &p_clip_rect, Rect2 p_global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *r_canvas_group_from); private: - void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info = nullptr); - void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask); + void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info = nullptr); + void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask); static constexpr int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; @@ -193,7 +196,7 @@ private: RendererCanvasRender::Item **z_last_list; public: - void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info = nullptr); + void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info = nullptr); bool was_sdf_used(); @@ -329,6 +332,9 @@ public: Rect2 _debug_canvas_item_get_rect(RID p_item); bool free(RID p_rid); + + void finalize(); + RendererCanvasCull(); ~RendererCanvasCull(); }; diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp index af0ec621e5..6eb7bab9c9 100644 --- a/servers/rendering/renderer_canvas_render.cpp +++ b/servers/rendering/renderer_canvas_render.cpp @@ -31,6 +31,8 @@ #include "renderer_canvas_render.h" #include "servers/rendering/rendering_server_globals.h" +RendererCanvasRender *RendererCanvasRender::singleton = nullptr; + const Rect2 &RendererCanvasRender::Item::get_rect() const { if (custom_rect || (!rect_dirty && !update_when_visible && skeleton == RID())) { return rect; diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp index a6083fe70d..c36da51e50 100644 --- a/servers/rendering/renderer_compositor.cpp +++ b/servers/rendering/renderer_compositor.cpp @@ -31,8 +31,6 @@ #include "renderer_compositor.h" #include "core/config/project_settings.h" -#include "core/os/os.h" -#include "core/string/print_string.h" #include "servers/xr_server.h" RendererCompositor *RendererCompositor::singleton = nullptr; @@ -57,5 +55,3 @@ RendererCompositor::RendererCompositor() { xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON; } } - -RendererCanvasRender *RendererCanvasRender::singleton = nullptr; diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index ff7792741c..13767a3875 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -99,6 +99,7 @@ public: virtual void prepare_for_blitting_render_targets() = 0; virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0; + virtual void end_viewport(bool p_swap_buffers) = 0; virtual void end_frame(bool p_swap_buffers) = 0; virtual void finalize() = 0; virtual uint64_t get_frame_number() const = 0; diff --git a/servers/rendering/renderer_rd/api_context_rd.h b/servers/rendering/renderer_rd/api_context_rd.h index 22167be3c1..fd3be80605 100644 --- a/servers/rendering/renderer_rd/api_context_rd.h +++ b/servers/rendering/renderer_rd/api_context_rd.h @@ -58,16 +58,12 @@ public: virtual void set_setup_buffer(RDD::CommandBufferID p_command_buffer) = 0; virtual void append_command_buffer(RDD::CommandBufferID p_command_buffer) = 0; - virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false) = 0; + virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false, bool p_sync = true) = 0; virtual Error prepare_buffers(RDD::CommandBufferID p_command_buffer) = 0; virtual void postpare_buffers(RDD::CommandBufferID p_command_buffer) = 0; virtual Error swap_buffers() = 0; virtual Error initialize() = 0; - virtual void command_begin_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) = 0; - virtual void command_insert_label(RDD::CommandBufferID p_command_buffer, String p_label_name, const Color &p_color) = 0; - virtual void command_end_label(RDD::CommandBufferID p_command_buffer) = 0; - virtual String get_device_vendor_name() const = 0; virtual String get_device_name() const = 0; virtual RDD::DeviceType get_device_type() const = 0; @@ -78,6 +74,7 @@ public: virtual DisplayServer::VSyncMode get_vsync_mode(DisplayServer::WindowID p_window = 0) const = 0; virtual RenderingDeviceDriver *get_driver(RID p_local_device = RID()) = 0; + virtual bool is_debug_utils_enabled() const = 0; virtual ~ApiContextRD(); }; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 7554e478bb..e661fd9217 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -266,8 +266,8 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID screen_size = p_screen_size; - cluster_screen_size.width = (p_screen_size.width - 1) / cluster_size + 1; - cluster_screen_size.height = (p_screen_size.height - 1) / cluster_size + 1; + cluster_screen_size.width = Math::division_round_up((uint32_t)p_screen_size.width, cluster_size); + cluster_screen_size.height = Math::division_round_up((uint32_t)p_screen_size.height, cluster_size); max_elements_by_type = p_max_elements; if (max_elements_by_type % 32) { // Needs to be aligned to 32. @@ -420,11 +420,11 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->draw_command_begin_label("Bake Light Cluster"); // Clear cluster buffer. - RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size); if (render_element_count > 0) { // Clear render buffer. - RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size); { // Fill state uniform. @@ -439,18 +439,18 @@ void ClusterBuilderRD::bake_cluster() { state.cluster_depth_offset = (render_element_max / 32); state.cluster_data_size = state.cluster_depth_offset + render_element_max; - RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state); } // Update instances. - RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements); RENDER_TIMESTAMP("Render 3D Cluster Elements"); // Render elements. { - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD); ClusterBuilderSharedDataRD::ClusterRender::PushConstant push_constant = {}; RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shared->cluster_render.shader_pipelines[use_msaa ? ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_MSAA : ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_NORMAL]); @@ -488,7 +488,7 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->draw_list_draw(draw_list, true, instances); i += instances; } - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->draw_list_end(); } // Store elements. RENDER_TIMESTAMP("Pack 3D Cluster Elements"); @@ -503,7 +503,8 @@ void ClusterBuilderRD::bake_cluster() { push_constant.max_render_element_count_div_32 = render_element_max / 32; push_constant.cluster_screen_size[0] = cluster_screen_size.x; push_constant.cluster_screen_size[1] = cluster_screen_size.y; - push_constant.render_element_count_div_32 = render_element_count > 0 ? (render_element_count - 1) / 32 + 1 : 0; + + push_constant.render_element_count_div_32 = Math::division_round_up(render_element_count, 32U); push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32; push_constant.pad1 = 0; push_constant.pad2 = 0; @@ -512,10 +513,8 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->compute_list_dispatch_threads(compute_list, cluster_screen_size.x, cluster_screen_size.y, 1); - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->compute_list_end(); } - } else { - RD::get_singleton()->barrier(RD::BARRIER_MASK_TRANSFER, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); } RENDER_TIMESTAMP("< Bake 3D Cluster"); RD::get_singleton()->draw_command_end_label(); diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp index cc5031823e..e6262c83e2 100644 --- a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp +++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp @@ -356,7 +356,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr ERR_FAIL_COND(shader.is_null()); RID framebuffer = p_buffers.base_weight_fb; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_depth_texture), 0); @@ -388,7 +388,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; // Pass 1 - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1); @@ -412,7 +412,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr RD::Uniform texture = bokeh.push_constant.half_size ? u_half_texture0 : u_secondary_texture; RD::Uniform weight = bokeh.push_constant.half_size ? u_weight_texture2 : u_weight_texture1; - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, texture), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, weight), 1); @@ -430,7 +430,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr framebuffer = p_buffers.base_fb; - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture1), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture3), 1); @@ -463,7 +463,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1); @@ -481,7 +481,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr framebuffer = p_buffers.base_fb; - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture0), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture2), 1); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index 92bd3a043a..fd6409d6bf 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -533,7 +533,7 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff RD::get_singleton()->draw_list_draw(draw_list, true); } -void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one, bool p_linear) { +void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one, bool p_linear, bool p_normal) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -564,6 +564,10 @@ void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffe copy_to_fb.push_constant.luminance_multiplier = prefer_raster_effects ? 2.0 : 1.0; } + if (p_normal) { + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_NORMAL; + } + // setup our uniforms RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -579,7 +583,7 @@ void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffe RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); if (p_secondary.is_valid()) { @@ -646,7 +650,7 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) { ERR_FAIL_COND(shader.is_null()); // Just copy it back (we use our blur raster shader here).. - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); @@ -720,7 +724,7 @@ void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_textu RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); @@ -822,7 +826,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_textu ERR_FAIL_COND(shader.is_null()); //HORIZONTAL - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(half_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); if (p_auto_exposure.is_valid() && p_first_pass) { @@ -842,7 +846,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_textu ERR_FAIL_COND(shader.is_null()); //VERTICAL - draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0); @@ -912,7 +916,7 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); @@ -978,7 +982,7 @@ void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, con RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_region); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); @@ -986,7 +990,7 @@ void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, con RD::get_singleton()->draw_list_end(); } -void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip, BitField<RD::BarrierMask> p_post_barrier) { +void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -1011,14 +1015,14 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(p_post_barrier); + RD::get_singleton()->draw_list_end(); } void CopyEffects::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) { @@ -1046,8 +1050,8 @@ void CopyEffects::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, c RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_cubemap), 1); - int x_groups = (p_size.x - 1) / 8 + 1; - int y_groups = (p_size.y - 1) / 8 + 1; + int x_groups = Math::division_round_up(p_size.x, 8); + int y_groups = Math::division_round_up(p_size.y, 8); RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant)); @@ -1076,7 +1080,7 @@ void CopyEffects::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_fra RID shader = cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0); @@ -1155,7 +1159,7 @@ void CopyEffects::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebu RID shader = filter.raster_shader.version_get_shader(filter.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1); @@ -1200,8 +1204,8 @@ void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); - int x_groups = (p_size - 1) / 8 + 1; - int y_groups = (p_size - 1) / 8 + 1; + int x_groups = Math::division_round_up(p_size, 8); + int y_groups = x_groups; RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1); @@ -1233,7 +1237,7 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f RID shader = roughness.raster_shader.version_get_shader(roughness.shader_version, 0); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); @@ -1253,7 +1257,7 @@ void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_b RD::get_singleton()->draw_command_begin_label("Merge specular"); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>()); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, Vector<Color>()); int mode; if (p_reflection.is_valid()) { diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index f9dcc42421..d18971a676 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -190,6 +190,7 @@ private: COPY_TO_FB_FLAG_SRGB = (1 << 4), COPY_TO_FB_FLAG_ALPHA_TO_ONE = (1 << 5), COPY_TO_FB_FLAG_LINEAR = (1 << 6), + COPY_TO_FB_FLAG_NORMAL = (1 << 7), }; struct CopyToFbPushConstant { @@ -328,7 +329,7 @@ public: void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); - void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false, bool p_linear = false); + void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false, bool p_linear = false, bool p_normal = false); void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); void copy_to_drawlist(RD::DrawListID p_draw_list, RD::FramebufferFormatID p_fb_format, RID p_source_rd_texture, bool p_linear = false); void copy_raster(RID p_source_texture, RID p_dest_framebuffer); @@ -344,7 +345,7 @@ public: void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); void set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region); - void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip, BitField<RD::BarrierMask> p_post_barrier = RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER); + void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip); void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size); void cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size); void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array); diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp index 3033d42375..a57a65fd5a 100644 --- a/servers/rendering/renderer_rd/effects/debug_effects.cpp +++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp @@ -282,7 +282,7 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj // And draw our frustum. RD::FramebufferFormatID fb_format_id = RD::get_singleton()->framebuffer_get_format(p_dest_fb); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, rect); RID pipeline = shadow_frustum.pipelines[SFP_TRANSPARENT].get_render_pipeline(frustum.vertex_format, fb_format_id); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline); @@ -326,7 +326,7 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj rect.size.x *= atlas_rect_norm.size.x; rect.size.y *= atlas_rect_norm.size.y; - draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, rect); + draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, rect); pipeline = shadow_frustum.pipelines[SFP_TRANSPARENT].get_render_pipeline(frustum.vertex_format, fb_format_id); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline); @@ -351,7 +351,7 @@ void DebugEffects::draw_motion_vectors(RID p_velocity, RID p_depth, RID p_dest_f RD::Uniform u_source_velocity(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_velocity })); RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_depth })); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, motion_vectors.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_fb), false, RD::get_singleton()->draw_list_get_current_pass())); Projection reprojection = p_previous_projection.flipped_y() * p_previous_transform.affine_inverse() * p_current_transform * p_current_projection.flipped_y().inverse(); diff --git a/servers/rendering/renderer_rd/effects/fsr.cpp b/servers/rendering/renderer_rd/effects/fsr.cpp index 0c51adf9ee..5599a5a162 100644 --- a/servers/rendering/renderer_rd/effects/fsr.cpp +++ b/servers/rendering/renderer_rd/effects/fsr.cpp @@ -124,5 +124,5 @@ void FSR::fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_r RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1); - RD::get_singleton()->compute_list_end(compute_list); + RD::get_singleton()->compute_list_end(); } diff --git a/servers/rendering/renderer_rd/effects/fsr2.cpp b/servers/rendering/renderer_rd/effects/fsr2.cpp index 0c38989304..bebbf51d51 100644 --- a/servers/rendering/renderer_rd/effects/fsr2.cpp +++ b/servers/rendering/renderer_rd/effects/fsr2.cpp @@ -377,10 +377,7 @@ static FfxErrorCode execute_gpu_job_copy_rd(FSR2Context::Scratch &p_scratch, con ERR_FAIL_COND_V(dst_desc.type == FFX_RESOURCE_TYPE_BUFFER, FFX_ERROR_INVALID_ARGUMENT); for (uint32_t mip_level = 0; mip_level < src_desc.mipCount; mip_level++) { - // Only push the barriers on the last copy. - // FIXME: This could be optimized if RenderingDevice was able to copy multiple mip levels in a single command. - BitField<RD::BarrierMask> post_barrier = (mip_level == (src_desc.mipCount - 1)) ? RD::BARRIER_MASK_ALL_BARRIERS : RD::BARRIER_MASK_NO_BARRIER; - RD::get_singleton()->texture_copy(src, dst, Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(src_desc.width, src_desc.height, src_desc.depth), mip_level, mip_level, 0, 0, post_barrier); + RD::get_singleton()->texture_copy(src, dst, Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(src_desc.width, src_desc.height, src_desc.depth), mip_level, mip_level, 0, 0); } return FFX_OK; @@ -435,8 +432,7 @@ static FfxErrorCode execute_gpu_job_compute_rd(FSR2Context::Scratch &p_scratch, RID buffer_rid = p_scratch.ubo_ring_buffer[p_scratch.ubo_ring_buffer_index]; p_scratch.ubo_ring_buffer_index = (p_scratch.ubo_ring_buffer_index + 1) % FSR2_UBO_RING_BUFFER_SIZE; - BitField<RD::BarrierMask> post_barrier = (i == (p_job.pipeline.constCount - 1)) ? RD::BARRIER_MASK_ALL_BARRIERS : RD::BARRIER_MASK_NO_BARRIER; - RD::get_singleton()->buffer_update(buffer_rid, 0, p_job.cbs[i].uint32Size * sizeof(uint32_t), p_job.cbs[i].data, post_barrier); + RD::get_singleton()->buffer_update(buffer_rid, 0, p_job.cbs[i].uint32Size * sizeof(uint32_t), p_job.cbs[i].data); RD::Uniform buffer_uniform(RD::UNIFORM_TYPE_UNIFORM_BUFFER, p_job.pipeline.cbResourceBindings[i].slotIndex, buffer_rid); compute_uniforms.push_back(buffer_uniform); @@ -566,7 +562,6 @@ FSR2Effect::FSR2Effect() { FfxResourceBinding{ 2, 0, L"r_dilatedDepth" }, FfxResourceBinding{ 3, 0, L"r_reactive_mask" }, FfxResourceBinding{ 4, 0, L"r_transparency_and_composition_mask" }, - FfxResourceBinding{ 5, 0, L"r_prepared_input_color" }, FfxResourceBinding{ 6, 0, L"r_previous_dilated_motion_vectors" }, FfxResourceBinding{ 7, 0, L"r_input_motion_vectors" }, FfxResourceBinding{ 8, 0, L"r_input_color_jittered" }, diff --git a/servers/rendering/renderer_rd/effects/luminance.cpp b/servers/rendering/renderer_rd/effects/luminance.cpp index 3aa5f5706e..61b2248b5c 100644 --- a/servers/rendering/renderer_rd/effects/luminance.cpp +++ b/servers/rendering/renderer_rd/effects/luminance.cpp @@ -184,7 +184,7 @@ void Luminance::luminance_reduction(RID p_source_texture, const Size2i p_source_ RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, i == 0 ? p_source_texture : p_luminance_buffers->reduce[i - 1] })); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, luminance_reduce_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); if (final) { diff --git a/servers/rendering/renderer_rd/effects/resolve.cpp b/servers/rendering/renderer_rd/effects/resolve.cpp index 18671d06e1..feb0e6ed1e 100644 --- a/servers/rendering/renderer_rd/effects/resolve.cpp +++ b/servers/rendering/renderer_rd/effects/resolve.cpp @@ -54,7 +54,7 @@ Resolve::~Resolve() { resolve.shader.version_free(resolve.shader_version); } -void Resolve::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) { +void Resolve::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -93,10 +93,10 @@ void Resolve::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1); - RD::get_singleton()->compute_list_end(p_barrier); + RD::get_singleton()->compute_list_end(); } -void Resolve::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) { +void Resolve::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -126,5 +126,5 @@ void Resolve::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_scr RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1); - RD::get_singleton()->compute_list_end(p_barrier); + RD::get_singleton()->compute_list_end(); } diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h index fcc1021904..14477f90e4 100644 --- a/servers/rendering/renderer_rd/effects/resolve.h +++ b/servers/rendering/renderer_rd/effects/resolve.h @@ -65,8 +65,8 @@ public: Resolve(); ~Resolve(); - void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); - void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); + void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples); + void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples); }; } // namespace RendererRD diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 628edc0127..46fb0a75d6 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -525,7 +525,7 @@ void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uin RD::get_singleton()->compute_list_add_barrier(compute_list); RD::get_singleton()->draw_command_end_label(); - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->compute_list_end(); ss_effects.used_full_mips_last_frame = use_full_mips; ss_effects.used_half_size_last_frame = use_half_size; @@ -950,10 +950,10 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende RD::get_singleton()->draw_command_end_label(); // SSIL - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_TRANSFER); // Zeroing importance_map_load_counter depends on us. + RD::get_singleton()->compute_list_end(); int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier + RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero); } /* SSAO */ @@ -1332,10 +1332,10 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe RD::get_singleton()->draw_command_end_label(); // Interleave } RD::get_singleton()->draw_command_end_label(); //SSAO - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_TRANSFER); // Zeroing importance_map_load_counter depends on us. + RD::get_singleton()->compute_list_end(); int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier + RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero); } /* Screen Space Reflection */ @@ -1394,7 +1394,7 @@ void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffe scene_data.eye_offset[v][3] = 0.0; } - RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data); } uint32_t pipeline_specialization = 0; diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp index 48c6511408..ee0b6adb4d 100644 --- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp +++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp @@ -166,7 +166,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton RID shader = tonemap.shader.version_get_shader(tonemap.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass())); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_color), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp index 63c99facdd..41a6b2d622 100644 --- a/servers/rendering/renderer_rd/effects/vrs.cpp +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -82,7 +82,7 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>()); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>()); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); // RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant)); diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 7d4eb0e038..78ab6f3650 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -570,7 +570,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform); - RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms); if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) { Vector<RD::Uniform> uniforms; @@ -1069,8 +1069,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P uint32_t cluster_size = p_settings.cluster_builder->get_cluster_size(); params.cluster_shift = get_shift_from_power_of_2(cluster_size); - uint32_t cluster_screen_width = (p_settings.rb_size.x - 1) / cluster_size + 1; - uint32_t cluster_screen_height = (p_settings.rb_size.y - 1) / cluster_size + 1; + uint32_t cluster_screen_width = Math::division_round_up((uint32_t)p_settings.rb_size.x, cluster_size); + uint32_t cluster_screen_height = Math::division_round_up((uint32_t)p_settings.rb_size.y, cluster_size); params.max_cluster_element_count_div_32 = p_settings.max_cluster_elements / 32; params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32); params.cluster_width = cluster_screen_width; @@ -1086,7 +1086,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog"); RENDER_TIMESTAMP("Render Fog"); - RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms); RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -1140,7 +1140,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set, 0); RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1); - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); + RD::get_singleton()->compute_list_end(); RENDER_TIMESTAMP("< Volumetric Fog"); RD::get_singleton()->draw_command_end_label(); diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index dce8fadb63..6da828df45 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -583,7 +583,8 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re /* Buffers */ cascade.solid_cell_buffer = RD::get_singleton()->storage_buffer_create(sizeof(SDFGI::Cascade::SolidCell) * solid_cell_count); - cascade.solid_cell_dispatch_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4, Vector<uint8_t>(), RD::STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT); + cascade.solid_cell_dispatch_buffer_storage = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4, Vector<uint8_t>()); + cascade.solid_cell_dispatch_buffer_call = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4, Vector<uint8_t>(), RD::STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT); cascade.lights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(SDFGIShader::Light) * MAX(SDFGI::MAX_STATIC_LIGHTS, SDFGI::MAX_DYNAMIC_LIGHTS)); { Vector<RD::Uniform> uniforms; @@ -650,7 +651,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 10; - u.append_id(cascade.solid_cell_dispatch_buffer); + u.append_id(cascade.solid_cell_dispatch_buffer_storage); uniforms.push_back(u); } { @@ -698,7 +699,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 5; - u.append_id(cascade.solid_cell_dispatch_buffer); + u.append_id(cascade.solid_cell_dispatch_buffer_storage); uniforms.push_back(u); } { @@ -761,7 +762,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(cascade.solid_cell_dispatch_buffer); + u.append_id(cascade.solid_cell_dispatch_buffer_storage); uniforms.push_back(u); } { @@ -1129,7 +1130,8 @@ GI::SDFGI::~SDFGI() { RD::get_singleton()->free(c.light_aniso_0_tex); RD::get_singleton()->free(c.light_aniso_1_tex); RD::get_singleton()->free(c.sdf_tex); - RD::get_singleton()->free(c.solid_cell_dispatch_buffer); + RD::get_singleton()->free(c.solid_cell_dispatch_buffer_storage); + RD::get_singleton()->free(c.solid_cell_dispatch_buffer_call); RD::get_singleton()->free(c.solid_cell_buffer); RD::get_singleton()->free(c.lightprobe_history_tex); RD::get_singleton()->free(c.lightprobe_average_tex); @@ -1238,6 +1240,10 @@ void GI::SDFGI::update(RID p_env, const Vector3 &p_world_position) { void GI::SDFGI::update_light() { RD::get_singleton()->draw_command_begin_label("SDFGI Update dynamic Light"); + for (uint32_t i = 0; i < cascades.size(); i++) { + RD::get_singleton()->buffer_copy(cascades[i].solid_cell_dispatch_buffer_storage, cascades[i].solid_cell_dispatch_buffer_call, 0, 0, sizeof(uint32_t) * 4); + } + /* Update dynamic light */ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -1276,9 +1282,9 @@ void GI::SDFGI::update_light() { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_dynamic_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DirectLightPushConstant)); - RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0); + RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer_call, 0); } - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->compute_list_end(); RD::get_singleton()->draw_command_end_label(); } @@ -1351,7 +1357,7 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) { render_pass++; - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true); + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_PROCESS]); int32_t probe_divisor = cascade_size / SDFGI::PROBE_DIVISOR; @@ -1368,14 +1374,11 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) { RD::get_singleton()->compute_list_dispatch_threads(compute_list, probe_axis_count * probe_axis_count, probe_axis_count, 1); } - //end later after raster to avoid barriering on layout changes - //RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); - + RD::get_singleton()->compute_list_end(); RD::get_singleton()->draw_command_end_label(); } void GI::SDFGI::store_probes() { - RD::get_singleton()->barrier(RD::BARRIER_MASK_COMPUTE, RD::BARRIER_MASK_COMPUTE); RD::get_singleton()->draw_command_begin_label("SDFGI Store Probes"); SDFGIShader::IntegratePushConstant push_constant; @@ -1414,7 +1417,7 @@ void GI::SDFGI::store_probes() { RD::get_singleton()->compute_list_dispatch_threads(compute_list, probe_axis_count * probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, 1); } - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->compute_list_end(); RD::get_singleton()->draw_command_end_label(); } @@ -1493,7 +1496,7 @@ void GI::SDFGI::update_cascades() { cascade_data[i].pad = 0; } - RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data); } void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) { @@ -1636,7 +1639,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2i(Point2i(), rtsize), true, false, false, false, RID(), p_view_count > 1); } -void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { +void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); // setup scene data @@ -1651,7 +1654,7 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con RendererRD::MaterialStorage::store_camera(p_camera_with_transforms[v], scene_data.projection[v]); } - RD::get_singleton()->buffer_update(debug_probes_scene_data_ubo, 0, sizeof(SDFGIShader::DebugProbesSceneData), &scene_data, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(debug_probes_scene_data_ubo, 0, sizeof(SDFGIShader::DebugProbesSceneData), &scene_data); } // setup push constant @@ -1718,7 +1721,7 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con SDFGIShader::ProbeDebugMode mode = p_view_count > 1 ? SDFGIShader::PROBE_DEBUG_PROBES_MULTIVIEW : SDFGIShader::PROBE_DEBUG_PROBES; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CONTINUE, p_will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); RD::get_singleton()->draw_command_begin_label("Debug SDFGI"); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, gi->sdfgi_shader.debug_probes_pipeline[mode].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); @@ -1861,7 +1864,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r } } - RD::get_singleton()->buffer_update(gi->sdfgi_ubo, 0, sizeof(SDFGIData), &sdfgi_data, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(gi->sdfgi_ubo, 0, sizeof(SDFGIData), &sdfgi_data); /* Update dynamic lights in SDFGI cascades */ @@ -1983,7 +1986,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r } if (idx > 0) { - RD::get_singleton()->buffer_update(cascade.lights_buffer, 0, idx * sizeof(SDFGIShader::Light), lights, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(cascade.lights_buffer, 0, idx * sizeof(SDFGIShader::Light), lights); } cascade_dynamic_light_count[i] = idx; @@ -2046,6 +2049,8 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_ push_constant.cascade = cascade; if (cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) { + RD::get_singleton()->buffer_copy(cascades[cascade].solid_cell_dispatch_buffer_storage, cascades[cascade].solid_cell_dispatch_buffer_call, 0, 0, sizeof(uint32_t) * 4); + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); //must pre scroll existing data because not all is dirty @@ -2053,7 +2058,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].scroll_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant)); - RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascades[cascade].solid_cell_dispatch_buffer, 0); + RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascades[cascade].solid_cell_dispatch_buffer_call, 0); // no barrier do all together RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_SCROLL_OCCLUSION]); @@ -2142,7 +2147,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_ //clear dispatch indirect data uint32_t dispatch_indirct_data[4] = { 0, 0, 0, 0 }; - RD::get_singleton()->buffer_update(cascades[cascade].solid_cell_dispatch_buffer, 0, sizeof(uint32_t) * 4, dispatch_indirct_data); + RD::get_singleton()->buffer_update(cascades[cascade].solid_cell_dispatch_buffer_storage, 0, sizeof(uint32_t) * 4, dispatch_indirct_data); RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -2451,6 +2456,15 @@ void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderScen } } + for (uint32_t i = 0; i < p_cascade_count; i++) { + ERR_CONTINUE(p_cascade_indices[i] >= cascades.size()); + + SDFGI::Cascade &cc = cascades[p_cascade_indices[i]]; + if (light_count[i] > 0) { + RD::get_singleton()->buffer_copy(cc.solid_cell_dispatch_buffer_storage, cc.solid_cell_dispatch_buffer_call, 0, 0, sizeof(uint32_t) * 4); + } + } + /* Static Lights */ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -2482,7 +2496,7 @@ void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderScen if (dl_push_constant.light_count > 0) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_static_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDFGIShader::DirectLightPushConstant)); - RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0); + RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer_call, 0); } } @@ -3143,7 +3157,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[0].uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant)); - RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1); + RD::get_singleton()->compute_list_dispatch(compute_list, Math::division_round_up(rect.size.x, 8), Math::division_round_up(rect.size.y, 8), 1); //print_line("rect: " + itos(i) + ": " + rect); for (int k = 1; k < dynamic_maps.size(); k++) { @@ -3205,7 +3219,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID } RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[k].uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant)); - RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1); + RD::get_singleton()->compute_list_dispatch(compute_list, Math::division_round_up(rect.size.x, 8), Math::division_round_up(rect.size.y, 8), 1); } RD::get_singleton()->compute_list_end(); @@ -3716,7 +3730,7 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBu if (p_voxel_gi_instances.size() > 0) { RD::get_singleton()->draw_command_begin_label("VoxelGIs Setup"); - RD::get_singleton()->buffer_update(voxel_gi_buffer, 0, sizeof(VoxelGIData) * MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()), voxel_gi_data, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(voxel_gi_buffer, 0, sizeof(VoxelGIData) * MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()), voxel_gi_data); RD::get_singleton()->draw_command_end_label(); } @@ -3804,11 +3818,11 @@ void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_nor scene_data.screen_size[0] = internal_size.x; scene_data.screen_size[1] = internal_size.y; - RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data); } // Now compute the contents of our buffers. - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true); + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); // Render each eye separately. // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference.. @@ -4038,8 +4052,7 @@ void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_nor } } - //do barrier later to allow oeverlap - //RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time + RD::get_singleton()->compute_list_end(); RD::get_singleton()->draw_command_end_label(); } diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index c46d4cbd25..011493f1f6 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -584,7 +584,9 @@ public: uint32_t static_light_aniso; }; - RID solid_cell_dispatch_buffer; //buffer for indirect compute dispatch + // Buffers for indirect compute dispatch. + RID solid_cell_dispatch_buffer_storage; + RID solid_cell_dispatch_buffer_call; RID solid_cell_buffer; RID lightprobe_history_tex; @@ -686,7 +688,7 @@ public: void update_cascades(); void debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views); - void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); + void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms); void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data); void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index ba72ab3b08..41609dc74d 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -1307,7 +1307,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd, p_render_buffers); - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } @@ -1328,7 +1328,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd, p_render_buffers); - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } @@ -1345,7 +1345,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd, p_render_buffers); - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } @@ -1469,7 +1469,7 @@ void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); _render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } @@ -1488,7 +1488,7 @@ void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); _render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 14995d0156..0c0062662a 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -576,31 +576,13 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis } } -void RenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { - uint32_t render_total = p_params->element_count; - uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); - uint32_t render_from = p_thread * render_total / total_threads; - uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads); - _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); -} - -void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { +void RenderForwardClustered::_render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer); p_params->framebuffer_format = fb_format; - if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time - //multi threaded - thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); - RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardClustered::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardClusteredRenderList")); - WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); - RD::get_singleton()->draw_list_end(p_params->barrier); - } else { - //single threaded - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - _render_list(draw_list, fb_format, p_params, 0, p_params->element_count); - RD::get_singleton()->draw_list_end(p_params->barrier); - } + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region); + _render_list(draw_list, fb_format, p_params, 0, p_params->element_count); + RD::get_singleton()->draw_list_end(); } void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier, bool p_pancake_shadows, int p_index) { @@ -626,8 +608,8 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.cluster_shift = get_shift_from_power_of_2(p_render_data->cluster_size); scene_state.ubo.max_cluster_element_count_div_32 = p_render_data->cluster_max_elements / 32; { - uint32_t cluster_screen_width = (p_screen_size.width - 1) / p_render_data->cluster_size + 1; - uint32_t cluster_screen_height = (p_screen_size.height - 1) / p_render_data->cluster_size + 1; + uint32_t cluster_screen_width = Math::division_round_up((uint32_t)p_screen_size.width, p_render_data->cluster_size); + uint32_t cluster_screen_height = Math::division_round_up((uint32_t)p_screen_size.height, p_render_data->cluster_size); scene_state.ubo.cluster_type_size = cluster_screen_width * cluster_screen_height * (scene_state.ubo.max_cluster_element_count_div_32 + 32); scene_state.ubo.cluster_width = cluster_screen_width; } @@ -683,7 +665,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat } } - RD::get_singleton()->buffer_update(scene_state.implementation_uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(scene_state.implementation_uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo); } void RenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) { @@ -696,7 +678,7 @@ void RenderForwardClustered::_update_instance_data_buffer(RenderListType p_rende scene_state.instance_buffer[p_render_list] = RD::get_singleton()->storage_buffer_create(new_size * sizeof(SceneState::InstanceData)); scene_state.instance_buffer_size[p_render_list] = new_size; } - RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr(), RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr()); } } void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, int *p_render_info, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) { @@ -961,13 +943,17 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con inst->gi_offset_cache = 0xFFFFFFFF; } } - - if (p_pass_mode == PASS_MODE_COLOR && p_using_motion_pass) { + if (p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI || p_pass_mode == PASS_MODE_COLOR) { bool transform_changed = inst->prev_transform_change_frame == frame; bool has_mesh_instance = inst->mesh_instance.is_valid(); bool uses_particles = inst->base_flags & INSTANCE_DATA_FLAG_PARTICLES; bool is_multimesh_with_motion = !uses_particles && (inst->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) && mesh_storage->_multimesh_uses_motion_vectors_offsets(inst->data->base); - uses_motion = transform_changed || has_mesh_instance || uses_particles || is_multimesh_with_motion; + bool is_dynamic = transform_changed || has_mesh_instance || uses_particles || is_multimesh_with_motion; + if (p_pass_mode == PASS_MODE_COLOR && p_using_motion_pass) { + uses_motion = is_dynamic; + } else if (is_dynamic) { + flags |= INSTANCE_DATA_FLAGS_DYNAMIC; + } } } inst->flags_cache = flags; @@ -1093,7 +1079,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } if (p_render_list == RENDER_LIST_OPAQUE && lightmap_captures_used) { - RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures); } } @@ -1131,7 +1117,7 @@ void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data, scene_state.lightmaps_used++; } if (scene_state.lightmaps_used > 0) { - RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps); } } @@ -1423,7 +1409,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo if (p_render_data->directional_shadows.size()) { //open the pass for directional shadows light_storage->update_directional_shadow_atlas(); - RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE); + RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE); RD::get_singleton()->draw_list_end(); } } @@ -1457,18 +1443,12 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo _render_shadow_process(); } - //start GI if (render_gi) { gi.process_gi(rb, p_normal_roughness_slices, p_voxel_gi_buffer, p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances); } - //Do shadow rendering (in parallel with GI) if (render_shadows) { - _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER); - } - - if (render_gi) { - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier + _render_shadow_end(); } if (rb_data.is_valid() && ss_effects) { @@ -1492,9 +1472,6 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo } } - //full barrier here, we need raster, transfer and compute and it depends from the previous work - RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL_BARRIERS, RD::BARRIER_MASK_ALL_BARRIERS); - if (current_cluster_builder) { // Note: when rendering stereoscopic (multiview) we are using our combined frustum projection to create // our cluster data. We use reprojection in the shader to adjust for our left/right eye. @@ -1779,11 +1756,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS); - depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + depth_pass_clear.push_back(Color(0, 0, 0, 0)); } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS_VOXELGI); - depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + depth_pass_clear.push_back(Color(0, 0, 0, 0)); depth_pass_clear.push_back(Color(0, 0, 0, 0)); } break; default: { @@ -1810,7 +1787,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co float sky_energy_multiplier = 1.0 / _render_buffers_get_luminance_multiplier(); Color clear_color; - bool keep_color = false; + bool load_color = false; if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black @@ -1853,10 +1830,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool convert_to_linear = !RendererRD::TextureStorage::get_singleton()->render_target_is_using_hdr(rb->get_render_target()); copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, convert_to_linear); } - keep_color = true; + load_color = true; } break; case RS::ENV_BG_KEEP: { - keep_color = true; + load_color = true; } break; case RS::ENV_BG_CAMERA_FEED: { } break; @@ -1908,7 +1885,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid(); bool using_ssao = depth_pre_pass && !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); - bool continue_depth = false; if (depth_pre_pass) { //depth pre pass bool needs_pre_resolve = _needs_post_prepass_render(p_render_data, using_sdfgi || using_voxelgi); @@ -1919,7 +1895,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } if (needs_pre_resolve) { //pre clear the depth framebuffer, as AMD (and maybe others?) use compute for it, and barrier other compute shaders. - RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear); + RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, depth_pass_clear); RD::get_singleton()->draw_list_end(); //start compute processes here, so they run at the same time as depth pre-pass _post_prepass_render(p_render_data, using_sdfgi || using_voxelgi); @@ -1931,21 +1907,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool finish_depth = using_ssao || using_ssil || using_sdfgi || using_voxelgi; RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); - _render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear); + _render_list_with_draw_list(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear); RD::get_singleton()->draw_command_end_label(); - if (needs_pre_resolve) { - _pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi); - } - if (rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)"); RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)"); if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) { - if (needs_pre_resolve) { - RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE); - } for (uint32_t v = 0; v < rb->get_view_count(); v++) { resolve_effects->resolve_gi(rb->get_depth_msaa(v), rb_data->get_normal_roughness_msaa(v), using_voxelgi ? rb_data->get_voxelgi_msaa(v) : RID(), rb->get_depth_texture(v), rb_data->get_normal_roughness(v), using_voxelgi ? rb_data->get_voxelgi(v) : RID(), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); } @@ -1956,8 +1925,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } RD::get_singleton()->draw_command_end_label(); } - - continue_depth = !finish_depth; } RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS]; @@ -1986,10 +1953,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co { bool render_motion_pass = !render_list[RENDER_LIST_MOTION].elements.is_empty(); - bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); - bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); - RD::FinalAction final_color_action = will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ; - RD::FinalAction final_depth_action = will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ; { Vector<Color> c; @@ -2010,7 +1973,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co uint32_t opaque_color_pass_flags = using_motion_pass ? (color_pass_flags & ~COLOR_PASS_FLAG_MOTION_VECTORS) : color_pass_flags; RID opaque_framebuffer = using_motion_pass ? rb_data->get_color_pass_fb(opaque_color_pass_flags) : color_framebuffer; RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, opaque_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); - _render_list_with_threads(&render_list_params, opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, render_motion_pass ? RD::FINAL_ACTION_CONTINUE : final_color_action, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, render_motion_pass ? RD::FINAL_ACTION_CONTINUE : final_depth_action, c, 1.0, 0); + _render_list_with_draw_list(&render_list_params, opaque_framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, depth_pre_pass ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 1.0, 0); } RD::get_singleton()->draw_command_end_label(); @@ -2018,7 +1981,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_motion_pass) { Vector<Color> motion_vector_clear_colors; motion_vector_clear_colors.push_back(Color(-1, -1, 0, 0)); - RD::get_singleton()->draw_list_begin(rb_data->get_velocity_only_fb(), RD::INITIAL_ACTION_CLEAR, render_motion_pass ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE, motion_vector_clear_colors); + RD::get_singleton()->draw_list_begin(rb_data->get_velocity_only_fb(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, motion_vector_clear_colors); RD::get_singleton()->draw_list_end(); } @@ -2030,33 +1993,17 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_MOTION, p_render_data, radiance_texture, samplers, true); RenderListParameters render_list_params(render_list[RENDER_LIST_MOTION].elements.ptr(), render_list[RENDER_LIST_MOTION].element_info.ptr(), render_list[RENDER_LIST_MOTION].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); - _render_list_with_threads(&render_list_params, color_framebuffer, RD::INITIAL_ACTION_CONTINUE, final_color_action, RD::INITIAL_ACTION_CONTINUE, final_depth_action); + _render_list_with_draw_list(&render_list_params, color_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); RD::get_singleton()->draw_command_end_label(); - - if (will_continue_color) { - // Close the motion vectors framebuffer as it'll no longer be used. - RD::get_singleton()->draw_list_begin(rb_data->get_velocity_only_fb(), RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); - RD::get_singleton()->draw_list_end(); - } - } - - if (will_continue_color && using_separate_specular) { - // Close the specular framebuffer as it'll no longer be used. - RD::get_singleton()->draw_list_begin(rb_data->get_specular_only_fb(), RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); - RD::get_singleton()->draw_list_end(); } } if (debug_voxelgis) { - //debug voxelgis - bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); - bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); - Projection dc; dc.set_depth_correction(true); Projection cm = (dc * p_render_data->scene_data->cam_projection) * Projection(p_render_data->scene_data->cam_transform.affine_inverse()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs"); for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) { gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, color_only_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0); @@ -2066,24 +2013,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } if (debug_sdfgi_probes) { - //debug sdfgi - bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); - bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); - Projection dc; dc.set_depth_correction(true); Projection cms[RendererSceneRender::MAX_RENDER_VIEWS]; for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) { cms[v] = (dc * p_render_data->scene_data->view_projection[v]) * Projection(p_render_data->scene_data->cam_transform.affine_inverse()); } - _debug_sdfgi_probes(rb, color_only_framebuffer, p_render_data->scene_data->view_count, cms, will_continue_color, will_continue_depth); + _debug_sdfgi_probes(rb, color_only_framebuffer, p_render_data->scene_data->view_count, cms); } if (draw_sky || draw_sky_fog_only) { RENDER_TIMESTAMP("Render Sky"); RD::get_singleton()->draw_command_begin_label("Draw Sky"); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); sky.draw_sky(draw_list, rb, p_render_data->environment, color_only_framebuffer, time, sky_energy_multiplier); @@ -2142,7 +2085,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Clear Separate Specular (Canvas Background Mode)"); Vector<Color> blank_clear_color; blank_clear_color.push_back(Color(0.0, 0.0, 0.0)); - RD::get_singleton()->draw_list_begin(rb_data->get_specular_only_fb(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, blank_clear_color); + RD::get_singleton()->draw_list_begin(rb_data->get_specular_only_fb(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, blank_clear_color); RD::get_singleton()->draw_list_end(); } @@ -2183,7 +2126,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RID alpha_framebuffer = rb_data.is_valid() ? rb_data->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer; RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); - _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); + _render_list_with_draw_list(&render_list_params, alpha_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); } RD::get_singleton()->draw_command_end_label(); @@ -2222,7 +2165,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co exposure = luminance->get_current_luminance_buffer(rb); } + RD::get_singleton()->draw_command_begin_label("FSR2"); RENDER_TIMESTAMP("FSR2"); + for (uint32_t v = 0; v < rb->get_view_count(); v++) { real_t fov = p_render_data->scene_data->cam_projection.get_fov(); real_t aspect = p_render_data->scene_data->cam_projection.get_aspect(); @@ -2253,9 +2198,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co fsr2_effect->upscale(params); } + + RD::get_singleton()->draw_command_end_label(); } else if (using_taa) { + RD::get_singleton()->draw_command_begin_label("TAA"); RENDER_TIMESTAMP("TAA"); taa->process(rb, _render_buffers_get_color_format(), p_render_data->scene_data->z_near, p_render_data->scene_data->z_far); + RD::get_singleton()->draw_command_end_label(); } } @@ -2567,8 +2516,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier; shadow_pass.framebuffer = p_framebuffer; - shadow_pass.initial_depth_action = p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE : RD::INITIAL_ACTION_CONTINUE); - shadow_pass.final_depth_action = p_end ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE; + shadow_pass.initial_depth_action = p_begin ? RD::INITIAL_ACTION_CLEAR : (p_clear_region ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD); shadow_pass.rect = p_rect; scene_state.shadow_passes.push_back(shadow_pass); @@ -2587,17 +2535,14 @@ void RenderForwardClustered::_render_shadow_process() { RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { +void RenderForwardClustered::_render_shadow_end() { RD::get_singleton()->draw_command_begin_label("Shadow Render"); for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) { - RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); - _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect); + RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from); + _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, RD::FINAL_ACTION_STORE, Vector<Color>(), 1.0, 0, shadow_pass.rect); } - if (p_barrier != RD::BARRIER_MASK_NO_BARRIER) { - RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, p_barrier); - } RD::get_singleton()->draw_command_end_label(); } @@ -2640,7 +2585,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con { //regular forward for now RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, rp_uniform_set); - _render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); + _render_list_with_draw_list(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE); } RD::get_singleton()->draw_command_end_label(); } @@ -2693,7 +2638,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform Color(0, 0, 0, 0) }; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 1.0, 0, p_region); _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); RD::get_singleton()->draw_list_end(); } @@ -2743,7 +2688,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance Color(0, 0, 0, 0), Color(0, 0, 0, 0) }; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 1.0, 0, p_region); const int uv_offset_count = 9; static const Vector2 uv_offsets[uv_offset_count] = { @@ -2799,13 +2744,6 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu Vector3 half_size = p_bounds.size * 0.5; Vector3 center = p_bounds.position + half_size; - Vector<RID> sbs = { - p_albedo_texture, - p_emission_texture, - p_emission_aniso_texture, - p_geom_facing_texture - }; - //print_line("re-render " + p_from + " - " + p_size + " bounds " + p_bounds); for (int i = 0; i < 3; i++) { scene_state.ubo.sdf_offset[i] = p_from[i]; @@ -2856,7 +2794,7 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu } RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false); - _render_list_with_threads(&render_list_params, E->value, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); + _render_list_with_draw_list(&render_list_params, E->value, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2()); } RD::get_singleton()->draw_command_end_label(); @@ -2980,6 +2918,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() { uniforms.push_back(u); } + { + RD::Uniform u; + u.binding = 15; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.append_id(best_fit_normal.texture); + uniforms.push_back(u); + } + render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET); } } @@ -4230,7 +4176,43 @@ RenderForwardClustered::RenderForwardClustered() { shadow_sampler = RD::get_singleton()->sampler_create(sampler); } - render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances"); + { + Vector<String> modes; + modes.push_back("\n"); + best_fit_normal.shader.initialize(modes); + best_fit_normal.shader_version = best_fit_normal.shader.version_create(); + best_fit_normal.pipeline = RD::get_singleton()->compute_pipeline_create(best_fit_normal.shader.version_get_shader(best_fit_normal.shader_version, 0)); + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8_UNORM; + tformat.width = 1024; + tformat.height = 1024; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D; + best_fit_normal.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView()); + + RID shader = best_fit_normal.shader.version_get_shader(best_fit_normal.shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.append_id(best_fit_normal.texture); + uniforms.push_back(u); + } + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, best_fit_normal.pipeline); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, tformat.width, tformat.height, 1); + RD::get_singleton()->compute_list_end(); + + best_fit_normal.shader.version_free(best_fit_normal.shader_version); + } _update_shader_quality_settings(); @@ -4263,6 +4245,7 @@ RenderForwardClustered::~RenderForwardClustered() { RD::get_singleton()->free(shadow_sampler); RSG::light_storage->directional_shadow_atlas_set_size(0); + RD::get_singleton()->free(best_fit_normal.texture); { for (const RID &rid : scene_state.uniform_buffers) { diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 8119e6ff4d..5af213bc02 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -40,6 +40,7 @@ #include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" +#include "servers/rendering/renderer_rd/shaders/forward_clustered/best_fit_normal.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/utilities.h" @@ -164,6 +165,13 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture, const RendererRD::MaterialStorage::Samplers &p_samplers); RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, const RendererRD::MaterialStorage::Samplers &p_samplers, bool p_use_directional_shadow_atlas = false, int p_index = 0); + struct BestFitNormal { + BestFitNormalShaderRD shader; + RID shader_version; + RID pipeline; + RID texture; + } best_fit_normal; + enum PassMode { PASS_MODE_COLOR, PASS_MODE_SHADOW, @@ -201,10 +209,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { float screen_mesh_lod_threshold = 0.0; RD::FramebufferFormatID framebuffer_format = 0; uint32_t element_offset = 0; - uint32_t barrier = RD::BARRIER_MASK_ALL_BARRIERS; bool use_directional_soft_shadow = false; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; @@ -219,7 +226,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { lod_distance_multiplier = p_lod_distance_multiplier; screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; element_offset = p_element_offset; - barrier = p_barrier; use_directional_soft_shadow = p_use_directional_soft_shadows; } }; @@ -236,6 +242,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { // When changing any of these enums, remember to change the corresponding enums in the shader files as well. enum { + INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3, INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4, INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5, INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 6, @@ -343,7 +350,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID framebuffer; RD::InitialAction initial_depth_action; - RD::FinalAction final_depth_action; Rect2i rect; }; @@ -369,14 +375,8 @@ class RenderForwardClustered : public RendererSceneRenderRD { template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0> _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); - void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); - - LocalVector<RD::DrawListID> thread_draw_lists; - void _render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params); - void _render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); - - uint32_t render_list_thread_threshold = 500; + void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); void _update_instance_data_buffer(RenderListType p_render_list); void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); @@ -595,7 +595,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _render_shadow_begin(); void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1)); void _render_shadow_process(); - void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); + void _render_shadow_end(); /* Render Scene */ void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index bba1f62023..86852ce020 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -446,7 +446,7 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) { bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; - return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, true, RD::BARRIER_MASK_RASTER); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, true); } SceneShaderForwardClustered::MaterialData::~MaterialData() { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index b7d7105daa..da04e6f938 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -596,7 +596,7 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co scene_state.lightmaps_used++; } if (scene_state.lightmaps_used > 0) { - RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps); } } @@ -631,7 +631,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { if (p_render_data->directional_shadows.size()) { //open the pass for directional shadows light_storage->update_directional_shadow_atlas(); - RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE); + RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE); RD::get_singleton()->draw_list_end(); } } @@ -655,11 +655,8 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { _render_shadow_process(); - _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER); + _render_shadow_end(); } - - //full barrier here, we need raster, transfer and compute and it depends from the previous work - RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL_BARRIERS, RD::BARRIER_MASK_ALL_BARRIERS); } void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { @@ -811,7 +808,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color float sky_energy_multiplier = inverse_luminance_multiplier; Color clear_color = p_default_bg_color; - bool keep_color = false; + bool load_color = false; bool copy_canvas = false; if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { @@ -855,7 +852,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } } break; case RS::ENV_BG_KEEP: { - keep_color = true; + load_color = true; } break; case RS::ENV_BG_CAMERA_FEED: { } break; @@ -955,6 +952,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (rb_data.is_valid()) { cc.a = 0; // For transparent viewport backgrounds. } + c.push_back(cc); // Our render buffer. if (rb_data.is_valid()) { if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { @@ -966,7 +964,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } } - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, merge_transparent_pass ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, merge_transparent_pass ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, c, 1.0, 0); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 1.0, 0); RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); if (copy_canvas) { @@ -1026,12 +1024,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS); + RD::get_singleton()->draw_list_end(); } else { // We're done with our subpasses so end our container pass // note, if MSAA is used we should get an automatic resolve here - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS); + RD::get_singleton()->draw_list_end(); RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass @@ -1062,9 +1060,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color render_list_params.framebuffer_format = fb_format; render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass(); // Should now always be 0. - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); _render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count); - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS); + RD::get_singleton()->draw_list_end(); RD::get_singleton()->draw_command_end_label(); // Render Transparent Pass } @@ -1248,15 +1246,15 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info); if (finalize_cubemap) { _render_shadow_process(); - _render_shadow_end(RD::BARRIER_MASK_FRAGMENT); + _render_shadow_end(); // reblit Rect2 atlas_rect_norm = atlas_rect; atlas_rect_norm.position /= float(atlas_size); atlas_rect_norm.size /= float(atlas_size); - copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false, RD::BARRIER_MASK_NO_BARRIER); + copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false); atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size; - copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true, RD::BARRIER_MASK_NO_BARRIER); + copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true); //restore transform so it can be properly used light_storage->light_instance_set_shadow_transform(p_light, Projection(), light_storage->light_instance_get_base_transform(p_light), zfar, 0, 0, 0); @@ -1337,8 +1335,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier; shadow_pass.framebuffer = p_framebuffer; - shadow_pass.initial_depth_action = p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE : RD::INITIAL_ACTION_CONTINUE); - shadow_pass.final_depth_action = p_end ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE; + shadow_pass.initial_depth_action = p_begin ? RD::INITIAL_ACTION_CLEAR : (p_clear_region ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD); shadow_pass.rect = p_rect; scene_state.shadow_passes.push_back(shadow_pass); @@ -1357,17 +1354,14 @@ void RenderForwardMobile::_render_shadow_process() { RD::get_singleton()->draw_command_end_label(); } -void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) { +void RenderForwardMobile::_render_shadow_end() { RD::get_singleton()->draw_command_begin_label("Shadow Render"); for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) { - RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); - _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect); + RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from); + _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, RD::FINAL_ACTION_STORE, Vector<Color>(), 1.0, 0, shadow_pass.rect); } - if (p_barrier != RD::BARRIER_MASK_NO_BARRIER) { - RD::get_singleton()->barrier(RD::BARRIER_MASK_FRAGMENT, p_barrier); - } RD::get_singleton()->draw_command_end_label(); } @@ -1416,7 +1410,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c Color(0, 0, 0, 0), Color(0, 0, 0, 0) }; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 1.0, 0, p_region); _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); RD::get_singleton()->draw_list_end(); } @@ -1462,7 +1456,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> Color(0, 0, 0, 0) }; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 1.0, 0, p_region); const int uv_offset_count = 9; static const Vector2 uv_offsets[uv_offset_count] = { @@ -1535,7 +1529,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const { //regular forward for now RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, rp_uniform_set, 0); - _render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); + _render_list_with_draw_list(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE); } RD::get_singleton()->draw_command_end_label(); } @@ -1672,7 +1666,7 @@ void RenderForwardMobile::_update_instance_data_buffer(RenderListType p_render_l scene_state.instance_buffer[p_render_list] = RD::get_singleton()->storage_buffer_create(new_size * sizeof(SceneState::InstanceData)); scene_state.instance_buffer_size[p_render_list] = new_size; } - RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr(), RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr()); } } @@ -1991,32 +1985,13 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list, } } -void RenderForwardMobile::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { - uint32_t render_total = p_params->element_count; - uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); - uint32_t render_from = p_thread * render_total / total_threads; - uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads); - _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); -} - -void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { +void RenderForwardMobile::_render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer); p_params->framebuffer_format = fb_format; - if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time - //multi threaded - thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); - RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass")); - WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); - - RD::get_singleton()->draw_list_end(p_params->barrier); - } else { - //single threaded - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - _render_list(draw_list, fb_format, p_params, 0, p_params->element_count); - RD::get_singleton()->draw_list_end(p_params->barrier); - } + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region); + _render_list(draw_list, fb_format, p_params, 0, p_params->element_count); + RD::get_singleton()->draw_list_end(); } template <RenderForwardMobile::PassMode p_pass_mode> @@ -2813,9 +2788,6 @@ RenderForwardMobile::RenderForwardMobile() { scene_shader.init(defines); - // !BAS! maybe we need a mobile version of this setting? - render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances"); - _update_shader_quality_settings(); } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 3496495245..f1f6bb3db4 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -155,10 +155,9 @@ private: float screen_mesh_lod_threshold = 0.0; RD::FramebufferFormatID framebuffer_format = 0; uint32_t element_offset = 0; - uint32_t barrier = RD::BARRIER_MASK_ALL_BARRIERS; uint32_t subpass = 0; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; @@ -172,7 +171,6 @@ private: lod_distance_multiplier = p_lod_distance_multiplier; screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; element_offset = p_element_offset; - barrier = p_barrier; spec_constant_base_flags = p_spec_constant_base_flags; } }; @@ -183,7 +181,7 @@ private: void _render_shadow_begin(); void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr); void _render_shadow_process(); - void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); + void _render_shadow_end(); /* Render Scene */ @@ -277,7 +275,6 @@ private: RID framebuffer; RD::InitialAction initial_depth_action; - RD::FinalAction final_depth_action; Rect2i rect; }; @@ -351,14 +348,8 @@ private: template <PassMode p_pass_mode> _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); - void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); - - LocalVector<RD::DrawListID> thread_draw_lists; - void _render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params); - void _render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); - - uint32_t render_list_thread_threshold = 500; + void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); RenderList render_list[RENDER_LIST_MAX]; @@ -386,6 +377,7 @@ protected: // When changing any of these enums, remember to change the corresponding enums in the shader files as well. enum { + INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3, INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4, INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5, INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 6, diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index f1cec0e07c..043cdbc8e5 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -398,7 +398,7 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) { bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton; - return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true, RD::BARRIER_MASK_RASTER); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true); } SceneShaderForwardMobile::MaterialData::~MaterialData() { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 657628111a..283b3ee09a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1177,7 +1177,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, fb_uniform_set, BASE_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET); @@ -1721,8 +1721,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); - RD::InitialAction initial_action = i == 0 ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, initial_action, i != 3 ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, initial_action, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); Projection projection; { @@ -1811,7 +1810,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh cc.push_back(Color(1, 1, 1, 1)); Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); Projection projection; projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance); @@ -1881,7 +1880,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan Vector<Color> cc; cc.push_back(Color(0, 0, 0, 0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc); Projection projection; @@ -2371,8 +2370,8 @@ RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_ bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); - bool uniform_set_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, true, false, RD::BARRIER_MASK_ALL_BARRIERS); - bool uniform_set_srgb_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set_srgb, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false, false, RD::BARRIER_MASK_ALL_BARRIERS); + bool uniform_set_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, true, false); + bool uniform_set_srgb_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set_srgb, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false, false); return uniform_set_changed || uniform_set_srgb_changed; } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 705fb9e8e5..9b073821c2 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -123,6 +123,7 @@ public: void prepare_for_blitting_render_targets(); void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount); + void end_viewport(bool p_swap_buffers) {} void end_frame(bool p_swap_buffers); void finalize(); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index d4ed640247..3b05431f4a 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -220,7 +220,7 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects); } -void RendererSceneRenderRD::_debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { +void RendererSceneRenderRD::_debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms) { ERR_FAIL_COND(p_render_buffers.is_null()); if (!p_render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { @@ -229,7 +229,7 @@ void RendererSceneRenderRD::_debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_rend Ref<RendererRD::GI::SDFGI> sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI); - sdfgi->debug_probes(p_framebuffer, p_view_count, p_camera_with_transforms, p_will_continue_color, p_will_continue_depth); + sdfgi->debug_probes(p_framebuffer, p_view_count, p_camera_with_transforms); } //////////////////////////////// @@ -773,7 +773,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(const RenderDataRD *p_ren if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(rb).is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(rb), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); + copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(rb), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false, false, false, RID(), false, false, false, true); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { @@ -987,14 +987,6 @@ void RendererSceneRenderRD::_post_prepass_render(RenderDataRD *p_render_data, bo } } -void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi) { - if (p_render_data->render_buffers.is_valid()) { - if (p_use_gi) { - RD::get_singleton()->compute_list_end(); - } - } -} - void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RenderingMethod::RenderInfo *r_render_info) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 211d191039..4811ae3b44 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -137,14 +137,13 @@ protected: virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0; - void _debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); + void _debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms); virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); - void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi); void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data); void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data); diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 2873269586..1c54ce5657 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -45,7 +45,7 @@ void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) { String text; for (int i = 0; i < lines.size(); i++) { - String l = lines[i]; + const String &l = lines[i]; bool push_chunk = false; StageTemplate::Chunk chunk; @@ -463,6 +463,7 @@ bool ShaderRD::_load_from_cache(Version *p_version, int p_group) { } void ShaderRD::_save_to_cache(Version *p_version, int p_group) { + ERR_FAIL_COND(!shader_cache_dir_valid); String sha1 = _version_get_sha1(p_version); String path = shader_cache_dir.path_join(name).path_join(group_sha256[p_group]).path_join(sha1) + ".cache"; diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 6137224162..1b065a8dd3 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl @@ -20,6 +20,7 @@ #define FLAG_SRGB (1 << 4) #define FLAG_ALPHA_TO_ONE (1 << 5) #define FLAG_LINEAR (1 << 6) +#define FLAG_NORMAL (1 << 7) #ifdef MULTIVIEW layout(location = 0) out vec3 uv_interp; @@ -77,6 +78,7 @@ void main() { #define FLAG_SRGB (1 << 4) #define FLAG_ALPHA_TO_ONE (1 << 5) #define FLAG_LINEAR (1 << 6) +#define FLAG_NORMAL (1 << 7) layout(push_constant, std430) uniform Params { vec4 section; @@ -192,6 +194,9 @@ void main() { if (bool(params.flags & FLAG_LINEAR)) { color.rgb = srgb_to_linear(color.rgb); } + if (bool(params.flags & FLAG_NORMAL)) { + color.rgb = normalize(color.rgb * 2.0 - 1.0) * 0.5 + 0.5; + } frag_color = color / params.luminance_multiplier; #endif // MODE_SET_COLOR diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub b/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub index f06a2d86e2..5b8bbc343b 100644 --- a/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub @@ -6,6 +6,11 @@ if "RD_GLSL" in env["BUILDERS"]: # find all include files gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")] + # Add all FSR2 shader and header files. + fsr2_dir = "#thirdparty/amd-fsr2/shaders" + gl_include_files += [str(f) for f in Glob(fsr2_dir + "/*.h")] + gl_include_files += [str(f) for f in Glob(fsr2_dir + "/*.glsl")] + # find all shader code(all glsl files excluding our include files) glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl index fecf70bd01..8618f083b3 100644 --- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl @@ -65,8 +65,12 @@ void main() { vec3 vertex = reconstructCSPosition(uv * vec2(params.screen_size), base_depth); vec4 normal_roughness = imageLoad(source_normal_roughness, ssC); - vec3 normal = normal_roughness.xyz * 2.0 - 1.0; + vec3 normal = normalize(normal_roughness.xyz * 2.0 - 1.0); float roughness = normal_roughness.w; + if (roughness > 0.5) { + roughness = 1.0 - roughness; + } + roughness /= (127.0 / 255.0); // The roughness cutoff of 0.6 is chosen to match the roughness fadeout from GH-69828. if (roughness > 0.6) { diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl index 4df74b8626..51caa67d3c 100644 --- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl @@ -59,8 +59,13 @@ void main() { color += texelFetch(source_ssr, ofs, 0); float d = texelFetch(source_depth, ofs, 0).r; vec4 nr = texelFetch(source_normal, ofs, 0); - normal.xyz += nr.xyz * 2.0 - 1.0; - normal.w += nr.w; + normal.xyz += normalize(nr.xyz * 2.0 - 1.0); + float roughness = normal.w; + if (roughness > 0.5) { + roughness = 1.0 - roughness; + } + roughness /= (127.0 / 255.0); + normal.w += roughness; if (sc_multiview) { // we're doing a full unproject so we need the value as is. @@ -81,6 +86,7 @@ void main() { depth /= 4.0; normal.xyz = normalize(normal.xyz / 4.0) * 0.5 + 0.5; normal.w /= 4.0; + normal.w = normal.w * (127.0 / 255.0); } else { ivec2 ofs = ssC << 1; diff --git a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl index db710b7cdd..e87f644bb0 100644 --- a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl @@ -30,7 +30,7 @@ void main() { vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0)); gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0); uv_interp.xy = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0 -#ifdef MULTIVIEW +#ifdef USE_MULTIVIEW uv_interp.z = ViewIndex; #endif } diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl index 58efc68bc7..8c50bb544d 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl @@ -158,21 +158,16 @@ vec4 calculate_edges(const float p_center_z, const float p_left_z, const float p return clamp((1.3 - edgesLRTB / (p_center_z * 0.040)), 0.0, 1.0); } -vec3 decode_normal(vec3 p_encoded_normal) { - vec3 normal = p_encoded_normal * 2.0 - 1.0; - return normal; -} - vec3 load_normal(ivec2 p_pos) { - vec3 encoded_normal = imageLoad(source_normal, p_pos).xyz; - encoded_normal.z = 1.0 - encoded_normal.z; - return decode_normal(encoded_normal); + vec3 encoded_normal = normalize(imageLoad(source_normal, p_pos).xyz * 2.0 - 1.0); + encoded_normal.z = -encoded_normal.z; + return encoded_normal; } vec3 load_normal(ivec2 p_pos, ivec2 p_offset) { - vec3 encoded_normal = imageLoad(source_normal, p_pos + p_offset).xyz; - encoded_normal.z = 1.0 - encoded_normal.z; - return decode_normal(encoded_normal); + vec3 encoded_normal = normalize(imageLoad(source_normal, p_pos + p_offset).xyz * 2.0 - 1.0); + encoded_normal.z = -encoded_normal.z; + return encoded_normal; } // all vectors in viewspace diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl index fac13b0e3f..0b623c1d4e 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl @@ -159,21 +159,16 @@ vec4 calculate_edges(const float p_center_z, const float p_left_z, const float p return clamp((1.3 - edgesLRTB / (p_center_z * 0.040)), 0.0, 1.0); } -vec3 decode_normal(vec3 p_encoded_normal) { - vec3 normal = p_encoded_normal * 2.0 - 1.0; - return normal; -} - vec3 load_normal(ivec2 p_pos) { - vec3 encoded_normal = imageLoad(source_normal, p_pos).xyz; - encoded_normal.z = 1.0 - encoded_normal.z; - return decode_normal(encoded_normal); + vec3 encoded_normal = normalize(imageLoad(source_normal, p_pos).xyz * 2.0 - 1.0); + encoded_normal.z = -encoded_normal.z; + return encoded_normal; } vec3 load_normal(ivec2 p_pos, ivec2 p_offset) { - vec3 encoded_normal = imageLoad(source_normal, p_pos + p_offset).xyz; - encoded_normal.z = 1.0 - encoded_normal.z; - return decode_normal(encoded_normal); + vec3 encoded_normal = normalize(imageLoad(source_normal, p_pos + p_offset).xyz * 2.0 - 1.0); + encoded_normal.z = -encoded_normal.z; + return encoded_normal; } // all vectors in viewspace diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl index 59af9501ba..80ed34cda1 100644 --- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl @@ -618,6 +618,11 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref if (normal.length() > 0.5) { //valid normal, can do GI float roughness = normal_roughness.w; + bool dynamic_object = roughness > 0.5; + if (dynamic_object) { + roughness = 1.0 - roughness; + } + roughness /= (127.0 / 255.0); vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[gl_GlobalInvocationID.z].xyz)); vertex = mat3(scene_data.cam_transform) * vertex; normal = normalize(mat3(scene_data.cam_transform) * normal); diff --git a/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl b/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl index 577c6d0cd0..6e9e0f82b3 100644 --- a/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl @@ -492,7 +492,7 @@ void main() { ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(z); - vec3 normal = imageLoad(source_normal, uv_xy).xyz * 2.0 - 1.0; + vec3 normal = normalize(imageLoad(source_normal, uv_xy).xyz * 2.0 - 1.0); normal = vec3(params.x_dir) * normal.x * mix(1.0, -1.0, params.flip_x) + vec3(params.y_dir) * normal.y * mix(1.0, -1.0, params.flip_y) - vec3(params.z_dir) * normal.z; vec4 albedo = imageLoad(source_albedo, uv_xy); diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/best_fit_normal.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/best_fit_normal.glsl new file mode 100644 index 0000000000..8280d192e3 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/best_fit_normal.glsl @@ -0,0 +1,43 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(r8, set = 0, binding = 0) uniform restrict writeonly image2D current_image; + +// This shader is used to generate a "best fit normal texture" as described by: +// https://advances.realtimerendering.com/s2010/Kaplanyan-CryEngine3(SIGGRAPH%202010%20Advanced%20RealTime%20Rendering%20Course).pdf +// This texture tells you what length of normal can be used to store a unit vector +// with the lest amount of error. + +vec3 quantize(vec3 c) { + return round(clamp(c * 0.5 + 0.5, 0.0, 1.0) * 255.0) * (1.0 / 255.0) * 2.0 - 1.0; +} + +float find_minimum_error(vec3 normal) { + float min_error = 100000.0; + float t_best = 0.0; + for (float nstep = 1.5; nstep < 127.5; ++nstep) { + float t = nstep / 127.5; + vec3 vp = normal * t; + vec3 quantizedp = quantize(vp); + vec3 vdiff = (quantizedp - vp) / t; + float error = max(abs(vdiff.x), max(abs(vdiff.y), abs(vdiff.z))); + if (error < min_error) { + min_error = error; + t_best = t; + } + } + return t_best; +} + +void main() { + vec2 uv = vec2(gl_GlobalInvocationID.xy) * vec2(1.0 / 1024.0) + vec2(0.5 / 1024.0); + uv.y *= uv.x; + + vec3 dir = vec3(uv.x, uv.y, 1.0); + imageStore(current_image, ivec2(gl_GlobalInvocationID.xy), vec4(find_minimum_error(dir), 1.0, 1.0, 1.0)); +} diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index e17fa0ce90..930d981494 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -868,6 +868,28 @@ uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) { #endif //!MODE_RENDER DEPTH +#if defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_MATERIAL) +// https://advances.realtimerendering.com/s2010/Kaplanyan-CryEngine3(SIGGRAPH%202010%20Advanced%20RealTime%20Rendering%20Course).pdf +vec3 encode24(vec3 v) { + // Unsigned normal (handles most symmetry) + vec3 vNormalUns = abs(v); + // Get the major axis for our collapsed cubemap lookup + float maxNAbs = max(vNormalUns.z, max(vNormalUns.x, vNormalUns.y)); + // Get the collapsed cubemap texture coordinates + vec2 vTexCoord = vNormalUns.z < maxNAbs ? (vNormalUns.y < maxNAbs ? vNormalUns.yz : vNormalUns.xz) : vNormalUns.xy; + vTexCoord /= maxNAbs; + vTexCoord = vTexCoord.x < vTexCoord.y ? vTexCoord.yx : vTexCoord.xy; + // Stretch: + vTexCoord.y /= vTexCoord.x; + float fFittingScale = texture(sampler2D(best_fit_normal_texture, SAMPLER_NEAREST_CLAMP), vTexCoord).r; + // Make vector touch unit cube + vec3 result = v / maxNAbs; + // scale the normal to get the best fit + result *= fFittingScale; + return result; +} +#endif // MODE_RENDER_NORMAL_ROUGHNESS + void fragment_shader(in SceneData scene_data) { uint instance_index = instance_index_interp; @@ -1519,18 +1541,18 @@ void fragment_shader(in SceneData scene_data) { vec2 base_coord = screen_uv; vec2 closest_coord = base_coord; #ifdef USE_MULTIVIEW - float closest_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), vec3(base_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0); + float closest_ang = dot(normal, normalize(textureLod(sampler2DArray(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), vec3(base_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0)); #else // USE_MULTIVIEW - float closest_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), base_coord, 0.0).xyz * 2.0 - 1.0); + float closest_ang = dot(normal, normalize(textureLod(sampler2D(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), base_coord, 0.0).xyz * 2.0 - 1.0)); #endif // USE_MULTIVIEW for (int i = 0; i < 4; i++) { const vec2 neighbors[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1)); vec2 neighbour_coord = base_coord + neighbors[i] * scene_data.screen_pixel_size; #ifdef USE_MULTIVIEW - float neighbour_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0); + float neighbour_ang = dot(normal, normalize(textureLod(sampler2DArray(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0)); #else // USE_MULTIVIEW - float neighbour_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), neighbour_coord, 0.0).xyz * 2.0 - 1.0); + float neighbour_ang = dot(normal, normalize(textureLod(sampler2D(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), neighbour_coord, 0.0).xyz * 2.0 - 1.0)); #endif // USE_MULTIVIEW if (neighbour_ang > closest_ang) { closest_ang = neighbour_ang; @@ -2302,7 +2324,7 @@ void fragment_shader(in SceneData scene_data) { albedo_output_buffer.rgb = albedo; albedo_output_buffer.a = alpha; - normal_output_buffer.rgb = normal * 0.5 + 0.5; + normal_output_buffer.rgb = encode24(normal) * 0.5 + 0.5; normal_output_buffer.a = 0.0; depth_output_buffer.r = -vertex.z; @@ -2316,7 +2338,15 @@ void fragment_shader(in SceneData scene_data) { #endif #ifdef MODE_RENDER_NORMAL_ROUGHNESS - normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness); + normal_roughness_output_buffer = vec4(encode24(normal) * 0.5 + 0.5, roughness); + + // We encode the dynamic static into roughness. + // Values over 0.5 are dynamic, under 0.5 are static. + normal_roughness_output_buffer.w = normal_roughness_output_buffer.w * (127.0 / 255.0); + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_DYNAMIC)) { + normal_roughness_output_buffer.w = 1.0 - normal_roughness_output_buffer.w; + } + normal_roughness_output_buffer.w = normal_roughness_output_buffer.w; #ifdef MODE_RENDER_VOXEL_GI if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 5cde975f94..441cf3c80c 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -48,6 +48,7 @@ draw_call; layout(set = 0, binding = 2) uniform sampler shadow_sampler; +#define INSTANCE_FLAGS_DYNAMIC (1 << 3) #define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 4) #define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 5) #define INSTANCE_FLAGS_USE_SDFGI (1 << 6) @@ -163,6 +164,8 @@ sdfgi; layout(set = 0, binding = 14) uniform sampler DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP; +layout(set = 0, binding = 15) uniform texture2D best_fit_normal_texture; + /* Set 1: Render Pass (changes per render pass) */ layout(set = 1, binding = 0, std140) uniform SceneDataBlock { @@ -328,6 +331,15 @@ layout(set = 1, binding = 34) uniform texture2D ssil_buffer; #endif +vec4 normal_roughness_compatibility(vec4 p_normal_roughness) { + float roughness = p_normal_roughness.w; + if (roughness > 0.5) { + roughness = 1.0 - roughness; + } + roughness /= (127.0 / 255.0); + return vec4(normalize(p_normal_roughness.xyz * 2.0 - 1.0) * 0.5 + 0.5, roughness); +} + /* Set 2 Skeleton & Instancing (can change per item) */ layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms { diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index cc3e5f6a14..7674e905e1 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -29,6 +29,7 @@ draw_call; layout(set = 0, binding = 2) uniform sampler shadow_sampler; +#define INSTANCE_FLAGS_DYNAMIC (1 << 3) #define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 4) #define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 5) #define INSTANCE_FLAGS_USE_SDFGI (1 << 6) diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index 5f4bf6c8ed..21c6425a87 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -996,15 +996,15 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged //update without barriers if (omni_light_count) { - RD::get_singleton()->buffer_update(omni_light_buffer, 0, sizeof(LightData) * omni_light_count, omni_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(omni_light_buffer, 0, sizeof(LightData) * omni_light_count, omni_lights); } if (spot_light_count) { - RD::get_singleton()->buffer_update(spot_light_buffer, 0, sizeof(LightData) * spot_light_count, spot_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(spot_light_buffer, 0, sizeof(LightData) * spot_light_count, spot_lights); } if (r_directional_light_count) { - RD::get_singleton()->buffer_update(directional_light_buffer, 0, sizeof(DirectionalLightData) * r_directional_light_count, directional_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(directional_light_buffer, 0, sizeof(DirectionalLightData) * r_directional_light_count, directional_lights); } } @@ -1722,7 +1722,7 @@ void LightStorage::update_reflection_probe_buffer(RenderDataRD *p_render_data, c } if (reflection_count) { - RD::get_singleton()->buffer_update(reflection_buffer, 0, reflection_count * sizeof(ReflectionData), reflections, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(reflection_buffer, 0, reflection_count * sizeof(ReflectionData), reflections); } } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 2e8c9d7f8e..1c3076b128 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -986,7 +986,7 @@ void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_se } } -bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material, uint32_t p_barrier) { +bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (uniform_buffer.is_valid()) { @@ -1011,7 +1011,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap< //check whether buffer changed if (p_uniform_dirty && ubo_data.size()) { update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), p_use_linear_color); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); + RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); } uint32_t tex_uniform_count = 0U; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index 403fd286b4..fe769a778d 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -87,7 +87,7 @@ public: virtual ~MaterialData(); //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &r_uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); + bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &r_uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material); void free_parameters_uniform_set(RID p_uniform_set); private: diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 3bc1b476cb..b97ce2d006 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -657,7 +657,8 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - if (!skeleton || skeleton->size == 0 || mesh->skeleton_aabb_version == skeleton->version) { + // A mesh can be shared by multiple skeletons and we need to avoid using the AABB from a different skeleton. + if (!skeleton || skeleton->size == 0 || (mesh->skeleton_aabb_version == skeleton->version && mesh->skeleton_aabb_rid == p_skeleton)) { return mesh->aabb; } @@ -763,6 +764,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { mesh->aabb = aabb; mesh->skeleton_aabb_version = skeleton->version; + mesh->skeleton_aabb_rid = p_skeleton; return aabb; } @@ -1456,8 +1458,7 @@ void MeshStorage::_multimesh_enable_motion_vectors(MultiMesh *multimesh) { if (multimesh->buffer_set && multimesh->data_cache.is_empty()) { // If the buffer was set but there's no data cached in the CPU, we copy the buffer directly on the GPU. - RD::get_singleton()->barrier(); - RD::get_singleton()->buffer_copy(multimesh->buffer, new_buffer, 0, 0, buffer_size, RD::BARRIER_MASK_NO_BARRIER); + RD::get_singleton()->buffer_copy(multimesh->buffer, new_buffer, 0, 0, buffer_size); RD::get_singleton()->buffer_copy(multimesh->buffer, new_buffer, 0, buffer_size, buffer_size); } else if (!multimesh->data_cache.is_empty()) { // Simply upload the data cached in the CPU, which should already be doubled in size. @@ -1553,7 +1554,7 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { memset(w, 0, buffer_size * sizeof(float)); } } - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); memset(multimesh->data_cache_dirty_regions, 0, data_cache_dirty_region_count * sizeof(bool)); multimesh->data_cache_dirty_region_count = 0; @@ -1581,7 +1582,7 @@ void MeshStorage::_multimesh_update_motion_vectors_data_cache(MultiMesh *multime uint32_t current_ofs = multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float); uint32_t previous_ofs = multimesh->motion_vectors_previous_offset * multimesh->stride_cache * sizeof(float); uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; - uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t visible_region_count = visible_instances == 0 ? 0 : Math::division_round_up(visible_instances, (uint32_t)MULTIMESH_DIRTY_REGION_SIZE); uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); for (uint32_t i = 0; i < visible_region_count; i++) { @@ -1601,7 +1602,7 @@ bool MeshStorage::_multimesh_uses_motion_vectors(MultiMesh *multimesh) { void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; #ifdef DEBUG_ENABLED - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug #endif if (!multimesh->data_cache_dirty_regions[region_index]) { @@ -1622,7 +1623,7 @@ void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { if (p_data) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { if (!multimesh->data_cache_dirty_regions[i]) { @@ -2021,8 +2022,8 @@ void MeshStorage::_update_dirty_multimeshes() { uint32_t total_dirty_regions = multimesh->data_cache_dirty_region_count + multimesh->previous_data_cache_dirty_region_count; if (total_dirty_regions != 0) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, (int)MULTIMESH_DIRTY_REGION_SIZE); + uint32_t visible_region_count = visible_instances == 0 ? 0 : Math::division_round_up(visible_instances, (uint32_t)MULTIMESH_DIRTY_REGION_SIZE); uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); if (total_dirty_regions > 32 || total_dirty_regions > visible_region_count / 2) { @@ -2035,10 +2036,9 @@ void MeshStorage::_update_dirty_multimeshes() { uint32_t offset = i * region_size; uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i; - RD::get_singleton()->buffer_update(multimesh->buffer, buffer_offset * sizeof(float) + offset, MIN(region_size, size - offset), &data[region_start_index], RD::BARRIER_MASK_NO_BARRIER); + RD::get_singleton()->buffer_update(multimesh->buffer, buffer_offset * sizeof(float) + offset, MIN(region_size, size - offset), &data[region_start_index]); } } - RD::get_singleton()->barrier(RD::BARRIER_MASK_NO_BARRIER, RD::BARRIER_MASK_ALL_BARRIERS); } memcpy(multimesh->previous_data_cache_dirty_regions, multimesh->data_cache_dirty_regions, data_cache_dirty_region_count * sizeof(bool)); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 0fc1a6f320..a1e2ffcf7e 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -153,6 +153,7 @@ private: AABB aabb; AABB custom_aabb; uint64_t skeleton_aabb_version = 0; + RID skeleton_aabb_rid; Vector<RID> material_cache; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 3d3cb585ac..a854e78f53 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -307,6 +307,11 @@ void ParticlesStorage::_particles_free_data(Particles *particles) { particles->emission_storage_buffer = RID(); } + if (particles->unused_storage_buffer.is_valid()) { + RD::get_singleton()->free(particles->unused_storage_buffer); + particles->unused_storage_buffer = RID(); + } + if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { //will need to be re-created RD::get_singleton()->free(particles->particles_material_uniform_set); @@ -530,6 +535,12 @@ void ParticlesStorage::_particles_allocate_emission_buffer(Particles *particles) } } +void ParticlesStorage::_particles_ensure_unused_buffer(Particles *particles) { + if (particles->unused_storage_buffer.is_null()) { + particles->unused_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); + } +} + void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { Particles *particles = particles_owner.get_or_null(p_particles); ERR_FAIL_NULL(particles); @@ -757,7 +768,8 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta if (p_particles->emission_storage_buffer.is_valid()) { u.append_id(p_particles->emission_storage_buffer); } else { - u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer()); + _particles_ensure_unused_buffer(p_particles); + u.append_id(p_particles->unused_storage_buffer); } uniforms.push_back(u); } @@ -772,7 +784,8 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta } u.append_id(sub_emitter->emission_storage_buffer); } else { - u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer()); + _particles_ensure_unused_buffer(p_particles); + u.append_id(p_particles->unused_storage_buffer); } uniforms.push_back(u); } @@ -1463,7 +1476,8 @@ void ParticlesStorage::update_particles() { if (particles->trail_bind_pose_buffer.is_valid()) { u.append_id(particles->trail_bind_pose_buffer); } else { - u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer()); + _particles_ensure_unused_buffer(particles); + u.append_id(particles->unused_storage_buffer); } uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index a28d7b4154..33f44f3045 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -247,6 +247,8 @@ private: ParticleEmissionBuffer *emission_buffer = nullptr; RID emission_storage_buffer; + RID unused_storage_buffer; + HashSet<RID> collisions; Dependency dependency; @@ -263,6 +265,7 @@ private: void _particles_process(Particles *p_particles, double p_delta); void _particles_allocate_emission_buffer(Particles *particles); + void _particles_ensure_unused_buffer(Particles *particles); void _particles_free_data(Particles *particles); void _particles_update_buffers(Particles *particles); diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index 6a99eb4108..c338dd0377 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -151,6 +151,14 @@ void RenderSceneBuffersRD::configure(const RenderSceneBuffersConfiguration *p_co // cleanout any old buffers we had. cleanup(); + // At least one of these is required to be supported. + RenderingDeviceCommons::DataFormat preferred_format[2] = { RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::DATA_FORMAT_D32_SFLOAT_S8_UINT }; + if (can_be_storage) { + // Prefer higher precision on desktop. + preferred_format[0] = RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + preferred_format[1] = RD::DATA_FORMAT_D24_UNORM_S8_UINT; + } + // create our 3D render buffers { // Create our color buffer(s) @@ -174,7 +182,7 @@ void RenderSceneBuffersRD::configure(const RenderSceneBuffersConfiguration *p_co if (msaa_3d == RS::VIEWPORT_MSAA_DISABLED) { usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, usage_bits) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + format = RD::get_singleton()->texture_is_format_supported_for_usage(preferred_format[0], usage_bits) ? preferred_format[0] : preferred_format[1]; } else { format = RD::DATA_FORMAT_R32_SFLOAT; usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | (can_be_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0); @@ -202,7 +210,7 @@ void RenderSceneBuffersRD::configure(const RenderSceneBuffersConfiguration *p_co create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples); usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, usage_bits) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + format = RD::get_singleton()->texture_is_format_supported_for_usage(preferred_format[0], usage_bits) ? preferred_format[0] : preferred_format[1]; create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples); } @@ -330,7 +338,7 @@ RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context return named_texture.texture; } -RID RenderSceneBuffersRD::_create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, const Ref<RDTextureView> p_view) { +RID RenderSceneBuffersRD::_create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, const Ref<RDTextureView> p_view) { RD::TextureView texture_view; if (p_view.is_valid()) { // only use when supplied, else default. texture_view = p_view->base; @@ -339,7 +347,7 @@ RID RenderSceneBuffersRD::_create_texture_view(const StringName &p_context, cons return create_texture_view(p_context, p_texture_name, p_view_name, texture_view); } -RID RenderSceneBuffersRD::create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view) { +RID RenderSceneBuffersRD::create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, RD::TextureView p_view) { NTKey view_key(p_context, p_view_name); // check if this is a known texture diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index b2946e6bbc..5b8a74de83 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -106,7 +106,7 @@ private: } NTKey() {} - NTKey(const StringName p_context, const StringName p_texture_name) { + NTKey(const StringName &p_context, const StringName &p_texture_name) { context = p_context; buffer_name = p_texture_name; } @@ -196,7 +196,7 @@ public: bool has_texture(const StringName &p_context, const StringName &p_texture_name) const; RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true); RID create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view = RD::TextureView(), bool p_unique = true); - RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView()); + RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, RD::TextureView p_view = RD::TextureView()); RID get_texture(const StringName &p_context, const StringName &p_texture_name) const; const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const; RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1); @@ -310,7 +310,7 @@ public: private: RID _create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const Ref<RDTextureFormat> &p_texture_format, const Ref<RDTextureView> &p_view = Ref<RDTextureView>(), bool p_unique = true); - RID _create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, const Ref<RDTextureView> p_view = Ref<RDTextureView>()); + RID _create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, const Ref<RDTextureView> p_view = Ref<RDTextureView>()); Ref<RDTextureFormat> _get_texture_format(const StringName &p_context, const StringName &p_texture_name) const; RID _get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1, const Ref<RDTextureView> p_view = Ref<RDTextureView>()); diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp index 40891f9a63..f2231664fa 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -252,7 +252,7 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p } uniform_buffer = p_uniform_buffer; - RD::get_singleton()->buffer_update(uniform_buffer, 0, sizeof(UBODATA), &ubo, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(uniform_buffer, 0, sizeof(UBODATA), &ubo); } RID RenderSceneDataRD::get_uniform_buffer() { diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 380e325ffa..d8baf260f9 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -2703,7 +2703,7 @@ void TextureStorage::update_decal_atlas() { Vector<Color> cc; cc.push_back(clear_color); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, cc); for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) { DecalAtlas::Texture *t = decal_atlas.textures.getptr(E.key); @@ -2981,7 +2981,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const } if (decal_count > 0) { - RD::get_singleton()->buffer_update(decal_buffer, 0, sizeof(DecalData) * decal_count, decals, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(decal_buffer, 0, sizeof(DecalData) * decal_count, decals); } } @@ -3384,7 +3384,7 @@ void TextureStorage::render_target_do_msaa_resolve(RID p_render_target) { if (!rt->msaa_needs_resolve) { return; } - RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_end(); rt->msaa_needs_resolve = false; } @@ -3501,7 +3501,7 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) { } Vector<Color> clear_colors; clear_colors.push_back(rt->use_hdr ? rt->clear_color.srgb_to_linear() : rt->clear_color); - RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors); RD::get_singleton()->draw_list_end(); rt->clear_requested = false; rt->msaa_needs_resolve = false; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 97e9694fe1..7a2415442d 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -754,7 +754,6 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) { if (blits.size() > 0) { RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blits.ptr(), blits.size()); } - RSG::rasterizer->end_frame(true); } else if (blits.size() > 0) { if (!blit_to_screen_list.has(vp->viewport_to_screen)) { blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>(); @@ -764,6 +763,7 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) { blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]); } } + RSG::rasterizer->end_viewport(p_swap_buffers && blits.size() > 0); } } } else { @@ -793,10 +793,10 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) { Vector<BlitToScreen> blit_to_screen_vec; blit_to_screen_vec.push_back(blit); RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blit_to_screen_vec.ptr(), 1); - RSG::rasterizer->end_frame(true); } else { blit_to_screen_list[vp->viewport_to_screen].push_back(blit); } + RSG::rasterizer->end_viewport(p_swap_buffers); } } @@ -823,8 +823,8 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) { RENDER_TIMESTAMP("< Render Viewports"); - if (p_swap_buffers) { - //this needs to be called to make screen swapping more efficient + if (p_swap_buffers && !blit_to_screen_list.is_empty()) { + // This needs to be called to make screen swapping more efficient. RSG::rasterizer->prepare_for_blitting_render_targets(); for (const KeyValue<int, Vector<BlitToScreen>> &E : blit_to_screen_list) { diff --git a/servers/rendering/rendering_device.compat.inc b/servers/rendering/rendering_device.compat.inc index 8e7beda6f3..edc08e972d 100644 --- a/servers/rendering/rendering_device.compat.inc +++ b/servers/rendering/rendering_device.compat.inc @@ -34,39 +34,87 @@ RID RenderingDevice::_shader_create_from_bytecode_bind_compat_79606(const Vector return shader_create_from_bytecode(p_shader_binary, RID()); } -BitField<RenderingDevice::BarrierMask> RenderingDevice::_convert_barrier_mask_81356(BitField<BarrierMask> p_old_barrier) { - if (p_old_barrier == 7) { - return BARRIER_MASK_ALL_BARRIERS; - } else if (p_old_barrier == 16) { - return BARRIER_MASK_NO_BARRIER; - } +void RenderingDevice::_draw_list_end_bind_compat_81356(BitField<BarrierMask> p_post_barrier) { + draw_list_end(); +} - BitField<BarrierMask> new_barrier; - if (p_old_barrier & 1) { - new_barrier.set_flag(BARRIER_MASK_VERTEX); - } - if (p_old_barrier & 2) { - new_barrier.set_flag(BARRIER_MASK_FRAGMENT); - } - if (p_old_barrier & 4) { - new_barrier.set_flag(BARRIER_MASK_COMPUTE); +void RenderingDevice::_compute_list_end_bind_compat_81356(BitField<BarrierMask> p_post_barrier) { + compute_list_end(); +} + +void RenderingDevice::_barrier_bind_compat_81356(BitField<BarrierMask> p_from, BitField<BarrierMask> p_to) { + // Does nothing. +} + +void RenderingDevice::_draw_list_end_bind_compat_84976(BitField<BarrierMask> p_post_barrier) { + draw_list_end(); +} + +void RenderingDevice::_compute_list_end_bind_compat_84976(BitField<BarrierMask> p_post_barrier) { + compute_list_end(); +} + +RenderingDevice::InitialAction RenderingDevice::_convert_initial_action_84976(InitialAction p_old_initial_action) { + switch (uint32_t(p_old_initial_action)) { + case 0: // INITIAL_ACTION_CLEAR + return INITIAL_ACTION_CLEAR; + case 1: // INITIAL_ACTION_CLEAR_REGION + case 2: // INITIAL_ACTION_CLEAR_REGION_CONTINUE + return INITIAL_ACTION_CLEAR; + case 3: // INITIAL_ACTION_KEEP + return INITIAL_ACTION_LOAD; + case 4: // INITIAL_ACTION_DROP + return INITIAL_ACTION_DISCARD; + case 5: // INITIAL_ACTION_CONTINUE + return INITIAL_ACTION_LOAD; + default: + return INITIAL_ACTION_LOAD; } - if (p_old_barrier & 8) { - new_barrier.set_flag(BARRIER_MASK_TRANSFER); +} + +RenderingDevice::FinalAction RenderingDevice::_convert_final_action_84976(FinalAction p_old_final_action) { + switch (uint32_t(p_old_final_action)) { + case 0: // FINAL_ACTION_READ + return FINAL_ACTION_STORE; + case 1: // FINAL_ACTION_DISCARD + return FINAL_ACTION_DISCARD; + case 2: // FINAL_ACTION_CONTINUE + return FINAL_ACTION_STORE; + default: + return FINAL_ACTION_STORE; } - return new_barrier; } -void RenderingDevice::_draw_list_end_bind_compat_81356(BitField<BarrierMask> p_post_barrier) { - draw_list_end(_convert_barrier_mask_81356(p_post_barrier)); +RenderingDevice::DrawListID RenderingDevice::_draw_list_begin_bind_compat_84976(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) { + return draw_list_begin(p_framebuffer, _convert_initial_action_84976(p_initial_color_action), _convert_final_action_84976(p_final_color_action), _convert_initial_action_84976(p_initial_depth_action), _convert_final_action_84976(p_final_depth_action), p_clear_color_values, p_clear_depth, p_clear_stencil, p_region); } -void RenderingDevice::_compute_list_end_bind_compat_81356(BitField<BarrierMask> p_post_barrier) { - compute_list_end(_convert_barrier_mask_81356(p_post_barrier)); +RenderingDevice::ComputeListID RenderingDevice::_compute_list_begin_bind_compat_84976(bool p_allow_draw_overlap) { + return compute_list_begin(); } -void RenderingDevice::_barrier_bind_compat_81356(BitField<BarrierMask> p_from, BitField<BarrierMask> p_to) { - barrier(_convert_barrier_mask_81356(p_from), _convert_barrier_mask_81356(p_to)); +Error RenderingDevice::_buffer_update_bind_compat_84976(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier) { + return _buffer_update_bind(p_buffer, p_offset, p_size, p_data); +} + +Error RenderingDevice::_buffer_clear_bind_compat_84976(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier) { + return buffer_clear(p_buffer, p_offset, p_size); +} + +Error RenderingDevice::_texture_update_bind_compat_84976(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier) { + return texture_update(p_texture, p_layer, p_data); +} + +Error RenderingDevice::_texture_copy_bind_compat_84976(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier) { + return texture_copy(p_from_texture, p_to_texture, p_from, p_to, p_size, p_src_mipmap, p_dst_mipmap, p_src_layer, p_dst_layer); +} + +Error RenderingDevice::_texture_clear_bind_compat_84976(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier) { + return texture_clear(p_texture, p_color, p_base_mipmap, p_mipmaps, p_base_layer, p_layers); +} + +Error RenderingDevice::_texture_resolve_multisample_bind_compat_84976(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier) { + return texture_resolve_multisample(p_from_texture, p_to_texture); } void RenderingDevice::_bind_compatibility_methods() { @@ -74,6 +122,16 @@ void RenderingDevice::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::_draw_list_end_bind_compat_81356, DEFVAL(7)); ClassDB::bind_compatibility_method(D_METHOD("compute_list_end", "post_barrier"), &RenderingDevice::_compute_list_end_bind_compat_81356, DEFVAL(7)); ClassDB::bind_compatibility_method(D_METHOD("barrier", "from", "to"), &RenderingDevice::_barrier_bind_compat_81356, DEFVAL(7), DEFVAL(7)); + ClassDB::bind_compatibility_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::_draw_list_end_bind_compat_84976, DEFVAL(0x7FFF)); + ClassDB::bind_compatibility_method(D_METHOD("compute_list_end", "post_barrier"), &RenderingDevice::_compute_list_end_bind_compat_84976, DEFVAL(0x7FFF)); + ClassDB::bind_compatibility_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_bind_compat_84976, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); + ClassDB::bind_compatibility_method(D_METHOD("compute_list_begin", "allow_draw_overlap"), &RenderingDevice::_compute_list_begin_bind_compat_84976, DEFVAL(false)); + ClassDB::bind_compatibility_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "post_barrier"), &RenderingDevice::_buffer_update_bind_compat_84976, DEFVAL(0x7FFF)); + ClassDB::bind_compatibility_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::_buffer_clear_bind_compat_84976, DEFVAL(0x7FFF)); + ClassDB::bind_compatibility_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::_texture_update_bind_compat_84976, DEFVAL(0x7FFF)); + ClassDB::bind_compatibility_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer", "post_barrier"), &RenderingDevice::_texture_copy_bind_compat_84976, DEFVAL(0x7FFF)); + ClassDB::bind_compatibility_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::_texture_clear_bind_compat_84976, DEFVAL(0x7FFF)); + ClassDB::bind_compatibility_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::_texture_resolve_multisample_bind_compat_84976, DEFVAL(0x7FFF)); } #endif diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index a7f124c23c..8e03796d33 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -37,7 +37,26 @@ #include "core/io/dir_access.h" #include "servers/rendering/renderer_rd/api_context_rd.h" -//#define FORCE_FULL_BARRIER +// When true, the command graph will attempt to reorder the rendering commands submitted by the user based on the dependencies detected from +// the commands automatically. This should improve rendering performance in most scenarios at the cost of some extra CPU overhead. +// +// This behavior can be disabled if it's suspected that the graph is not detecting dependencies correctly and more control over the order of +// the commands is desired (e.g. debugging). + +#define RENDER_GRAPH_REORDER 1 + +// Synchronization barriers are issued between the graph's levels only with the necessary amount of detail to achieve the correct result. If +// it's suspected that the graph is not doing this correctly, full barriers can be issued instead that will block all types of operations +// between the synchronization levels. This setting will have a very negative impact on performance when enabled, so it's only intended for +// debugging purposes. + +#define RENDER_GRAPH_FULL_BARRIERS 0 + +// The command graph can automatically issue secondary command buffers and record them on background threads when they reach an arbitrary +// size threshold. This can be very beneficial towards reducing the time the main thread takes to record all the rendering commands. However, +// this setting is not enabled by default as it's been shown to cause some strange issues with certain IHVs that have yet to be understood. + +#define SECONDARY_COMMAND_BUFFERS_PER_FRAME 0 RenderingDevice *RenderingDevice::singleton = nullptr; @@ -131,127 +150,23 @@ RID RenderingDevice::shader_create_from_spirv(const Vector<ShaderStageSPIRVData> return shader_create_from_bytecode(bytecode); } -/******************/ -/**** BARRIERS ****/ -/******************/ - -void RenderingDevice::_full_barrier(bool p_sync_with_draw) { - // Used for debug. - - RDD::MemoryBarrier mb; - mb.src_access = (RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT | - RDD::BARRIER_ACCESS_INDEX_READ_BIT | - RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | - RDD::BARRIER_ACCESS_UNIFORM_READ_BIT | - RDD::BARRIER_ACCESS_INPUT_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_SHADER_READ_BIT | - RDD::BARRIER_ACCESS_SHADER_WRITE_BIT | - RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | - RDD::BARRIER_ACCESS_TRANSFER_READ_BIT | - RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT | - RDD::BARRIER_ACCESS_HOST_READ_BIT | - RDD::BARRIER_ACCESS_HOST_WRITE_BIT); - mb.dst_access = (RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT | - RDD::BARRIER_ACCESS_INDEX_READ_BIT | - RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | - RDD::BARRIER_ACCESS_UNIFORM_READ_BIT | - RDD::BARRIER_ACCESS_INPUT_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_SHADER_READ_BIT | - RDD::BARRIER_ACCESS_SHADER_WRITE_BIT | - RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | - RDD::BARRIER_ACCESS_TRANSFER_READ_BIT | - RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT | - RDD::BARRIER_ACCESS_HOST_READ_BIT | - RDD::BARRIER_ACCESS_HOST_WRITE_BIT); - - RDD::CommandBufferID cmd_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer; - driver->command_pipeline_barrier(cmd_buffer, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, mb, {}, {}); -} - /***************************/ /**** BUFFER MANAGEMENT ****/ /***************************/ -RenderingDevice::Buffer *RenderingDevice::_get_buffer_from_owner(RID p_buffer, BitField<RDD::PipelineStageBits> &r_stages, BitField<RDD::BarrierAccessBits> &r_access, BitField<BarrierMask> p_post_barrier) { +RenderingDevice::Buffer *RenderingDevice::_get_buffer_from_owner(RID p_buffer) { Buffer *buffer = nullptr; - r_stages.clear(); - r_access.clear(); if (vertex_buffer_owner.owns(p_buffer)) { buffer = vertex_buffer_owner.get_or_null(p_buffer); - - r_stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT); - if (buffer->usage & RDD::BUFFER_USAGE_STORAGE_BIT) { - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - r_stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - r_stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - r_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - } - } } else if (index_buffer_owner.owns(p_buffer)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_INDEX_READ_BIT); buffer = index_buffer_owner.get_or_null(p_buffer); } else if (uniform_buffer_owner.owns(p_buffer)) { - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - } - r_access.set_flag(RDD::BARRIER_ACCESS_UNIFORM_READ_BIT); buffer = uniform_buffer_owner.get_or_null(p_buffer); } else if (texture_buffer_owner.owns(p_buffer)) { - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT); - } - - // FIXME: Broken. + DEV_ASSERT(false && "FIXME: Broken."); //buffer = texture_buffer_owner.get_or_null(p_buffer)->buffer; } else if (storage_buffer_owner.owns(p_buffer)) { buffer = storage_buffer_owner.get_or_null(p_buffer); - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - - if (buffer->usage.has_flag(RDD::BUFFER_USAGE_INDIRECT_BIT)) { - r_stages.set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); - r_access.set_flag(RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT); - } } return buffer; } @@ -269,10 +184,11 @@ Error RenderingDevice::_insert_staging_block() { return OK; } -Error RenderingDevice::_staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, bool p_can_segment) { +Error RenderingDevice::_staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, StagingRequiredAction &r_required_action, bool p_can_segment) { // Determine a block to use. r_alloc_size = p_amount; + r_required_action = STAGING_REQUIRED_ACTION_NONE; while (true) { r_alloc_offset = 0; @@ -324,23 +240,7 @@ Error RenderingDevice::_staging_buffer_allocate(uint32_t p_amount, uint32_t p_re // and this frame is not even done. // If this is the main thread, it means the user is likely loading a lot of resources at once,. // Otherwise, the thread should just be blocked until the next frame (currently unimplemented). - - if (false) { // Separate thread from render. - - //block_until_next_frame() - continue; - } else { - // Flush EVERYTHING including setup commands. IF not immediate, also need to flush the draw commands. - _flush(true); - - // Clear the whole staging buffer. - for (int i = 0; i < staging_buffer_blocks.size(); i++) { - staging_buffer_blocks.write[i].frame_used = 0; - staging_buffer_blocks.write[i].fill_amount = 0; - } - // Claim current. - staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn; - } + r_required_action = STAGING_REQUIRED_ACTION_FLUSH_CURRENT; } } else { @@ -368,28 +268,7 @@ Error RenderingDevice::_staging_buffer_allocate(uint32_t p_amount, uint32_t p_re // Let's flush older frames. // The logic here is that if a game is loading a lot of data from the main thread, it will need to be stalled anyway. // If loading from a separate thread, we can block that thread until next frame when more room is made (not currently implemented, though). - - if (false) { - // Separate thread from render. - //block_until_next_frame() - continue; // And try again. - } else { - _flush(false); - - for (int i = 0; i < staging_buffer_blocks.size(); i++) { - // Clear all blocks but the ones from this frame. - int block_idx = (i + staging_buffer_current) % staging_buffer_blocks.size(); - if (staging_buffer_blocks[block_idx].frame_used == frames_drawn) { - break; // Ok, we reached something from this frame, abort. - } - - staging_buffer_blocks.write[block_idx].frame_used = 0; - staging_buffer_blocks.write[block_idx].fill_amount = 0; - } - - // Claim for current frame. - staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn; - } + r_required_action = STAGING_REQUIRED_ACTION_FLUSH_OLDER; } } @@ -402,20 +281,78 @@ Error RenderingDevice::_staging_buffer_allocate(uint32_t p_amount, uint32_t p_re return OK; } -Error RenderingDevice::_buffer_update(Buffer *p_buffer, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_command_buffer, uint32_t p_required_align) { +void RenderingDevice::_staging_buffer_execute_required_action(StagingRequiredAction p_required_action) { + switch (p_required_action) { + case STAGING_REQUIRED_ACTION_NONE: { + // Do nothing. + } break; + case STAGING_REQUIRED_ACTION_FLUSH_CURRENT: { + // Flush EVERYTHING including setup commands. IF not immediate, also need to flush the draw commands. + _flush(true); + + // Clear the whole staging buffer. + for (int i = 0; i < staging_buffer_blocks.size(); i++) { + staging_buffer_blocks.write[i].frame_used = 0; + staging_buffer_blocks.write[i].fill_amount = 0; + } + + // Claim for current frame. + staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn; + } break; + case STAGING_REQUIRED_ACTION_FLUSH_OLDER: { + _flush(false); + + for (int i = 0; i < staging_buffer_blocks.size(); i++) { + // Clear all blocks but the ones from this frame. + int block_idx = (i + staging_buffer_current) % staging_buffer_blocks.size(); + if (staging_buffer_blocks[block_idx].frame_used == frames_drawn) { + break; // Ok, we reached something from this frame, abort. + } + + staging_buffer_blocks.write[block_idx].frame_used = 0; + staging_buffer_blocks.write[block_idx].fill_amount = 0; + } + + // Claim for current frame. + staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn; + } break; + default: { + DEV_ASSERT(false && "Unknown required action."); + } break; + } +} + +Error RenderingDevice::_buffer_update(Buffer *p_buffer, RID p_buffer_id, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_queue, uint32_t p_required_align) { // Submitting may get chunked for various reasons, so convert this to a task. size_t to_submit = p_data_size; size_t submit_from = 0; + thread_local LocalVector<RDG::RecordedBufferCopy> command_buffer_copies_vector; + command_buffer_copies_vector.clear(); + while (to_submit > 0) { uint32_t block_write_offset; uint32_t block_write_amount; + StagingRequiredAction required_action; - Error err = _staging_buffer_allocate(MIN(to_submit, staging_buffer_block_size), p_required_align, block_write_offset, block_write_amount); + Error err = _staging_buffer_allocate(MIN(to_submit, staging_buffer_block_size), p_required_align, block_write_offset, block_write_amount, required_action); if (err) { return err; } + if (p_use_draw_queue && !command_buffer_copies_vector.is_empty() && required_action == STAGING_REQUIRED_ACTION_FLUSH_CURRENT) { + if (_buffer_make_mutable(p_buffer, p_buffer_id)) { + // The buffer must be mutable to be used as a copy destination. + draw_graph.add_synchronization(); + } + + // If we're using the draw queue and the staging buffer requires flushing everything, we submit the command early and clear the current vector. + draw_graph.add_buffer_update(p_buffer->driver_id, p_buffer->draw_tracker, command_buffer_copies_vector); + command_buffer_copies_vector.clear(); + } + + _staging_buffer_execute_required_action(required_action); + // Map staging buffer (It's CPU and coherent). uint8_t *data_ptr = driver->buffer_map(staging_buffer_blocks[staging_buffer_current].driver_id); ERR_FAIL_NULL_V(data_ptr, ERR_CANT_CREATE); @@ -427,12 +364,19 @@ Error RenderingDevice::_buffer_update(Buffer *p_buffer, size_t p_offset, const u driver->buffer_unmap(staging_buffer_blocks[staging_buffer_current].driver_id); // Insert a command to copy this. - RDD::BufferCopyRegion region; region.src_offset = block_write_offset; region.dst_offset = submit_from + p_offset; region.size = block_write_amount; - driver->command_copy_buffer(p_use_draw_command_buffer ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, staging_buffer_blocks[staging_buffer_current].driver_id, p_buffer->driver_id, region); + + if (p_use_draw_queue) { + RDG::RecordedBufferCopy buffer_copy; + buffer_copy.source = staging_buffer_blocks[staging_buffer_current].driver_id; + buffer_copy.region = region; + command_buffer_copies_vector.push_back(buffer_copy); + } else { + driver->command_copy_buffer(frames[frame].setup_command_buffer, staging_buffer_blocks[staging_buffer_current].driver_id, p_buffer->driver_id, region); + } staging_buffer_blocks.write[staging_buffer_current].fill_amount = block_write_offset + block_write_amount; @@ -440,10 +384,19 @@ Error RenderingDevice::_buffer_update(Buffer *p_buffer, size_t p_offset, const u submit_from += block_write_amount; } + if (p_use_draw_queue && !command_buffer_copies_vector.is_empty()) { + if (_buffer_make_mutable(p_buffer, p_buffer_id)) { + // The buffer must be mutable to be used as a copy destination. + draw_graph.add_synchronization(); + } + + draw_graph.add_buffer_update(p_buffer->driver_id, p_buffer->draw_tracker, command_buffer_copies_vector); + } + return OK; } -Error RenderingDevice::buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t p_src_offset, uint32_t p_dst_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier) { +Error RenderingDevice::buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t p_src_offset, uint32_t p_dst_offset, uint32_t p_size) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER, @@ -451,25 +404,12 @@ Error RenderingDevice::buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER, "Copying buffers is forbidden during creation of a compute list"); - // This method assumes the barriers have been pushed prior to being called, therefore no barriers are pushed - // for the source or destination buffers before performing the copy. These masks are effectively ignored. - BitField<RDD::PipelineStageBits> src_stages; - BitField<RDD::BarrierAccessBits> src_access; - Buffer *src_buffer = _get_buffer_from_owner(p_src_buffer, src_stages, src_access, BARRIER_MASK_NO_BARRIER); + Buffer *src_buffer = _get_buffer_from_owner(p_src_buffer); if (!src_buffer) { ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Source buffer argument is not a valid buffer of any type."); } - BitField<RDD::PipelineStageBits> dst_stages; - BitField<RDD::BarrierAccessBits> dst_access; - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - // If the post barrier mask defines it, we indicate the destination buffer will require a barrier with these flags set - // after the copy command is queued. - dst_stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT); - } - - Buffer *dst_buffer = _get_buffer_from_owner(p_dst_buffer, dst_stages, dst_access, p_post_barrier); + Buffer *dst_buffer = _get_buffer_from_owner(p_dst_buffer); if (!dst_buffer) { ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Destination buffer argument is not a valid buffer of any type."); } @@ -483,31 +423,18 @@ Error RenderingDevice::buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t region.src_offset = p_src_offset; region.dst_offset = p_dst_offset; region.size = p_size; - driver->command_copy_buffer(frames[frame].draw_command_buffer, src_buffer->driver_id, dst_buffer->driver_id, region); -#ifdef FORCE_FULL_BARRIER - _full_barrier(true); -#else - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS) && p_post_barrier != RD::BARRIER_MASK_NO_BARRIER) { - if (dst_stages.is_empty()) { - dst_stages = RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - } - - // As indicated by the post barrier mask, push a new barrier. - RDD::BufferBarrier bb; - bb.buffer = dst_buffer->driver_id; - bb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - bb.dst_access = dst_access; - bb.offset = p_dst_offset; - bb.size = p_size; - driver->command_pipeline_barrier(frames[frame].draw_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, dst_stages, {}, bb, {}); + if (_buffer_make_mutable(dst_buffer, p_dst_buffer)) { + // The destination buffer must be mutable to be used as a copy destination. + draw_graph.add_synchronization(); } -#endif + + draw_graph.add_buffer_copy(src_buffer->driver_id, src_buffer->draw_tracker, dst_buffer->driver_id, dst_buffer->draw_tracker, region); return OK; } -Error RenderingDevice::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, BitField<BarrierMask> p_post_barrier) { +Error RenderingDevice::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER, @@ -515,14 +442,7 @@ Error RenderingDevice::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER, "Updating buffers is forbidden during creation of a compute list"); - BitField<RDD::PipelineStageBits> dst_stages; - BitField<RDD::BarrierAccessBits> dst_access; - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - // Protect subsequent updates. - dst_stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT); - } - Buffer *buffer = _get_buffer_from_owner(p_buffer, dst_stages, dst_access, p_post_barrier); + Buffer *buffer = _get_buffer_from_owner(p_buffer); if (!buffer) { ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Buffer argument is not a valid buffer of any type."); } @@ -530,33 +450,10 @@ Error RenderingDevice::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER, "Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end."); - Error err = _buffer_update(buffer, p_offset, (uint8_t *)p_data, p_size, true); - if (err) { - return err; - } - -#ifdef FORCE_FULL_BARRIER - _full_barrier(true); -#else - if (dst_stages.is_empty()) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - } - - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS) && p_post_barrier != RD::BARRIER_MASK_NO_BARRIER) { - RDD::BufferBarrier bb; - bb.buffer = buffer->driver_id; - bb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - bb.dst_access = dst_access; - bb.offset = p_offset; - bb.size = p_size; - driver->command_pipeline_barrier(frames[frame].draw_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, dst_stages, {}, bb, {}); - } - -#endif - return err; + return _buffer_update(buffer, p_buffer, p_offset, (uint8_t *)p_data, p_size, true); } -Error RenderingDevice::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier) { +Error RenderingDevice::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V_MSG((p_size % 4) != 0, ERR_INVALID_PARAMETER, @@ -566,15 +463,7 @@ Error RenderingDevice::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_ ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER, "Updating buffers is forbidden during creation of a compute list"); - BitField<RDD::PipelineStageBits> dst_stages; - BitField<RDD::BarrierAccessBits> dst_access; - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - // Protect subsequent updates. - dst_stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT); - } - - Buffer *buffer = _get_buffer_from_owner(p_buffer, dst_stages, dst_access, p_post_barrier); + Buffer *buffer = _get_buffer_from_owner(p_buffer); if (!buffer) { ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Buffer argument is not a valid buffer of any type."); } @@ -582,51 +471,24 @@ Error RenderingDevice::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_ ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER, "Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end."); - driver->command_clear_buffer(frames[frame].draw_command_buffer, buffer->driver_id, p_offset, p_size); - -#ifdef FORCE_FULL_BARRIER - _full_barrier(true); -#else - if (dst_stages.is_empty()) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); + if (_buffer_make_mutable(buffer, p_buffer)) { + // The destination buffer must be mutable to be used as a clear destination. + draw_graph.add_synchronization(); } - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::BufferBarrier bb; - bb.buffer = buffer->driver_id; - bb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - bb.dst_access = dst_access; - bb.offset = p_offset; - bb.size = p_size; - driver->command_pipeline_barrier(frames[frame].draw_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, dst_stages, {}, bb, {}); - } + draw_graph.add_buffer_clear(buffer->driver_id, buffer->draw_tracker, p_offset, p_size); -#endif return OK; } Vector<uint8_t> RenderingDevice::buffer_get_data(RID p_buffer, uint32_t p_offset, uint32_t p_size) { _THREAD_SAFE_METHOD_ - // It could be this buffer was just created. - BitField<RDD::PipelineStageBits> src_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; - BitField<RDD::BarrierAccessBits> src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - // Get the vulkan buffer and the potential stage/access possible. - Buffer *buffer = _get_buffer_from_owner(p_buffer, src_stages, src_access, BARRIER_MASK_ALL_BARRIERS); + Buffer *buffer = _get_buffer_from_owner(p_buffer); if (!buffer) { ERR_FAIL_V_MSG(Vector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving."); } - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - // Make sure no one is using the buffer -- the "true" gets us to the same command buffer as below. - RDD::BufferBarrier bb; - bb.buffer = buffer->driver_id; - bb.src_access = src_access; - bb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_READ_BIT; - bb.size = buffer->size; - driver->command_pipeline_barrier(frames[frame].draw_command_buffer, src_stages, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, bb, {}); - } - // Size of buffer to retrieve. if (!p_size) { p_size = buffer->size; @@ -641,7 +503,9 @@ Vector<uint8_t> RenderingDevice::buffer_get_data(RID p_buffer, uint32_t p_offset RDD::BufferCopyRegion region; region.src_offset = p_offset; region.size = p_size; - driver->command_copy_buffer(frames[frame].draw_command_buffer, buffer->driver_id, tmp_buffer, region); + + draw_graph.add_buffer_get_data(buffer->driver_id, buffer->draw_tracker, tmp_buffer, region); + // Flush everything so memory can be safely mapped. _flush(true); @@ -676,23 +540,21 @@ RID RenderingDevice::storage_buffer_create(uint32_t p_size_bytes, const Vector<u buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU); ERR_FAIL_COND_V(!buffer.driver_id, RID()); + // Storage buffers are assumed to be mutable. + buffer.draw_tracker = RDG::resource_tracker_create(); + buffer.draw_tracker->buffer_driver_id = buffer.driver_id; + if (p_data.size()) { - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - _buffer_update(&buffer, 0, r, data_size); - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::BufferBarrier bb; - bb.buffer = buffer.driver_id; - bb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - bb.dst_access = (RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - bb.size = data_size; - driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT | RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, {}, bb, {}); - } + _buffer_update(&buffer, RID(), 0, p_data.ptr(), p_data.size()); } buffer_memory += buffer.size; - return storage_buffer_owner.make_rid(buffer); + RID id = storage_buffer_owner.make_rid(buffer); +#ifdef DEV_ENABLED + set_resource_name(id, "RID:" + itos(id.get_id())); +#endif + return id; } RID RenderingDevice::texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data) { @@ -710,6 +572,12 @@ RID RenderingDevice::texture_buffer_create(uint32_t p_size_elements, DataFormat texture_buffer.driver_id = driver->buffer_create(size_bytes, usage, RDD::MEMORY_ALLOCATION_TYPE_GPU); ERR_FAIL_COND_V(!texture_buffer.driver_id, RID()); + // Texture buffers are assumed to be immutable unless they don't have initial data. + if (p_data.is_empty()) { + texture_buffer.draw_tracker = RDG::resource_tracker_create(); + texture_buffer.draw_tracker->buffer_driver_id = texture_buffer.driver_id; + } + bool ok = driver->buffer_set_texel_format(texture_buffer.driver_id, p_format); if (!ok) { driver->buffer_free(texture_buffer.driver_id); @@ -717,15 +585,7 @@ RID RenderingDevice::texture_buffer_create(uint32_t p_size_elements, DataFormat } if (p_data.size()) { - _buffer_update(&texture_buffer, 0, p_data.ptr(), p_data.size()); - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::BufferBarrier bb; - bb.buffer = texture_buffer.driver_id; - bb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - bb.dst_access = RDD::BARRIER_ACCESS_SHADER_READ_BIT; - bb.size = size_bytes; - driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, (RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT | RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT), {}, bb, {}); - } + _buffer_update(&texture_buffer, RID(), 0, p_data.ptr(), p_data.size()); } buffer_memory += size_bytes; @@ -787,10 +647,8 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture ERR_FAIL_COND_V_MSG(required_mipmaps < format.mipmaps, RID(), "Too many mipmaps requested for texture format and dimensions (" + itos(format.mipmaps) + "), maximum allowed: (" + itos(required_mipmaps) + ")."); + uint32_t forced_usage_bits = 0; if (p_data.size()) { - ERR_FAIL_COND_V_MSG(!(format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT), RID(), - "Texture needs the TEXTURE_USAGE_CAN_UPDATE_BIT usage flag in order to be updated at initialization or later"); - ERR_FAIL_COND_V_MSG(p_data.size() != (int)format.array_layers, RID(), "Default supplied data for image format is of invalid length (" + itos(p_data.size()) + "), should be (" + itos(format.array_layers) + ")."); @@ -799,6 +657,10 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture ERR_FAIL_COND_V_MSG((uint32_t)p_data[i].size() != required_size, RID(), "Data for slice index " + itos(i) + " (mapped to layer " + itos(i) + ") differs in size (supplied: " + itos(p_data[i].size()) + ") than what is required by the format (" + itos(required_size) + ")."); } + + if (!(format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT)) { + forced_usage_bits = TEXTURE_USAGE_CAN_UPDATE_BIT; + } } { @@ -849,7 +711,7 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture // Create. Texture texture; - + format.usage_bits |= forced_usage_bits; texture.driver_id = driver->texture_create(format, tv); ERR_FAIL_COND_V(!texture.driver_id, RID()); texture.type = format.texture_type; @@ -862,26 +724,10 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture texture.base_mipmap = 0; texture.base_layer = 0; texture.is_resolve_buffer = format.is_resolve_buffer; - texture.usage_flags = format.usage_bits; + texture.usage_flags = format.usage_bits & ~forced_usage_bits; texture.samples = format.samples; texture.allowed_shared_formats = format.shareable_formats; - - // Set base layout based on usage priority. - - if ((format.usage_bits & TEXTURE_USAGE_SAMPLING_BIT)) { - // First priority, readable. - texture.layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } else if ((format.usage_bits & TEXTURE_USAGE_STORAGE_BIT)) { - // Second priority, storage. - texture.layout = RDD::TEXTURE_LAYOUT_GENERAL; - } else if ((format.usage_bits & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - // Third priority, color or depth. - texture.layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } else if ((format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - texture.layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } else { - texture.layout = RDD::TEXTURE_LAYOUT_GENERAL; - } + texture.has_initial_data = !p_data.is_empty(); if ((format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT); @@ -896,18 +742,10 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture texture.bound = false; - // Barrier to set layout. - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::TextureBarrier tb; - tb.texture = texture.driver_id; - tb.dst_access = RDD::BARRIER_ACCESS_SHADER_READ_BIT; - tb.prev_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; - tb.next_layout = texture.layout; - tb.subresources.aspect = texture.barrier_aspect_flags; - tb.subresources.mipmap_count = format.mipmaps; - tb.subresources.layer_count = format.array_layers; - - driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT, RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT | RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, {}, {}, tb); + // Textures are only assumed to be immutable if they have initial data and none of the other bits that indicate write usage are enabled. + bool texture_mutable_by_default = texture.usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_STORAGE_BIT | TEXTURE_USAGE_STORAGE_ATOMIC_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT); + if (p_data.is_empty() || texture_mutable_by_default) { + _texture_make_mutable(&texture, RID()); } texture_memory += driver->texture_get_allocation_size(texture.driver_id); @@ -919,9 +757,15 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture if (p_data.size()) { for (uint32_t i = 0; i < p_format.array_layers; i++) { - _texture_update(id, i, p_data[i], BARRIER_MASK_ALL_BARRIERS, true); + _texture_update(id, i, p_data[i], true, false); + } + + if (texture.draw_tracker != nullptr) { + // Draw tracker can assume the texture will be in transfer destination. + texture.draw_tracker->usage = RDG::RESOURCE_USAGE_TRANSFER_TO; } } + return id; } @@ -959,6 +803,12 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with texture.driver_id = driver->texture_create_shared(texture.driver_id, tv); ERR_FAIL_COND_V(!texture.driver_id, RID()); + texture.slice_trackers.clear(); + + if (texture.draw_tracker != nullptr) { + texture.draw_tracker->reference_count++; + } + texture.owner = p_with_texture; RID id = texture_owner.make_rid(texture); #ifdef DEV_ENABLED @@ -988,23 +838,6 @@ RID RenderingDevice::texture_create_from_extension(TextureType p_type, DataForma texture.allowed_shared_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM); texture.allowed_shared_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB); - // Set base layout based on usage priority. - - if (p_usage.has_flag(TEXTURE_USAGE_SAMPLING_BIT)) { - // First priority, readable. - texture.layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } else if (p_usage.has_flag(TEXTURE_USAGE_STORAGE_BIT)) { - // Second priority, storage. - texture.layout = RDD::TEXTURE_LAYOUT_GENERAL; - } else if (p_usage.has_flag(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - // Third priority, color or depth. - texture.layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } else if (p_usage.has_flag(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - texture.layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } else { - texture.layout = RDD::TEXTURE_LAYOUT_GENERAL; - } - if (p_usage.has_flag(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT); texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT); @@ -1019,19 +852,7 @@ RID RenderingDevice::texture_create_from_extension(TextureType p_type, DataForma texture.driver_id = driver->texture_create_from_extension(p_image, p_type, p_format, p_layers, (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)); ERR_FAIL_COND_V(!texture.driver_id, RID()); - // Barrier to set layout. - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::TextureBarrier tb; - tb.texture = texture.driver_id; - tb.dst_access = RDD::BARRIER_ACCESS_SHADER_READ_BIT; - tb.prev_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; - tb.next_layout = texture.layout; - tb.subresources.aspect = texture.barrier_aspect_flags; - tb.subresources.mipmap_count = texture.mipmaps; - tb.subresources.layer_count = texture.layers; - - driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT, RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT, {}, {}, tb); - } + _texture_make_mutable(&texture, RID()); RID id = texture_owner.make_rid(texture); #ifdef DEV_ENABLED @@ -1081,6 +902,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, } Texture texture = *src_texture; + get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height); texture.mipmaps = p_mipmaps; texture.layers = slice_layers; @@ -1118,7 +940,17 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, texture.driver_id = driver->texture_create_shared_from_slice(src_texture->driver_id, tv, p_slice_type, p_layer, slice_layers, p_mipmap, p_mipmaps); ERR_FAIL_COND_V(!texture.driver_id, RID()); + const Rect2i slice_rect(p_mipmap, p_layer, p_mipmaps, slice_layers); texture.owner = p_with_texture; + texture.slice_type = p_slice_type; + texture.slice_rect = slice_rect; + + // If parent is mutable, make slice mutable by default. + if (src_texture->draw_tracker != nullptr) { + texture.draw_tracker = nullptr; + _texture_make_mutable(&texture, RID()); + } + RID id = texture_owner.make_rid(texture); #ifdef DEV_ENABLED set_resource_name(id, "RID:" + itos(id.get_id())); @@ -1128,8 +960,8 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, return id; } -Error RenderingDevice::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier) { - return _texture_update(p_texture, p_layer, p_data, p_post_barrier, false); +Error RenderingDevice::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data) { + return _texture_update(p_texture, p_layer, p_data, false, true); } static _ALWAYS_INLINE_ void _copy_region(uint8_t const *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_x, uint32_t p_src_y, uint32_t p_src_w, uint32_t p_src_h, uint32_t p_src_full_w, uint32_t p_dst_pitch, uint32_t p_unit_size) { @@ -1148,7 +980,7 @@ static _ALWAYS_INLINE_ void _copy_region(uint8_t const *__restrict p_src, uint8_ } } -Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier, bool p_use_setup_queue) { +Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, bool p_use_setup_queue, bool p_validate_can_update) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V_MSG((draw_list || compute_list) && !p_use_setup_queue, ERR_INVALID_PARAMETER, @@ -1166,7 +998,7 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve ERR_FAIL_COND_V_MSG(texture->bound, ERR_CANT_ACQUIRE_RESOURCE, "Texture can't be updated while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to update this texture."); - ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_CAN_UPDATE_BIT), ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(p_validate_can_update && !(texture->usage_flags & TEXTURE_USAGE_CAN_UPDATE_BIT), ERR_INVALID_PARAMETER, "Texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT` to be set to be updatable."); uint32_t layer_count = texture->layers; @@ -1191,21 +1023,22 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve const uint8_t *r = p_data.ptr(); - RDD::CommandBufferID command_buffer = p_use_setup_queue ? frames[frame].setup_command_buffer : frames[frame].draw_command_buffer; + thread_local LocalVector<RDG::RecordedBufferToTextureCopy> command_buffer_to_texture_copies_vector; + command_buffer_to_texture_copies_vector.clear(); - // Barrier to transfer. - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + if (p_use_setup_queue && driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + // When using the setup queue directly, we transition the texture to the optimal layout. RDD::TextureBarrier tb; tb.texture = texture->driver_id; tb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - tb.prev_layout = texture->layout; + tb.prev_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; tb.next_layout = RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL; tb.subresources.aspect = texture->barrier_aspect_flags; tb.subresources.mipmap_count = texture->mipmaps; tb.subresources.base_layer = p_layer; tb.subresources.layer_count = 1; - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb); + driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb); } uint32_t mipmap_offset = 0; @@ -1240,12 +1073,26 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP); region_pitch = STEPIFY(region_pitch, pitch_step); uint32_t to_allocate = region_pitch * region_h; - uint32_t alloc_offset = 0, alloc_size = 0; - Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false); + StagingRequiredAction required_action; + Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, required_action, false); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); - uint8_t *write_ptr = nullptr; + if (!p_use_setup_queue && !command_buffer_to_texture_copies_vector.is_empty() && required_action == STAGING_REQUIRED_ACTION_FLUSH_CURRENT) { + if (_texture_make_mutable(texture, p_texture)) { + // The texture must be mutable to be used as a copy destination. + draw_graph.add_synchronization(); + } + + // If we're using the draw queue and the staging buffer requires flushing everything, we submit the command early and clear the current vector. + draw_graph.add_texture_update(texture->driver_id, texture->draw_tracker, command_buffer_to_texture_copies_vector); + command_buffer_to_texture_copies_vector.clear(); + } + + _staging_buffer_execute_required_action(required_action); + + uint8_t *write_ptr; + { // Map. uint8_t *data_ptr = driver->buffer_map(staging_buffer_blocks[staging_buffer_current].driver_id); ERR_FAIL_NULL_V(data_ptr, ERR_CANT_CREATE); @@ -1288,7 +1135,14 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve copy_region.texture_offset = Vector3i(x, y, z); copy_region.texture_region_size = Vector3i(region_logic_w, region_logic_h, 1); - driver->command_copy_buffer_to_texture(command_buffer, staging_buffer_blocks[staging_buffer_current].driver_id, texture->driver_id, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, copy_region); + if (p_use_setup_queue) { + driver->command_copy_buffer_to_texture(frames[frame].setup_command_buffer, staging_buffer_blocks[staging_buffer_current].driver_id, texture->driver_id, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, copy_region); + } else { + RDG::RecordedBufferToTextureCopy buffer_to_texture_copy; + buffer_to_texture_copy.from_buffer = staging_buffer_blocks[staging_buffer_current].driver_id; + buffer_to_texture_copy.region = copy_region; + command_buffer_to_texture_copies_vector.push_back(buffer_to_texture_copy); + } staging_buffer_blocks.write[staging_buffer_current].fill_amount = alloc_offset + alloc_size; } @@ -1300,50 +1154,25 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve logic_height = MAX(1u, logic_height >> 1); } - // Barrier to restore layout. - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - BitField<RDD::PipelineStageBits> stages; - BitField<RDD::BarrierAccessBits> access; - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT); - } - - if (stages.is_empty()) { - stages.set_flag(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - } - + if (p_use_setup_queue && (texture->draw_tracker == nullptr) && driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + // If the texture does not have a tracker, it means it must be transitioned to the sampling state. RDD::TextureBarrier tb; tb.texture = texture->driver_id; tb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - tb.dst_access = access; tb.prev_layout = RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL; - tb.next_layout = texture->layout; + tb.next_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; tb.subresources.aspect = texture->barrier_aspect_flags; tb.subresources.mipmap_count = texture->mipmaps; tb.subresources.base_layer = p_layer; tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, stages, {}, {}, tb); - - if (texture->used_in_frame != frames_drawn) { - texture->used_in_raster = false; - texture->used_in_compute = false; - texture->used_in_frame = frames_drawn; + driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, {}, {}, tb); + } else if (!p_use_setup_queue && !command_buffer_to_texture_copies_vector.is_empty()) { + if (_texture_make_mutable(texture, p_texture)) { + // The texture must be mutable to be used as a copy destination. + draw_graph.add_synchronization(); } - texture->used_in_transfer = true; + + draw_graph.add_texture_update(texture->driver_id, texture->draw_tracker, command_buffer_to_texture_copies_vector); } return OK; @@ -1455,103 +1284,71 @@ Vector<uint8_t> RenderingDevice::texture_get_data(RID p_texture, uint32_t p_laye RDD::BufferID tmp_buffer = driver->buffer_create(work_buffer_size, RDD::BUFFER_USAGE_TRANSFER_TO_BIT, RDD::MEMORY_ALLOCATION_TYPE_CPU); ERR_FAIL_COND_V(!tmp_buffer, Vector<uint8_t>()); - RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer; // Makes more sense to retrieve. - - // Pre-copy barrier. - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::TextureBarrier tb; - tb.texture = tex->driver_id; - tb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_READ_BIT; - tb.prev_layout = tex->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL; - tb.subresources.aspect = tex->barrier_aspect_flags; - tb.subresources.mipmap_count = tex->mipmaps; - tb.subresources.base_layer = p_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb); - } + thread_local LocalVector<RDD::BufferTextureCopyRegion> command_buffer_texture_copy_regions_vector; + command_buffer_texture_copy_regions_vector.clear(); - { - uint32_t w = tex->width; - uint32_t h = tex->height; - uint32_t d = tex->depth; - for (uint32_t i = 0; i < tex->mipmaps; i++) { - RDD::BufferTextureCopyRegion copy_region; - copy_region.buffer_offset = mip_layouts[i].offset; - copy_region.texture_subresources.aspect = tex->read_aspect_flags; - copy_region.texture_subresources.mipmap = i; - copy_region.texture_subresources.base_layer = p_layer; - copy_region.texture_subresources.layer_count = 1; - copy_region.texture_region_size.x = w; - copy_region.texture_region_size.y = h; - copy_region.texture_region_size.z = d; - driver->command_copy_texture_to_buffer(command_buffer, tex->driver_id, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, tmp_buffer, copy_region); - - w = MAX(1u, w >> 1); - h = MAX(1u, h >> 1); - d = MAX(1u, d >> 1); - } + uint32_t w = tex->width; + uint32_t h = tex->height; + uint32_t d = tex->depth; + for (uint32_t i = 0; i < tex->mipmaps; i++) { + RDD::BufferTextureCopyRegion copy_region; + copy_region.buffer_offset = mip_layouts[i].offset; + copy_region.texture_subresources.aspect = tex->read_aspect_flags; + copy_region.texture_subresources.mipmap = i; + copy_region.texture_subresources.base_layer = p_layer; + copy_region.texture_subresources.layer_count = 1; + copy_region.texture_region_size.x = w; + copy_region.texture_region_size.y = h; + copy_region.texture_region_size.z = d; + command_buffer_texture_copy_regions_vector.push_back(copy_region); + + w = MAX(1u, w >> 1); + h = MAX(1u, h >> 1); + d = MAX(1u, d >> 1); } - // Post-copy barrier. - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::TextureBarrier tb; - tb.texture = tex->driver_id; - tb.src_access = RDD::BARRIER_ACCESS_TRANSFER_READ_BIT; - tb.dst_access = RDD::BARRIER_ACCESS_SHADER_READ_BIT; - if ((tex->usage_flags & TEXTURE_USAGE_STORAGE_BIT)) { - tb.dst_access.set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - tb.prev_layout = RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL; - tb.next_layout = tex->layout; - tb.subresources.aspect = tex->barrier_aspect_flags; - tb.subresources.mipmap_count = tex->mipmaps; - tb.subresources.base_layer = p_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT | RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, {}, {}, tb); + if (_texture_make_mutable(tex, p_texture)) { + // The texture must be mutable to be used as a copy source due to layout transitions. + draw_graph.add_synchronization(); } + draw_graph.add_texture_get_data(tex->driver_id, tex->draw_tracker, tmp_buffer, command_buffer_texture_copy_regions_vector); + _flush(true); const uint8_t *read_ptr = driver->buffer_map(tmp_buffer); ERR_FAIL_NULL_V(read_ptr, Vector<uint8_t>()); Vector<uint8_t> buffer_data; - { - uint32_t tight_buffer_size = get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps); - buffer_data.resize(tight_buffer_size); - - uint8_t *write_ptr = buffer_data.ptrw(); - - uint32_t w = tex->width; - uint32_t h = tex->height; - uint32_t d = tex->depth; - for (uint32_t i = 0; i < tex->mipmaps; i++) { - uint32_t width = 0, height = 0, depth = 0; - uint32_t tight_mip_size = get_image_format_required_size(tex->format, w, h, d, 1, &width, &height, &depth); - uint32_t block_w = 0, block_h = 0; - get_compressed_image_format_block_dimensions(tex->format, block_w, block_h); - uint32_t tight_row_pitch = tight_mip_size / ((height / block_h) * depth); - - { - // Copy row-by-row to erase padding due to alignments. - const uint8_t *rp = read_ptr; - uint8_t *wp = write_ptr; - for (uint32_t row = h * d / block_h; row != 0; row--) { - memcpy(wp, rp, tight_row_pitch); - rp += mip_layouts[i].row_pitch; - wp += tight_row_pitch; - } - } + uint32_t tight_buffer_size = get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps); + buffer_data.resize(tight_buffer_size); + + uint8_t *write_ptr = buffer_data.ptrw(); - w = MAX(1u, w >> 1); - h = MAX(1u, h >> 1); - d = MAX(1u, d >> 1); - read_ptr += mip_layouts[i].size; - write_ptr += tight_mip_size; + w = tex->width; + h = tex->height; + d = tex->depth; + for (uint32_t i = 0; i < tex->mipmaps; i++) { + uint32_t width = 0, height = 0, depth = 0; + uint32_t tight_mip_size = get_image_format_required_size(tex->format, w, h, d, 1, &width, &height, &depth); + uint32_t block_w = 0, block_h = 0; + get_compressed_image_format_block_dimensions(tex->format, block_w, block_h); + uint32_t tight_row_pitch = tight_mip_size / ((height / block_h) * depth); + + // Copy row-by-row to erase padding due to alignments. + const uint8_t *rp = read_ptr; + uint8_t *wp = write_ptr; + for (uint32_t row = h * d / block_h; row != 0; row--) { + memcpy(wp, rp, tight_row_pitch); + rp += mip_layouts[i].row_pitch; + wp += tight_row_pitch; } + + w = MAX(1u, w >> 1); + h = MAX(1u, h >> 1); + d = MAX(1u, d >> 1); + read_ptr += mip_layouts[i].size; + write_ptr += tight_mip_size; } driver->buffer_unmap(tmp_buffer); @@ -1610,7 +1407,7 @@ uint64_t RenderingDevice::texture_get_native_handle(RID p_texture) { } #endif -Error RenderingDevice::texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier) { +Error RenderingDevice::texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer) { _THREAD_SAFE_METHOD_ Texture *src_tex = texture_owner.get_or_null(p_from_texture); @@ -1658,133 +1455,34 @@ Error RenderingDevice::texture_copy(RID p_from_texture, RID p_to_texture, const ERR_FAIL_COND_V_MSG(src_tex->read_aspect_flags != dst_tex->read_aspect_flags, ERR_INVALID_PARAMETER, "Source and destination texture must be of the same type (color or depth)."); - RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer; - - // PRE Copy the image. - - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - { // Source. - RDD::TextureBarrier tb; - tb.texture = src_tex->driver_id; - tb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_READ_BIT; - tb.prev_layout = src_tex->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL; - tb.subresources.aspect = src_tex->barrier_aspect_flags; - tb.subresources.base_mipmap = p_src_mipmap; - tb.subresources.mipmap_count = 1; - tb.subresources.base_layer = p_src_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb); - } - { // Dest. - RDD::TextureBarrier tb; - tb.texture = dst_tex->driver_id; - tb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - tb.prev_layout = dst_tex->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL; - tb.subresources.aspect = dst_tex->read_aspect_flags; - tb.subresources.base_mipmap = p_dst_mipmap; - tb.subresources.mipmap_count = 1; - tb.subresources.base_layer = p_dst_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb); - } - } - - // COPY. - - { - RDD::TextureCopyRegion copy_region; - copy_region.src_subresources.aspect = src_tex->read_aspect_flags; - copy_region.src_subresources.mipmap = p_src_mipmap; - copy_region.src_subresources.base_layer = p_src_layer; - copy_region.src_subresources.layer_count = 1; - copy_region.src_offset = p_from; + RDD::TextureCopyRegion copy_region; + copy_region.src_subresources.aspect = src_tex->read_aspect_flags; + copy_region.src_subresources.mipmap = p_src_mipmap; + copy_region.src_subresources.base_layer = p_src_layer; + copy_region.src_subresources.layer_count = 1; + copy_region.src_offset = p_from; - copy_region.dst_subresources.aspect = dst_tex->read_aspect_flags; - copy_region.dst_subresources.mipmap = p_dst_mipmap; - copy_region.dst_subresources.base_layer = p_dst_layer; - copy_region.dst_subresources.layer_count = 1; - copy_region.dst_offset = p_to; + copy_region.dst_subresources.aspect = dst_tex->read_aspect_flags; + copy_region.dst_subresources.mipmap = p_dst_mipmap; + copy_region.dst_subresources.base_layer = p_dst_layer; + copy_region.dst_subresources.layer_count = 1; + copy_region.dst_offset = p_to; - copy_region.size = p_size; + copy_region.size = p_size; - driver->command_copy_texture(command_buffer, src_tex->driver_id, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_tex->driver_id, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, copy_region); + // The textures must be mutable to be used in the copy operation. + bool src_made_mutable = _texture_make_mutable(src_tex, p_from_texture); + bool dst_made_mutable = _texture_make_mutable(dst_tex, p_to_texture); + if (src_made_mutable || dst_made_mutable) { + draw_graph.add_synchronization(); } - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - // RESTORE LAYOUT for SRC and DST. - - BitField<RDD::PipelineStageBits> stages; - BitField<RDD::BarrierAccessBits> access; - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT); - } - - if (stages.is_empty()) { - stages.set_flag(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - } - - { // Restore src. - RDD::TextureBarrier tb; - tb.texture = src_tex->driver_id; - tb.src_access = RDD::BARRIER_ACCESS_TRANSFER_READ_BIT; - tb.dst_access = access; - tb.prev_layout = RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL; - tb.next_layout = src_tex->layout; - tb.subresources.aspect = src_tex->barrier_aspect_flags; - tb.subresources.base_mipmap = p_src_mipmap; - tb.subresources.mipmap_count = 1; - tb.subresources.base_layer = p_src_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, stages, {}, {}, tb); - } - - { // Make dst readable. - - RDD::TextureBarrier tb; - tb.texture = dst_tex->driver_id; - tb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - tb.dst_access = access; - tb.prev_layout = RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL; - tb.next_layout = dst_tex->layout; - tb.subresources.aspect = dst_tex->read_aspect_flags; - tb.subresources.base_mipmap = p_dst_mipmap; - tb.subresources.mipmap_count = 1; - tb.subresources.base_layer = p_dst_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, stages, {}, {}, tb); - } - - if (dst_tex->used_in_frame != frames_drawn) { - dst_tex->used_in_raster = false; - dst_tex->used_in_compute = false; - dst_tex->used_in_frame = frames_drawn; - } - dst_tex->used_in_transfer = true; - } + draw_graph.add_texture_copy(src_tex->driver_id, src_tex->draw_tracker, dst_tex->driver_id, dst_tex->draw_tracker, copy_region); return OK; } -Error RenderingDevice::texture_resolve_multisample(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier) { +Error RenderingDevice::texture_resolve_multisample(RID p_from_texture, RID p_to_texture) { _THREAD_SAFE_METHOD_ Texture *src_tex = texture_owner.get_or_null(p_from_texture); @@ -1815,108 +1513,19 @@ Error RenderingDevice::texture_resolve_multisample(RID p_from_texture, RID p_to_ ERR_FAIL_COND_V_MSG(src_tex->read_aspect_flags != dst_tex->read_aspect_flags, ERR_INVALID_PARAMETER, "Source and destination texture must be of the same type (color or depth)."); - RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer; - - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - // PRE Copy the image. - - { // Source. - RDD::TextureBarrier tb; - tb.texture = src_tex->driver_id; - tb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_READ_BIT; - tb.prev_layout = src_tex->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL; - tb.subresources.aspect = src_tex->barrier_aspect_flags; - tb.subresources.base_mipmap = src_tex->base_mipmap; - tb.subresources.mipmap_count = 1; - tb.subresources.base_layer = src_tex->base_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb); - } - { // Dest. - RDD::TextureBarrier tb; - tb.texture = dst_tex->driver_id; - tb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - tb.prev_layout = dst_tex->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL; - tb.subresources.aspect = dst_tex->barrier_aspect_flags; - tb.subresources.base_mipmap = dst_tex->base_mipmap; - tb.subresources.mipmap_count = 1; - tb.subresources.base_layer = dst_tex->base_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb); - } + // The textures must be mutable to be used in the resolve operation. + bool src_made_mutable = _texture_make_mutable(src_tex, p_from_texture); + bool dst_made_mutable = _texture_make_mutable(dst_tex, p_to_texture); + if (src_made_mutable || dst_made_mutable) { + draw_graph.add_synchronization(); } - // RESOLVE. - driver->command_resolve_texture(command_buffer, src_tex->driver_id, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, src_tex->base_layer, src_tex->base_mipmap, dst_tex->driver_id, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_tex->base_layer, dst_tex->base_mipmap); - - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - // RESTORE LAYOUT for SRC and DST. - - BitField<RDD::PipelineStageBits> stages; - BitField<RDD::BarrierAccessBits> access; - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT); - } - - if (stages.is_empty()) { - stages.set_flag(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - } - - { // Restore src. - RDD::TextureBarrier tb; - tb.texture = src_tex->driver_id; - tb.src_access = RDD::BARRIER_ACCESS_TRANSFER_READ_BIT; - tb.dst_access = access; - tb.prev_layout = RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL; - tb.next_layout = src_tex->layout; - tb.subresources.aspect = src_tex->barrier_aspect_flags; - tb.subresources.base_mipmap = src_tex->base_mipmap; - tb.subresources.mipmap_count = 1; - tb.subresources.base_layer = src_tex->base_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT, stages, {}, {}, tb); - } - - { // Make dst readable. - - RDD::TextureBarrier tb; - tb.texture = dst_tex->driver_id; - tb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - tb.dst_access = access; - tb.prev_layout = RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL; - tb.next_layout = dst_tex->layout; - tb.subresources.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT; - tb.subresources.base_mipmap = dst_tex->base_mipmap; - tb.subresources.mipmap_count = 1; - tb.subresources.base_layer = dst_tex->base_layer; - tb.subresources.layer_count = 1; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, stages, {}, {}, tb); - } - } + draw_graph.add_texture_resolve(src_tex->driver_id, src_tex->draw_tracker, dst_tex->driver_id, dst_tex->draw_tracker, src_tex->base_layer, src_tex->base_mipmap, dst_tex->base_layer, dst_tex->base_mipmap); return OK; } -Error RenderingDevice::texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier) { +Error RenderingDevice::texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers) { _THREAD_SAFE_METHOD_ Texture *src_tex = texture_owner.get_or_null(p_texture); @@ -1939,33 +1548,6 @@ Error RenderingDevice::texture_clear(RID p_texture, const Color &p_color, uint32 ERR_FAIL_COND_V(p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_base_layer + p_layers > src_layer_count, ERR_INVALID_PARAMETER); - RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer; - - RDD::TextureLayout clear_layout = (src_tex->layout == RDD::TEXTURE_LAYOUT_GENERAL) ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL; - - // NOTE: Perhaps the valid stages/accesses for a given owner should be a property of the owner. (Here and places like _get_buffer_from_owner.) - const BitField<RDD::PipelineStageBits> valid_texture_stages = RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT | RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT; - constexpr BitField<RDD::BarrierAccessBits> read_access = RDD::BARRIER_ACCESS_SHADER_READ_BIT; - constexpr BitField<RDD::BarrierAccessBits> read_write_access = RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT; - const BitField<RDD::BarrierAccessBits> valid_texture_access = (src_tex->usage_flags & TEXTURE_USAGE_STORAGE_BIT) ? read_write_access : read_access; - - // Barrier from previous access with optional layout change (see clear_layout logic above). - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::TextureBarrier tb; - tb.texture = src_tex->driver_id; - tb.src_access = valid_texture_access; - tb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - tb.prev_layout = src_tex->layout; - tb.next_layout = clear_layout; - tb.subresources.aspect = src_tex->read_aspect_flags; - tb.subresources.base_mipmap = src_tex->base_mipmap + p_base_mipmap; - tb.subresources.mipmap_count = p_mipmaps; - tb.subresources.base_layer = src_tex->base_layer + p_base_layer; - tb.subresources.layer_count = p_layers; - - driver->command_pipeline_barrier(command_buffer, valid_texture_stages, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb); - } - RDD::TextureSubresourceRange range; range.aspect = src_tex->read_aspect_flags; range.base_mipmap = src_tex->base_mipmap + p_base_mipmap; @@ -1973,55 +1555,13 @@ Error RenderingDevice::texture_clear(RID p_texture, const Color &p_color, uint32 range.base_layer = src_tex->base_layer + p_base_layer; range.layer_count = p_layers; - driver->command_clear_color_texture(command_buffer, src_tex->driver_id, clear_layout, p_color, range); - - // Barrier to post clear accesses (changing back the layout if needed). - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - BitField<RDD::PipelineStageBits> stages; - BitField<RDD::BarrierAccessBits> access; - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT); - } - - if (stages.is_empty()) { - stages.set_flag(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - } - - RDD::TextureBarrier tb; - tb.texture = src_tex->driver_id; - tb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - tb.dst_access = access; - tb.prev_layout = clear_layout; - tb.next_layout = src_tex->layout; - tb.subresources.aspect = src_tex->read_aspect_flags; - tb.subresources.base_mipmap = src_tex->base_mipmap + p_base_mipmap; - tb.subresources.mipmap_count = p_mipmaps; - tb.subresources.base_layer = src_tex->base_layer + p_base_layer; - tb.subresources.layer_count = p_layers; - - driver->command_pipeline_barrier(command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, stages, {}, {}, tb); - - if (src_tex->used_in_frame != frames_drawn) { - src_tex->used_in_raster = false; - src_tex->used_in_compute = false; - src_tex->used_in_frame = frames_drawn; - } - src_tex->used_in_transfer = true; + if (_texture_make_mutable(src_tex, p_texture)) { + // The texture must be mutable to be used as a clear destination. + draw_graph.add_synchronization(); } + draw_graph.add_texture_clear(src_tex->driver_id, src_tex->draw_tracker, p_color, range); + return OK; } @@ -2040,6 +1580,30 @@ bool RenderingDevice::texture_is_format_supported_for_usage(DataFormat p_format, /**** FRAMEBUFFER ****/ /*********************/ +static RDD::AttachmentLoadOp initial_action_to_load_op(RenderingDevice::InitialAction p_action) { + switch (p_action) { + case RenderingDevice::INITIAL_ACTION_LOAD: + return RDD::ATTACHMENT_LOAD_OP_LOAD; + case RenderingDevice::INITIAL_ACTION_CLEAR: + return RDD::ATTACHMENT_LOAD_OP_CLEAR; + case RenderingDevice::INITIAL_ACTION_DISCARD: + return RDD::ATTACHMENT_LOAD_OP_DONT_CARE; + default: + ERR_FAIL_V_MSG(RDD::ATTACHMENT_LOAD_OP_DONT_CARE, "Invalid initial action value (" + itos(p_action) + ")"); + } +} + +static RDD::AttachmentStoreOp final_action_to_store_op(RenderingDevice::FinalAction p_action) { + switch (p_action) { + case RenderingDevice::FINAL_ACTION_STORE: + return RDD::ATTACHMENT_STORE_OP_STORE; + case RenderingDevice::FINAL_ACTION_DISCARD: + return RDD::ATTACHMENT_STORE_OP_DONT_CARE; + default: + ERR_FAIL_V_MSG(RDD::ATTACHMENT_STORE_OP_DONT_CARE, "Invalid final action value (" + itos(p_action) + ")"); + } +} + RDD::RenderPassID RenderingDevice::_render_pass_create(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, uint32_t p_view_count, Vector<TextureSamples> *r_samples) { // NOTE: // Before the refactor to RenderingDevice-RenderingDeviceDriver, there was commented out code to @@ -2077,209 +1641,40 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(const Vector<AttachmentFo description.format = p_attachments[i].format; description.samples = p_attachments[i].samples; - bool is_sampled = (p_attachments[i].usage_flags & TEXTURE_USAGE_SAMPLING_BIT); - bool is_storage = (p_attachments[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT); - bool is_depth = (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - // We can setup a framebuffer where we write to our VRS texture to set it up. // We make the assumption here that if our texture is actually used as our VRS attachment. // It is used as such for each subpass. This is fairly certain seeing the restrictions on subpasses. bool is_vrs = (p_attachments[i].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && i == p_passes[0].vrs_attachment; if (is_vrs) { - // For VRS we only read, there is no writing to this texture. description.load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; - description.initial_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; - } else { - // For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write. - // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs - // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that - // stage. - - switch (is_depth ? p_initial_depth_action : p_initial_action) { - case INITIAL_ACTION_CLEAR_REGION: - case INITIAL_ACTION_CLEAR: { - if ((p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - description.load_op = RDD::ATTACHMENT_LOAD_OP_CLEAR; - description.initial_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - } else if ((p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - description.load_op = RDD::ATTACHMENT_LOAD_OP_CLEAR; - description.initial_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_CLEAR; - } else { - description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.initial_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; // Don't care what is there. - } - } break; - case INITIAL_ACTION_KEEP: { - if ((p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - description.load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; - description.initial_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - } else if ((p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - description.load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; - description.initial_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; - } else { - description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.initial_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; // Don't care what is there. - } - } break; - case INITIAL_ACTION_DROP: { - if ((p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.initial_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - } else if ((p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.initial_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; // Don't care what is there. - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - } else { - description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.initial_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; // Don't care what is there. - } - } break; - case INITIAL_ACTION_CLEAR_REGION_CONTINUE: - case INITIAL_ACTION_CONTINUE: { - if ((p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - description.load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; - description.initial_layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - } else if ((p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - description.load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; - description.initial_layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; - } else { - description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.initial_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; // Don't care what is there. - } - } break; - default: { - ERR_FAIL_V(RDD::RenderPassID()); // Should never reach here. - } - } - } - - bool used_last = false; - - { - int last_pass = p_passes.size() - 1; - - if (is_depth) { - // Likely missing depth resolve? - if (p_passes[last_pass].depth_attachment == i) { - used_last = true; - } - } else if (is_vrs) { - if (p_passes[last_pass].vrs_attachment == i) { - used_last = true; - } - } else { - if (p_passes[last_pass].resolve_attachments.size()) { - // If using resolve attachments, check resolve attachments. - for (int j = 0; j < p_passes[last_pass].resolve_attachments.size(); j++) { - if (p_passes[last_pass].resolve_attachments[j] == i) { - used_last = true; - break; - } - } - } - if (!used_last) { - for (int j = 0; j < p_passes[last_pass].color_attachments.size(); j++) { - if (p_passes[last_pass].color_attachments[j] == i) { - used_last = true; - break; - } - } - } - } - - if (!used_last) { - for (int j = 0; j < p_passes[last_pass].preserve_attachments.size(); j++) { - if (p_passes[last_pass].preserve_attachments[j] == i) { - used_last = true; - break; - } - } - } - } - - FinalAction final_action = p_final_action; - FinalAction final_depth_action = p_final_depth_action; - - if (!used_last) { - if (is_depth) { - final_depth_action = FINAL_ACTION_DISCARD; - - } else { - final_action = FINAL_ACTION_DISCARD; - } - } - - if (is_vrs) { - // We don't change our VRS texture during this process. - description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; + description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_LOAD; description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; + description.initial_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; description.final_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } else { - switch (is_depth ? final_depth_action : final_action) { - case FINAL_ACTION_READ: { - if ((p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - description.store_op = RDD::ATTACHMENT_STORE_OP_STORE; - description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.final_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } else if ((p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - description.store_op = RDD::ATTACHMENT_STORE_OP_STORE; - description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_STORE; - description.final_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - } else { - description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - description.final_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; // Don't care what is there. - // TODO: What does this mean about the next usage (and thus appropriate dependency masks. - } - } break; - case FINAL_ACTION_DISCARD: { - if ((p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.final_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } else if ((p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.final_layout = is_sampled ? RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - } else { - description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.final_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; // Don't care what is there. - } - } break; - case FINAL_ACTION_CONTINUE: { - if ((p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - description.store_op = RDD::ATTACHMENT_STORE_OP_STORE; - description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.final_layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } else if ((p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - description.store_op = RDD::ATTACHMENT_STORE_OP_STORE; - description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_STORE; - description.final_layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } else { - description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; - description.final_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; // Don't care what is there. - } - - } break; - default: { - ERR_FAIL_V(RDD::RenderPassID()); // Should never reach here. - } + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.load_op = initial_action_to_load_op(p_initial_action); + description.store_op = final_action_to_store_op(p_final_action); + description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; + description.initial_layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + description.final_layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.load_op = initial_action_to_load_op(p_initial_depth_action); + description.store_op = final_action_to_store_op(p_final_depth_action); + description.stencil_load_op = initial_action_to_load_op(p_initial_depth_action); + description.stencil_store_op = final_action_to_store_op(p_final_depth_action); + description.initial_layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + description.final_layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + } else { + description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; + description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; + description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; + description.initial_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; + description.final_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; } } @@ -2465,7 +1860,7 @@ RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_ } Vector<TextureSamples> samples; - RDD::RenderPassID render_pass = _render_pass_create(p_attachments, p_passes, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, p_view_count, &samples); // Actions don't matter for this use case. + RDD::RenderPassID render_pass = _render_pass_create(p_attachments, p_passes, INITIAL_ACTION_CLEAR, FINAL_ACTION_STORE, INITIAL_ACTION_CLEAR, FINAL_ACTION_STORE, p_view_count, &samples); // Actions don't matter for this use case. if (!render_pass) { // Was likely invalid. return INVALID_ID; @@ -2701,18 +2096,14 @@ RID RenderingDevice::vertex_buffer_create(uint32_t p_size_bytes, const Vector<ui buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU); ERR_FAIL_COND_V(!buffer.driver_id, RID()); + // Vertex buffers are assumed to be immutable unless they don't have initial data or they've been marked for storage explicitly. + if (p_data.is_empty() || p_use_as_storage) { + buffer.draw_tracker = RDG::resource_tracker_create(); + buffer.draw_tracker->buffer_driver_id = buffer.driver_id; + } + if (p_data.size()) { - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - _buffer_update(&buffer, 0, r, data_size); - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::BufferBarrier bb; - bb.buffer = buffer.driver_id; - bb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - bb.dst_access = RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - bb.size = data_size; - driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT, {}, bb, {}); - } + _buffer_update(&buffer, RID(), 0, p_data.ptr(), p_data.size()); } buffer_memory += buffer.size; @@ -2809,6 +2200,12 @@ RID RenderingDevice::vertex_array_create(uint32_t p_vertex_count, VertexFormatID } vertex_array.buffers.push_back(buffer->driver_id); + + if (buffer->draw_tracker != nullptr) { + vertex_array.draw_trackers.push_back(buffer->draw_tracker); + } else { + vertex_array.untracked_buffers.insert(p_src_buffers[i]); + } } RID id = vertex_array_owner.make_rid(vertex_array); @@ -2863,18 +2260,14 @@ RID RenderingDevice::index_buffer_create(uint32_t p_index_count, IndexBufferForm index_buffer.driver_id = driver->buffer_create(index_buffer.size, index_buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU); ERR_FAIL_COND_V(!index_buffer.driver_id, RID()); + // Index buffers are assumed to be immutable unless they don't have initial data. + if (p_data.is_empty()) { + index_buffer.draw_tracker = RDG::resource_tracker_create(); + index_buffer.draw_tracker->buffer_driver_id = index_buffer.driver_id; + } + if (p_data.size()) { - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - _buffer_update(&index_buffer, 0, r, data_size); - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::BufferBarrier bb; - bb.buffer = index_buffer.driver_id; - bb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - bb.dst_access = RDD::BARRIER_ACCESS_INDEX_READ_BIT; - bb.size = data_size; - driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT, {}, bb, {}); - } + _buffer_update(&index_buffer, RID(), 0, p_data.ptr(), p_data.size()); } buffer_memory += index_buffer.size; @@ -2899,6 +2292,7 @@ RID RenderingDevice::index_array_create(RID p_index_buffer, uint32_t p_index_off IndexArray index_array; index_array.max_index = index_buffer->max_index; index_array.driver_id = index_buffer->driver_id; + index_array.draw_tracker = index_buffer->draw_tracker; index_array.offset = p_index_offset; index_array.indices = p_index_count; index_array.format = index_buffer->format; @@ -2991,6 +2385,29 @@ RID RenderingDevice::shader_create_from_bytecode(const Vector<uint8_t> &p_shader shader->set_formats.push_back(format); } + for (ShaderStage stage : shader_desc.stages) { + switch (stage) { + case SHADER_STAGE_VERTEX: + shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); + break; + case SHADER_STAGE_FRAGMENT: + shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + break; + case SHADER_STAGE_TESSELATION_CONTROL: + shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT); + break; + case SHADER_STAGE_TESSELATION_EVALUATION: + shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT); + break; + case SHADER_STAGE_COMPUTE: + shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); + break; + default: + DEV_ASSERT(false && "Unknown shader stage."); + break; + } + } + #ifdef DEV_ENABLED set_resource_name(id, "RID:" + itos(id.get_id())); #endif @@ -3025,18 +2442,14 @@ RID RenderingDevice::uniform_buffer_create(uint32_t p_size_bytes, const Vector<u buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU); ERR_FAIL_COND_V(!buffer.driver_id, RID()); + // Uniform buffers are assumed to be immutable unless they don't have initial data. + if (p_data.is_empty()) { + buffer.draw_tracker = RDG::resource_tracker_create(); + buffer.draw_tracker->buffer_driver_id = buffer.driver_id; + } + if (p_data.size()) { - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - _buffer_update(&buffer, 0, r, data_size); - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::BufferBarrier bb; - bb.buffer = buffer.driver_id; - bb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; - bb.dst_access = RDD::BARRIER_ACCESS_UNIFORM_READ_BIT; - bb.size = data_size; - driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT | RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, {}, bb, {}); - } + _buffer_update(&buffer, RID(), 0, p_data.ptr(), p_data.size()); } buffer_memory += buffer.size; @@ -3073,8 +2486,9 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p // Used for verification to make sure a uniform set does not use a framebuffer bound texture. LocalVector<UniformSet::AttachableTexture> attachable_textures; - Vector<Texture *> mutable_sampled_textures; - Vector<Texture *> mutable_storage_textures; + Vector<RDG::ResourceTracker *> draw_trackers; + Vector<RDG::ResourceUsage> draw_trackers_usage; + HashMap<RID, RDG::ResourceUsage> untracked_usage; for (uint32_t i = 0; i < set_uniform_count; i++) { const ShaderUniform &set_uniform = set_uniforms[i]; @@ -3126,7 +2540,8 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p RDD::SamplerID *sampler_driver_id = sampler_owner.get_or_null(uniform.get_id(j + 0)); ERR_FAIL_COND_V_MSG(!sampler_driver_id, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler."); - Texture *texture = texture_owner.get_or_null(uniform.get_id(j + 1)); + RID texture_id = uniform.get_id(j + 1); + Texture *texture = texture_owner.get_or_null(texture_id); ERR_FAIL_NULL_V_MSG(texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(), @@ -3139,8 +2554,11 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p attachable_textures.push_back(attachable_texture); } - if ((texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT)) { - mutable_sampled_textures.push_back(texture); + if (texture->draw_tracker != nullptr) { + draw_trackers.push_back(texture->draw_tracker); + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_SAMPLE); + } else { + untracked_usage[texture_id] = RDG::RESOURCE_USAGE_TEXTURE_SAMPLE; } DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner)); @@ -3159,7 +2577,8 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p } for (uint32_t j = 0; j < uniform.get_id_count(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); + RID texture_id = uniform.get_id(j); + Texture *texture = texture_owner.get_or_null(texture_id); ERR_FAIL_NULL_V_MSG(texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(), @@ -3172,8 +2591,11 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p attachable_textures.push_back(attachable_texture); } - if ((texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT)) { - mutable_sampled_textures.push_back(texture); + if (texture->draw_tracker != nullptr) { + draw_trackers.push_back(texture->draw_tracker); + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_SAMPLE); + } else { + untracked_usage[texture_id] = RDG::RESOURCE_USAGE_TEXTURE_SAMPLE; } DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner)); @@ -3191,7 +2613,8 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p } for (uint32_t j = 0; j < uniform.get_id_count(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); + RID texture_id = uniform.get_id(j); + Texture *texture = texture_owner.get_or_null(texture_id); ERR_FAIL_NULL_V_MSG(texture, RID(), "Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); @@ -3199,8 +2622,19 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), RID(), "Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_STORAGE_BIT usage flag set in order to be used as uniform."); - if ((texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT)) { - mutable_storage_textures.push_back(texture); + if (_texture_make_mutable(texture, texture_id)) { + // The texture must be mutable as a layout transition will be required. + draw_graph.add_synchronization(); + } + + if (texture->draw_tracker != nullptr) { + draw_trackers.push_back(texture->draw_tracker); + + if (set_uniform.writable) { + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE); + } else { + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_STORAGE_IMAGE_READ); + } } DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner)); @@ -3218,9 +2652,27 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p } for (uint32_t j = 0; j < uniform.get_id_count(); j++) { - Buffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j)); + RID buffer_id = uniform.get_id(j); + Buffer *buffer = texture_buffer_owner.get_or_null(buffer_id); ERR_FAIL_NULL_V_MSG(buffer, RID(), "Texture Buffer (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture buffer."); + if (set_uniform.writable && _buffer_make_mutable(buffer, buffer_id)) { + // The buffer must be mutable if it's used for writing. + draw_graph.add_synchronization(); + } + + if (buffer->draw_tracker != nullptr) { + draw_trackers.push_back(buffer->draw_tracker); + + if (set_uniform.writable) { + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE); + } else { + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ); + } + } else { + untracked_usage[buffer_id] = RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ; + } + driver_uniform.ids.push_back(buffer->driver_id); } } break; @@ -3237,9 +2689,17 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p RDD::SamplerID *sampler_driver_id = sampler_owner.get_or_null(uniform.get_id(j + 0)); ERR_FAIL_COND_V_MSG(!sampler_driver_id, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler."); - Buffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j + 1)); + RID buffer_id = uniform.get_id(j + 1); + Buffer *buffer = texture_buffer_owner.get_or_null(buffer_id); ERR_FAIL_NULL_V_MSG(buffer, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid texture buffer."); + if (buffer->draw_tracker != nullptr) { + draw_trackers.push_back(buffer->draw_tracker); + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ); + } else { + untracked_usage[buffer_id] = RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ; + } + driver_uniform.ids.push_back(*sampler_driver_id); driver_uniform.ids.push_back(buffer->driver_id); } @@ -3251,12 +2711,20 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided)."); - Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.get_id(0)); + RID buffer_id = uniform.get_id(0); + Buffer *buffer = uniform_buffer_owner.get_or_null(buffer_id); ERR_FAIL_NULL_V_MSG(buffer, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") is invalid."); ERR_FAIL_COND_V_MSG(buffer->size < (uint32_t)set_uniform.length, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " is smaller than size of shader uniform: (" + itos(set_uniform.length) + ")."); + if (buffer->draw_tracker != nullptr) { + draw_trackers.push_back(buffer->draw_tracker); + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_UNIFORM_BUFFER_READ); + } else { + untracked_usage[buffer_id] = RDG::RESOURCE_USAGE_UNIFORM_BUFFER_READ; + } + driver_uniform.ids.push_back(buffer->driver_id); } break; case UNIFORM_TYPE_STORAGE_BUFFER: { @@ -3265,10 +2733,11 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p Buffer *buffer = nullptr; - if (storage_buffer_owner.owns(uniform.get_id(0))) { - buffer = storage_buffer_owner.get_or_null(uniform.get_id(0)); - } else if (vertex_buffer_owner.owns(uniform.get_id(0))) { - buffer = vertex_buffer_owner.get_or_null(uniform.get_id(0)); + RID buffer_id = uniform.get_id(0); + if (storage_buffer_owner.owns(buffer_id)) { + buffer = storage_buffer_owner.get_or_null(buffer_id); + } else if (vertex_buffer_owner.owns(buffer_id)) { + buffer = vertex_buffer_owner.get_or_null(buffer_id); ERR_FAIL_COND_V_MSG(!(buffer->usage.has_flag(RDD::BUFFER_USAGE_STORAGE_BIT)), RID(), "Vertex buffer supplied (binding: " + itos(uniform.binding) + ") was not created with storage flag."); } @@ -3278,6 +2747,23 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p ERR_FAIL_COND_V_MSG(set_uniform.length > 0 && buffer->size != (uint32_t)set_uniform.length, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ")."); + if (set_uniform.writable && _buffer_make_mutable(buffer, buffer_id)) { + // The buffer must be mutable if it's used for writing. + draw_graph.add_synchronization(); + } + + if (buffer->draw_tracker != nullptr) { + draw_trackers.push_back(buffer->draw_tracker); + + if (set_uniform.writable) { + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE); + } else { + draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_STORAGE_BUFFER_READ); + } + } else { + untracked_usage[buffer_id] = RDG::RESOURCE_USAGE_STORAGE_BUFFER_READ; + } + driver_uniform.ids.push_back(buffer->driver_id); } break; case UNIFORM_TYPE_INPUT_ATTACHMENT: { @@ -3292,7 +2778,8 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p } for (uint32_t j = 0; j < uniform.get_id_count(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); + RID texture_id = uniform.get_id(j); + Texture *texture = texture_owner.get_or_null(texture_id); ERR_FAIL_NULL_V_MSG(texture, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); @@ -3302,6 +2789,17 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner)); + if (_texture_make_mutable(texture, texture_id)) { + // The texture must be mutable as a layout transition will be required. + draw_graph.add_synchronization(); + } + + if (texture->draw_tracker != nullptr) { + bool depth_stencil_read = (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + draw_trackers.push_back(texture->draw_tracker); + draw_trackers_usage.push_back(depth_stencil_read ? RDG::RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ : RDG::RESOURCE_USAGE_ATTACHMENT_COLOR_READ); + } + driver_uniform.ids.push_back(texture->driver_id); } } break; @@ -3317,8 +2815,9 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p uniform_set.driver_id = driver_uniform_set; uniform_set.format = shader->set_formats[p_shader_set]; uniform_set.attachable_textures = attachable_textures; - uniform_set.mutable_sampled_textures = mutable_sampled_textures; - uniform_set.mutable_storage_textures = mutable_storage_textures; + uniform_set.draw_trackers = draw_trackers; + uniform_set.draw_trackers_usage = draw_trackers_usage; + uniform_set.untracked_usage = untracked_usage; uniform_set.shader_set = p_shader_set; uniform_set.shader_id = p_shader; @@ -3486,6 +2985,7 @@ RID RenderingDevice::render_pipeline_create(RID p_shader, FramebufferFormatID p_ pipeline.shader_layout_hash = shader->layout_hash; pipeline.set_formats = shader->set_formats; pipeline.push_constant_size = shader->push_constant_size; + pipeline.stage_bits = shader->stage_bits; #ifdef DEBUG_ENABLED pipeline.validation.dynamic_state = p_dynamic_state_flags; @@ -3623,15 +3123,13 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayS ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time."); ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time."); - RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer; - if (!context->window_is_valid_swapchain(p_screen)) { return INVALID_ID; } - Size2i size = Size2i(context->window_get_width(p_screen), context->window_get_height(p_screen)); + Rect2i viewport = Rect2i(0, 0, context->window_get_width(p_screen), context->window_get_height(p_screen)); - _draw_list_allocate(Rect2i(Vector2i(), size), 0, 0); + _draw_list_allocate(viewport, 0); #ifdef DEBUG_ENABLED draw_list_framebuffer_format = screen_get_framebuffer_format(); #endif @@ -3639,16 +3137,11 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayS RDD::RenderPassClearValue clear_value; clear_value.color = p_clear_color; - driver->command_begin_render_pass( - command_buffer, - context->window_get_render_pass(p_screen), - context->window_get_framebuffer(p_screen), - RDD::COMMAND_BUFFER_TYPE_PRIMARY, - Rect2i(0, 0, size.width, size.height), - VectorView(&clear_value, 1)); - driver->command_render_set_viewport(command_buffer, Rect2i(Point2i(), size)); - driver->command_render_set_scissor(command_buffer, Rect2i(Point2i(), size)); + draw_graph.add_draw_list_begin(context->window_get_render_pass(p_screen), context->window_get_framebuffer(p_screen), viewport, clear_value, true, false); + + _draw_list_set_viewport(viewport); + _draw_list_set_scissor(viewport); return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT; } @@ -3694,8 +3187,12 @@ Error RenderingDevice::_draw_list_setup_framebuffer(Framebuffer *p_framebuffer, return OK; } -Error RenderingDevice::_draw_list_render_pass_begin(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i p_viewport_offset, Point2i p_viewport_size, RDD::FramebufferID p_framebuffer_driver_id, RDD::RenderPassID p_render_pass, RDD::CommandBufferID p_command_buffer, RDD::CommandBufferType p_cmd_buffer_mode, const Vector<RID> &p_storage_textures, bool p_constrained_to_region) { +Error RenderingDevice::_draw_list_render_pass_begin(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i p_viewport_offset, Point2i p_viewport_size, RDD::FramebufferID p_framebuffer_driver_id, RDD::RenderPassID p_render_pass) { LocalVector<RDD::RenderPassClearValue> clear_values; + LocalVector<RDG::ResourceTracker *> resource_trackers; + LocalVector<RDG::ResourceUsage> resource_usages; + bool uses_color = false; + bool uses_depth = false; clear_values.resize(p_framebuffer->texture_ids.size()); int clear_values_count = 0; { @@ -3709,69 +3206,33 @@ Error RenderingDevice::_draw_list_render_pass_begin(Framebuffer *p_framebuffer, continue; } - if (color_index < p_clear_colors.size() && texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - ERR_FAIL_INDEX_V(color_index, p_clear_colors.size(), ERR_BUG); // A bug. - clear_value.color = p_clear_colors[color_index]; - color_index++; + if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + if (color_index < p_clear_colors.size()) { + ERR_FAIL_INDEX_V(color_index, p_clear_colors.size(), ERR_BUG); // A bug. + clear_value.color = p_clear_colors[color_index]; + color_index++; + } + + resource_trackers.push_back(texture->draw_tracker); + resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE); + uses_color = true; } else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { clear_value.depth = p_clear_depth; clear_value.stencil = p_clear_stencil; + resource_trackers.push_back(texture->draw_tracker); + resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE); + uses_depth = true; } clear_values[clear_values_count++] = clear_value; } } - for (int i = 0; i < p_storage_textures.size(); i++) { - Texture *texture = texture_owner.get_or_null(p_storage_textures[i]); - if (!texture) { - continue; - } - ERR_CONTINUE_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), "Supplied storage texture " + itos(i) + " for draw list is not set to be used for storage."); - - if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) { - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - // Must change layout to general. - RDD::TextureBarrier tb; - tb.texture = texture->driver_id; - tb.src_access = (RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - tb.dst_access = (RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - tb.prev_layout = texture->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_GENERAL; - tb.subresources.aspect = texture->read_aspect_flags; - tb.subresources.base_mipmap = texture->base_mipmap; - tb.subresources.mipmap_count = texture->mipmaps; - tb.subresources.base_layer = texture->base_layer; - tb.subresources.layer_count = texture->layers; - - driver->command_pipeline_barrier(p_command_buffer, RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT, RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT, {}, {}, tb); - - texture->layout = RDD::TEXTURE_LAYOUT_GENERAL; - } - - draw_list_storage_textures.push_back(p_storage_textures[i]); - } - } - - Rect2i region; - if (p_constrained_to_region) { - region = Rect2i(p_viewport_offset, p_viewport_size); - } else { - region = Rect2i(Point2i(), p_framebuffer->size); - } - - driver->command_begin_render_pass( - p_command_buffer, - p_render_pass, - p_framebuffer_driver_id, - p_cmd_buffer_mode, - region, - clear_values); + draw_graph.add_draw_list_begin(p_render_pass, p_framebuffer_driver_id, Rect2i(p_viewport_offset, p_viewport_size), clear_values, uses_color, uses_depth); + draw_graph.add_draw_list_usages(resource_trackers, resource_usages); // Mark textures as bound. draw_list_bound_textures.clear(); - draw_list_unbind_color_textures = p_final_color_action != FINAL_ACTION_CONTINUE; - draw_list_unbind_depth_textures = p_final_depth_action != FINAL_ACTION_CONTINUE; for (int i = 0; i < p_framebuffer->texture_ids.size(); i++) { Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]); @@ -3785,6 +3246,14 @@ Error RenderingDevice::_draw_list_render_pass_begin(Framebuffer *p_framebuffer, return OK; } +void RenderingDevice::_draw_list_set_viewport(Rect2i p_rect) { + draw_graph.add_draw_list_set_viewport(p_rect); +} + +void RenderingDevice::_draw_list_set_scissor(Rect2i p_rect) { + draw_graph.add_draw_list_set_scissor(p_rect); +} + void RenderingDevice::_draw_list_insert_clear_region(DrawList *p_draw_list, Framebuffer *p_framebuffer, Point2i p_viewport_offset, Point2i p_viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) { LocalVector<RDD::AttachmentClear> clear_attachments; int color_index = 0; @@ -3818,24 +3287,19 @@ void RenderingDevice::_draw_list_insert_clear_region(DrawList *p_draw_list, Fram } Rect2i rect = Rect2i(p_viewport_offset, p_viewport_size); - - driver->command_render_clear_attachments(p_draw_list->command_buffer, clear_attachments, rect); + draw_graph.add_draw_list_clear_attachments(clear_attachments, rect); } -RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { +RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time."); - ERR_FAIL_COND_V_MSG(compute_list != nullptr && !compute_list->state.allow_draw_overlap, INVALID_ID, "Only one draw/compute list can be active at the same time."); Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer); ERR_FAIL_NULL_V(framebuffer, INVALID_ID); Point2i viewport_offset; Point2i viewport_size = framebuffer->size; - bool constrained_to_region = false; - bool needs_clear_color = false; - bool needs_clear_depth = false; if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { // Check custom region. Rect2i viewport(viewport_offset, viewport_size); @@ -3848,34 +3312,9 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, viewport_offset = regioni.position; viewport_size = regioni.size; - - // If clearing regions both in color and depth, we can switch to a fast path where we let Vulkan to the clears - // and we constrain the render area to the region. - if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION && p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) { - constrained_to_region = true; - p_initial_color_action = INITIAL_ACTION_CLEAR; - p_initial_depth_action = INITIAL_ACTION_CLEAR; - } else { - if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) { - needs_clear_color = true; - p_initial_color_action = INITIAL_ACTION_CONTINUE; - } - if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) { - needs_clear_depth = true; - p_initial_depth_action = INITIAL_ACTION_CONTINUE; - } - if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) { - needs_clear_color = true; - p_initial_color_action = INITIAL_ACTION_KEEP; - } - if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) { - needs_clear_depth = true; - p_initial_depth_action = INITIAL_ACTION_KEEP; - } - } } - if (p_initial_color_action == INITIAL_ACTION_CLEAR || needs_clear_color) { // Check clear values. + if (p_initial_color_action == INITIAL_ACTION_CLEAR) { // Check clear values. int color_count = 0; for (int i = 0; i < framebuffer->texture_ids.size(); i++) { Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]); @@ -3897,8 +3336,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, Error err = _draw_list_setup_framebuffer(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, &fb_driver_id, &render_pass, &draw_list_subpass_count); ERR_FAIL_COND_V(err != OK, INVALID_ID); - RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer; - err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, fb_driver_id, render_pass, command_buffer, RDD::COMMAND_BUFFER_TYPE_PRIMARY, p_storage_textures, constrained_to_region); + err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, fb_driver_id, render_pass); if (err != OK) { return INVALID_ID; @@ -3907,135 +3345,23 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, draw_list_render_pass = render_pass; draw_list_vkframebuffer = fb_driver_id; - _draw_list_allocate(Rect2i(viewport_offset, viewport_size), 0, 0); + _draw_list_allocate(Rect2i(viewport_offset, viewport_size), 0); #ifdef DEBUG_ENABLED draw_list_framebuffer_format = framebuffer->format_id; #endif draw_list_current_subpass = 0; - if (needs_clear_color || needs_clear_depth) { - DEV_ASSERT(!constrained_to_region); - _draw_list_insert_clear_region(draw_list, framebuffer, viewport_offset, viewport_size, needs_clear_color, p_clear_color_values, needs_clear_depth, p_clear_depth, p_clear_stencil); - } - - driver->command_render_set_viewport(command_buffer, Rect2i(viewport_offset, viewport_size)); - driver->command_render_set_scissor(command_buffer, Rect2i(viewport_offset, viewport_size)); + _draw_list_set_viewport(Rect2i(viewport_offset, viewport_size)); + _draw_list_set_scissor(Rect2i(viewport_offset, viewport_size)); return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT; } +#ifndef DISABLE_DEPRECATED Error RenderingDevice::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { - _THREAD_SAFE_METHOD_ - - ERR_FAIL_COND_V_MSG(draw_list != nullptr, ERR_BUSY, "Only one draw list can be active at the same time."); - ERR_FAIL_COND_V_MSG(compute_list != nullptr && !compute_list->state.allow_draw_overlap, ERR_BUSY, "Only one draw/compute list can be active at the same time."); - - ERR_FAIL_COND_V(p_splits < 1, ERR_INVALID_DECLARATION); - - Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer); - ERR_FAIL_NULL_V(framebuffer, ERR_INVALID_DECLARATION); - - Point2i viewport_offset; - Point2i viewport_size = framebuffer->size; - bool constrained_to_region = false; - bool needs_clear_color = false; - bool needs_clear_depth = false; - - if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { // Check custom region. - Rect2i viewport(viewport_offset, viewport_size); - Rect2i regioni = p_region; - if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) && - ((regioni.position.x + regioni.size.x) <= (viewport.position.x + viewport.size.x)) && - ((regioni.position.y + regioni.size.y) <= (viewport.position.y + viewport.size.y))) { - ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "When supplying a custom region, it must be contained within the framebuffer rectangle"); - } - - viewport_offset = regioni.position; - viewport_size = regioni.size; - - // If clearing regions both in color and depth, we can switch to a fast path where we let Vulkan to the clears - // and we constrain the render area to the region. - if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION && p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) { - constrained_to_region = true; - p_initial_color_action = INITIAL_ACTION_CLEAR; - p_initial_depth_action = INITIAL_ACTION_CLEAR; - } else { - if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) { - needs_clear_color = true; - p_initial_color_action = INITIAL_ACTION_CONTINUE; - } - if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) { - needs_clear_depth = true; - p_initial_depth_action = INITIAL_ACTION_CONTINUE; - } - if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) { - needs_clear_color = true; - p_initial_color_action = INITIAL_ACTION_KEEP; - } - if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) { - needs_clear_depth = true; - p_initial_depth_action = INITIAL_ACTION_KEEP; - } - } - } - - if (p_initial_color_action == INITIAL_ACTION_CLEAR || needs_clear_color) { // Check clear values. - - int color_count = 0; - for (int i = 0; i < framebuffer->texture_ids.size(); i++) { - Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]); - - if (!texture || !(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - color_count++; - } - } - - ERR_FAIL_COND_V_MSG(p_clear_color_values.size() != color_count, ERR_INVALID_PARAMETER, - "Clear color values supplied (" + itos(p_clear_color_values.size()) + ") differ from the amount required for framebuffer (" + itos(color_count) + ")."); - } - - RDD::FramebufferID fb_driver_id; - RDD::RenderPassID render_pass; - - Error err = _draw_list_setup_framebuffer(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, &fb_driver_id, &render_pass, &draw_list_subpass_count); - ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); - - RDD::CommandBufferID frame_command_buffer = frames[frame].draw_command_buffer; - err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, fb_driver_id, render_pass, frame_command_buffer, RDD::COMMAND_BUFFER_TYPE_SECONDARY, p_storage_textures, constrained_to_region); - - if (err != OK) { - return ERR_CANT_CREATE; - } - - draw_list_current_subpass = 0; - -#ifdef DEBUG_ENABLED - draw_list_framebuffer_format = framebuffer->format_id; -#endif - draw_list_render_pass = render_pass; - draw_list_vkframebuffer = fb_driver_id; - - err = _draw_list_allocate(Rect2i(viewport_offset, viewport_size), p_splits, 0); - if (err != OK) { - return err; - } - - if (needs_clear_color || needs_clear_depth) { - DEV_ASSERT(!constrained_to_region); - _draw_list_insert_clear_region(&draw_list[0], framebuffer, viewport_offset, viewport_size, needs_clear_color, p_clear_color_values, needs_clear_depth, p_clear_depth, p_clear_stencil); - } - - bool secondary_viewport_scissor = driver->api_trait_get(RDD::API_TRAIT_SECONDARY_VIEWPORT_SCISSOR); - for (uint32_t i = 0; i < p_splits; i++) { - if (secondary_viewport_scissor) { - driver->command_render_set_viewport(draw_list[i].command_buffer, Rect2i(viewport_offset, viewport_size)); - driver->command_render_set_scissor(draw_list[i].command_buffer, Rect2i(viewport_offset, viewport_size)); - } - r_split_ids[i] = (int64_t(ID_TYPE_SPLIT_DRAW_LIST) << ID_BASE_SHIFT) + i; - } - - return OK; + ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Deprecated. Split draw lists are used automatically by RenderingDevice."); } +#endif RenderingDevice::DrawList *RenderingDevice::_get_draw_list_ptr(DrawListID p_id) { if (p_id < 0) { @@ -4045,22 +3371,7 @@ RenderingDevice::DrawList *RenderingDevice::_get_draw_list_ptr(DrawListID p_id) if (!draw_list) { return nullptr; } else if (p_id == (int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT)) { - if (draw_list_split) { - return nullptr; - } return draw_list; - } else if (p_id >> DrawListID(ID_BASE_SHIFT) == ID_TYPE_SPLIT_DRAW_LIST) { - if (!draw_list_split) { - return nullptr; - } - - uint64_t index = p_id & ((DrawListID(1) << DrawListID(ID_BASE_SHIFT)) - 1); // Mask. - - if (index >= draw_list_count) { - return nullptr; - } - - return &draw_list[index]; } else { return nullptr; } @@ -4073,7 +3384,7 @@ void RenderingDevice::draw_list_set_blend_constants(DrawListID p_list, const Col ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); #endif - driver->command_render_set_blend_constants(dl->command_buffer, p_color); + draw_graph.add_draw_list_set_blend_constants(p_color); } void RenderingDevice::draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) { @@ -4095,7 +3406,7 @@ void RenderingDevice::draw_list_bind_render_pipeline(DrawListID p_list, RID p_re dl->state.pipeline = p_render_pipeline; - driver->command_bind_render_pipeline(dl->command_buffer, pipeline->driver_id); + draw_graph.add_draw_list_bind_pipeline(pipeline->driver_id, pipeline->stage_bits); if (dl->state.pipeline_shader != pipeline->shader) { // Shader changed, so descriptor sets may become incompatible. @@ -4125,7 +3436,7 @@ void RenderingDevice::draw_list_bind_render_pipeline(DrawListID p_list, RID p_re } for (uint32_t i = 0; i < pcount; i++) { - dl->state.sets[i].bound = i < first_invalid_set; + dl->state.sets[i].bound = dl->state.sets[i].bound && i < first_invalid_set; dl->state.sets[i].pipeline_expected_format = pformats[i]; } @@ -4183,21 +3494,6 @@ void RenderingDevice::draw_list_bind_uniform_set(DrawListID p_list, RID p_unifor dl->state.sets[p_index].uniform_set_format = uniform_set->format; dl->state.sets[p_index].uniform_set = p_uniform_set; - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - uint32_t mst_count = uniform_set->mutable_storage_textures.size(); - if (mst_count) { - Texture **mst_textures = const_cast<UniformSet *>(uniform_set)->mutable_storage_textures.ptrw(); - for (uint32_t i = 0; i < mst_count; i++) { - if (mst_textures[i]->used_in_frame != frames_drawn) { - mst_textures[i]->used_in_frame = frames_drawn; - mst_textures[i]->used_in_transfer = false; - mst_textures[i]->used_in_compute = false; - } - mst_textures[i]->used_in_raster = true; - } - } - } - #ifdef DEBUG_ENABLED { // Validate that textures bound are not attached as framebuffer bindings. uint32_t attachable_count = uniform_set->attachable_textures.size(); @@ -4235,7 +3531,12 @@ void RenderingDevice::draw_list_bind_vertex_array(DrawListID p_list, RID p_verte dl->validation.vertex_max_instances_allowed = vertex_array->max_instances_allowed; #endif dl->validation.vertex_array_size = vertex_array->vertex_count; - driver->command_render_bind_vertex_buffers(dl->command_buffer, vertex_array->buffers.size(), vertex_array->buffers.ptr(), vertex_array->offsets.ptr()); + + draw_graph.add_draw_list_bind_vertex_buffers(vertex_array->buffers, vertex_array->offsets); + + for (int i = 0; i < vertex_array->draw_trackers.size(); i++) { + draw_graph.add_draw_list_usage(vertex_array->draw_trackers[i], RDG::RESOURCE_USAGE_VERTEX_BUFFER_READ); + } } void RenderingDevice::draw_list_bind_index_array(DrawListID p_list, RID p_index_array) { @@ -4256,10 +3557,14 @@ void RenderingDevice::draw_list_bind_index_array(DrawListID p_list, RID p_index_ #ifdef DEBUG_ENABLED dl->validation.index_array_max_index = index_array->max_index; #endif - dl->validation.index_array_size = index_array->indices; - dl->validation.index_array_offset = index_array->offset; + dl->validation.index_array_count = index_array->indices; + + const uint64_t offset_bytes = index_array->offset * (index_array->format == INDEX_BUFFER_FORMAT_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t)); + draw_graph.add_draw_list_bind_index_buffer(index_array->driver_id, index_array->format, offset_bytes); - driver->command_render_bind_index_buffer(dl->command_buffer, index_array->driver_id, index_array->format, index_array->offset); + if (index_array->draw_tracker != nullptr) { + draw_graph.add_draw_list_usage(index_array->draw_tracker, RDG::RESOURCE_USAGE_INDEX_BUFFER_READ); + } } void RenderingDevice::draw_list_set_line_width(DrawListID p_list, float p_width) { @@ -4269,7 +3574,7 @@ void RenderingDevice::draw_list_set_line_width(DrawListID p_list, float p_width) ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); #endif - driver->command_render_set_line_width(dl->command_buffer, p_width); + draw_graph.add_draw_list_set_line_width(p_width); } void RenderingDevice::draw_list_set_push_constant(DrawListID p_list, const void *p_data, uint32_t p_data_size) { @@ -4284,7 +3589,9 @@ void RenderingDevice::draw_list_set_push_constant(DrawListID p_list, const void ERR_FAIL_COND_MSG(p_data_size != dl->validation.pipeline_push_constant_size, "This render pipeline requires (" + itos(dl->validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")"); #endif - driver->command_bind_push_constants(dl->command_buffer, dl->state.pipeline_shader_driver_id, 0, VectorView((const uint32_t *)p_data, p_data_size / sizeof(uint32_t))); + + draw_graph.add_draw_list_set_push_constant(dl->state.pipeline_shader_driver_id, p_data, p_data_size); + #ifdef DEBUG_ENABLED dl->validation.pipeline_push_constant_supplied = true; #endif @@ -4338,14 +3645,19 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint } } #endif - driver->command_uniform_set_prepare_for_use(dl->command_buffer, dl->state.sets[i].uniform_set_driver_id, dl->state.pipeline_shader_driver_id, i); + draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); } for (uint32_t i = 0; i < dl->state.set_count; i++) { if (dl->state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. } if (!dl->state.sets[i].bound) { - driver->command_bind_render_uniform_set(dl->command_buffer, dl->state.sets[i].uniform_set_driver_id, dl->state.pipeline_shader_driver_id, i); + // All good, see if this requires re-binding. + draw_graph.add_draw_list_bind_uniform_set(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + + UniformSet *uniform_set = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); + dl->state.sets[i].bound = true; } } @@ -4355,13 +3667,13 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint ERR_FAIL_COND_MSG(p_procedural_vertices > 0, "Procedural vertices can't be used together with indices."); - ERR_FAIL_COND_MSG(!dl->validation.index_array_size, + ERR_FAIL_COND_MSG(!dl->validation.index_array_count, "Draw command requested indices, but no index buffer was set."); ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices, "The usage of restart indices in index buffer does not match the render primitive in the pipeline."); #endif - uint32_t to_draw = dl->validation.index_array_size; + uint32_t to_draw = dl->validation.index_array_count; #ifdef DEBUG_ENABLED ERR_FAIL_COND_MSG(to_draw < dl->validation.pipeline_primitive_minimum, @@ -4370,7 +3682,8 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint ERR_FAIL_COND_MSG((to_draw % dl->validation.pipeline_primitive_divisor) != 0, "Index amount (" + itos(to_draw) + ") must be a multiple of the amount of indices required by the render primitive (" + itos(dl->validation.pipeline_primitive_divisor) + ")."); #endif - driver->command_render_draw_indexed(dl->command_buffer, to_draw, p_instances, dl->validation.index_array_offset, 0, 0); + + draw_graph.add_draw_list_draw_indexed(to_draw, p_instances, 0); } else { uint32_t to_draw; @@ -4396,7 +3709,7 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint "Vertex amount (" + itos(to_draw) + ") must be a multiple of the amount of vertices required by the render primitive (" + itos(dl->validation.pipeline_primitive_divisor) + ")."); #endif - driver->command_render_draw(dl->command_buffer, to_draw, p_instances, 0, 0); + draw_graph.add_draw_list_draw(to_draw, p_instances); } } @@ -4416,7 +3729,7 @@ void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p return; } - driver->command_render_set_scissor(dl->command_buffer, rect); + _draw_list_set_scissor(rect); } void RenderingDevice::draw_list_disable_scissor(DrawListID p_list) { @@ -4426,7 +3739,7 @@ void RenderingDevice::draw_list_disable_scissor(DrawListID p_list) { ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); #endif - driver->command_render_set_scissor(dl->command_buffer, dl->viewport); + _draw_list_set_scissor(dl->viewport); } uint32_t RenderingDevice::draw_list_get_current_pass() { @@ -4443,230 +3756,80 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_switch_to_next_pass() { Rect2i viewport; _draw_list_free(&viewport); - driver->command_next_render_subpass(frames[frame].draw_command_buffer, RDD::COMMAND_BUFFER_TYPE_PRIMARY); + draw_graph.add_draw_list_next_subpass(RDD::COMMAND_BUFFER_TYPE_PRIMARY); - _draw_list_allocate(viewport, 0, draw_list_current_subpass); + _draw_list_allocate(viewport, draw_list_current_subpass); return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT; } -Error RenderingDevice::draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) { - _THREAD_SAFE_METHOD_ - ERR_FAIL_COND_V(draw_list == nullptr, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(draw_list_current_subpass >= draw_list_subpass_count - 1, ERR_INVALID_PARAMETER); - draw_list_current_subpass++; - - Rect2i viewport; - _draw_list_free(&viewport); - - driver->command_next_render_subpass(frames[frame].draw_command_buffer, RDD::COMMAND_BUFFER_TYPE_PRIMARY); - - _draw_list_allocate(viewport, p_splits, draw_list_current_subpass); - - for (uint32_t i = 0; i < p_splits; i++) { - r_split_ids[i] = (int64_t(ID_TYPE_SPLIT_DRAW_LIST) << ID_BASE_SHIFT) + i; - } - - return OK; +#ifndef DISABLE_DEPRECATED +Error RenderingDevice::draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) { + ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Deprecated. Split draw lists are used automatically by RenderingDevice."); } +#endif -Error RenderingDevice::_draw_list_allocate(const Rect2i &p_viewport, uint32_t p_splits, uint32_t p_subpass) { +Error RenderingDevice::_draw_list_allocate(const Rect2i &p_viewport, uint32_t p_subpass) { // Lock while draw_list is active. _THREAD_SAFE_LOCK_ - if (p_splits == 0) { - draw_list = memnew(DrawList); - draw_list->command_buffer = frames[frame].draw_command_buffer; - draw_list->viewport = p_viewport; - draw_list_count = 0; - draw_list_split = false; - } else { - if (p_splits > (uint32_t)split_draw_list_allocators.size()) { - uint32_t from = split_draw_list_allocators.size(); - split_draw_list_allocators.resize(p_splits); - for (uint32_t i = from; i < p_splits; i++) { - RDD::CommandPoolID cmd_pool = driver->command_pool_create(RDD::COMMAND_BUFFER_TYPE_SECONDARY); - ERR_FAIL_COND_V(!cmd_pool, ERR_CANT_CREATE); - split_draw_list_allocators.write[i].command_pool = cmd_pool; - - for (int j = 0; j < frame_count; j++) { - RDD::CommandBufferID cmd_buffer = driver->command_buffer_create(RDD::COMMAND_BUFFER_TYPE_SECONDARY, cmd_pool); - ERR_FAIL_COND_V(!cmd_buffer, ERR_CANT_CREATE); - split_draw_list_allocators.write[i].command_buffers.push_back(cmd_buffer); - } - } - } - draw_list = memnew_arr(DrawList, p_splits); - draw_list_count = p_splits; - draw_list_split = true; - - for (uint32_t i = 0; i < p_splits; i++) { - // Take a command buffer and initialize it. - RDD::CommandBufferID cmd_buffer = split_draw_list_allocators[i].command_buffers[frame]; - - bool ok = driver->command_buffer_begin_secondary(cmd_buffer, draw_list_render_pass, p_subpass, draw_list_vkframebuffer); - if (!ok) { - memdelete_arr(draw_list); - draw_list = nullptr; - ERR_FAIL_V(ERR_CANT_CREATE); - } - - draw_list[i].command_buffer = cmd_buffer; - draw_list[i].viewport = p_viewport; - } - } + draw_list = memnew(DrawList); + draw_list->viewport = p_viewport; + draw_list_count = 0; return OK; } void RenderingDevice::_draw_list_free(Rect2i *r_last_viewport) { - if (draw_list_split) { - // Send all command buffers. - RDD::CommandBufferID *command_buffers = (RDD::CommandBufferID *)alloca(sizeof(RDD::CommandBufferID) * draw_list_count); - for (uint32_t i = 0; i < draw_list_count; i++) { - driver->command_buffer_end(draw_list[i].command_buffer); - command_buffers[i] = draw_list[i].command_buffer; - if (r_last_viewport) { - if (i == 0 || draw_list[i].viewport_set) { - *r_last_viewport = draw_list[i].viewport; - } - } - } - - driver->command_buffer_execute_secondary(frames[frame].draw_command_buffer, VectorView(command_buffers, draw_list_count)); - memdelete_arr(draw_list); - draw_list = nullptr; - - } else { - if (r_last_viewport) { - *r_last_viewport = draw_list->viewport; - } - // Just end the list. - memdelete(draw_list); - draw_list = nullptr; + if (r_last_viewport) { + *r_last_viewport = draw_list->viewport; } + // Just end the list. + memdelete(draw_list); + draw_list = nullptr; // Draw_list is no longer active. _THREAD_SAFE_UNLOCK_ } -void RenderingDevice::draw_list_end(BitField<BarrierMask> p_post_barrier) { +void RenderingDevice::draw_list_end() { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_MSG(!draw_list, "Immediate draw list is already inactive."); - _draw_list_free(); + draw_graph.add_draw_list_end(); - driver->command_end_render_pass(frames[frame].draw_command_buffer); + _draw_list_free(); for (int i = 0; i < draw_list_bound_textures.size(); i++) { Texture *texture = texture_owner.get_or_null(draw_list_bound_textures[i]); ERR_CONTINUE(!texture); // Wtf. - if (draw_list_unbind_color_textures && (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { + if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { texture->bound = false; } - if (draw_list_unbind_depth_textures && (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { + if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { texture->bound = false; } } - draw_list_bound_textures.clear(); - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - BitField<RDD::PipelineStageBits> dst_stages; - BitField<RDD::BarrierAccessBits> dst_access; - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT).set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); // RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT - dst_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_INDEX_READ_BIT).set_flag(RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT); // RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); // RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT - dst_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); // RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT - } - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_TRANSFER_READ_BIT); - } - - if (dst_stages.is_empty()) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - } - - RDD::TextureBarrier *texture_barriers = nullptr; - - uint32_t texture_barrier_count = draw_list_storage_textures.size(); - - if (texture_barrier_count) { - texture_barriers = (RDD::TextureBarrier *)alloca(sizeof(RDD::TextureBarrier) * draw_list_storage_textures.size()); - } - - BitField<RDD::PipelineStageBits> src_stage(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | - RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); - BitField<RDD::BarrierAccessBits> src_access( - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - - if (texture_barrier_count) { - src_stage.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT).set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - src_access.set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - - for (uint32_t i = 0; i < texture_barrier_count; i++) { - Texture *texture = texture_owner.get_or_null(draw_list_storage_textures[i]); - - RDD::TextureBarrier &tb = texture_barriers[i]; - tb.texture = texture->driver_id; - tb.src_access = src_access; - tb.dst_access = dst_access; - tb.prev_layout = texture->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - tb.subresources.aspect = texture->read_aspect_flags; - tb.subresources.base_mipmap = texture->base_mipmap; - tb.subresources.mipmap_count = texture->mipmaps; - tb.subresources.base_layer = texture->base_layer; - tb.subresources.layer_count = texture->layers; - - texture->layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - // To ensure proper synchronization, we must make sure rendering is done before: - // * Some buffer is copied. - // * Another render pass happens (since we may be done). - - RDD::MemoryBarrier mb; - mb.src_access = src_access; - mb.dst_access = dst_access; - - if (texture_barrier_count > 0 || p_post_barrier != BARRIER_MASK_NO_BARRIER) { - driver->command_pipeline_barrier(frames[frame].draw_command_buffer, src_stage, dst_stages, mb, {}, VectorView(texture_barriers, texture_barrier_count)); - } - } - - draw_list_storage_textures.clear(); - -#ifdef FORCE_FULL_BARRIER - _full_barrier(true); -#endif + draw_list_bound_textures.clear(); } /***********************/ /**** COMPUTE LISTS ****/ /***********************/ -RenderingDevice::ComputeListID RenderingDevice::compute_list_begin(bool p_allow_draw_overlap) { +RenderingDevice::ComputeListID RenderingDevice::compute_list_begin() { _THREAD_SAFE_METHOD_ - ERR_FAIL_COND_V_MSG(!p_allow_draw_overlap && draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time."); ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time."); // Lock while compute_list is active. _THREAD_SAFE_LOCK_ compute_list = memnew(ComputeList); - compute_list->command_buffer = frames[frame].draw_command_buffer; - compute_list->state.allow_draw_overlap = p_allow_draw_overlap; + + draw_graph.add_compute_list_begin(); return ID_TYPE_COMPUTE_LIST; } @@ -4688,7 +3851,7 @@ void RenderingDevice::compute_list_bind_compute_pipeline(ComputeListID p_list, R cl->state.pipeline = p_compute_pipeline; - driver->command_bind_compute_pipeline(cl->command_buffer, pipeline->driver_id); + draw_graph.add_compute_list_bind_pipeline(pipeline->driver_id); if (cl->state.pipeline_shader != pipeline->shader) { // Shader changed, so descriptor sets may become incompatible. @@ -4718,7 +3881,7 @@ void RenderingDevice::compute_list_bind_compute_pipeline(ComputeListID p_list, R } for (uint32_t i = 0; i < pcount; i++) { - cl->state.sets[i].bound = i >= first_invalid_set; + cl->state.sets[i].bound = cl->state.sets[i].bound && i < first_invalid_set; cl->state.sets[i].pipeline_expected_format = pformats[i]; } @@ -4779,109 +3942,6 @@ void RenderingDevice::compute_list_bind_uniform_set(ComputeListID p_list, RID p_ cl->state.sets[p_index].uniform_set_format = uniform_set->format; cl->state.sets[p_index].uniform_set = p_uniform_set; - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - uint32_t textures_to_sampled_count = uniform_set->mutable_sampled_textures.size(); - uint32_t textures_to_storage_count = uniform_set->mutable_storage_textures.size(); - - Texture **textures_to_sampled = uniform_set->mutable_sampled_textures.ptrw(); - - RDD::TextureBarrier *texture_barriers = nullptr; - - if (textures_to_sampled_count + textures_to_storage_count) { - texture_barriers = (RDD::TextureBarrier *)alloca(sizeof(RDD::TextureBarrier) * (textures_to_sampled_count + textures_to_storage_count)); - } - uint32_t texture_barrier_count = 0; - - BitField<RDD::PipelineStageBits> src_stages; - - for (uint32_t i = 0; i < textures_to_sampled_count; i++) { - if (textures_to_sampled[i]->layout != RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - src_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - - RDD::TextureBarrier &tb = texture_barriers[texture_barrier_count++]; - tb.texture = textures_to_sampled[i]->driver_id; - tb.src_access = (RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - tb.dst_access = (RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - tb.prev_layout = textures_to_sampled[i]->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - tb.subresources.aspect = textures_to_sampled[i]->read_aspect_flags; - tb.subresources.base_mipmap = textures_to_sampled[i]->base_mipmap; - tb.subresources.mipmap_count = textures_to_sampled[i]->mipmaps; - tb.subresources.base_layer = textures_to_sampled[i]->base_layer; - tb.subresources.layer_count = textures_to_sampled[i]->layers; - - textures_to_sampled[i]->layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - cl->state.textures_to_sampled_layout.erase(textures_to_sampled[i]); - } - - if (textures_to_sampled[i]->used_in_frame != frames_drawn) { - textures_to_sampled[i]->used_in_frame = frames_drawn; - textures_to_sampled[i]->used_in_transfer = false; - textures_to_sampled[i]->used_in_raster = false; - } - textures_to_sampled[i]->used_in_compute = true; - } - - Texture **textures_to_storage = uniform_set->mutable_storage_textures.ptrw(); - - for (uint32_t i = 0; i < textures_to_storage_count; i++) { - if (textures_to_storage[i]->layout != RDD::TEXTURE_LAYOUT_GENERAL) { - BitField<RDD::BarrierAccessBits> src_access; - - if (textures_to_storage[i]->used_in_frame == frames_drawn) { - if (textures_to_storage[i]->used_in_compute) { - src_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - src_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (textures_to_storage[i]->used_in_raster) { - src_stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT).set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT); - src_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (textures_to_storage[i]->used_in_transfer) { - src_stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - src_access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_TRANSFER_READ_BIT); - } - - textures_to_storage[i]->used_in_compute = false; - textures_to_storage[i]->used_in_raster = false; - textures_to_storage[i]->used_in_transfer = false; - - } else { - src_access.clear(); - textures_to_storage[i]->used_in_compute = false; - textures_to_storage[i]->used_in_raster = false; - textures_to_storage[i]->used_in_transfer = false; - textures_to_storage[i]->used_in_frame = frames_drawn; - } - - RDD::TextureBarrier &tb = texture_barriers[texture_barrier_count++]; - tb.texture = textures_to_storage[i]->driver_id; - tb.src_access = src_access; - tb.dst_access = (RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - tb.prev_layout = textures_to_storage[i]->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_GENERAL; - tb.subresources.aspect = textures_to_storage[i]->read_aspect_flags; - tb.subresources.base_mipmap = textures_to_storage[i]->base_mipmap; - tb.subresources.mipmap_count = textures_to_storage[i]->mipmaps; - tb.subresources.base_layer = textures_to_storage[i]->base_layer; - tb.subresources.layer_count = textures_to_storage[i]->layers; - - textures_to_storage[i]->layout = RDD::TEXTURE_LAYOUT_GENERAL; - - cl->state.textures_to_sampled_layout.insert(textures_to_storage[i]); // Needs to go back to sampled layout afterwards. - } - } - - if (texture_barrier_count) { - if (src_stages.is_empty()) { - src_stages.set_flag(RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT); - } - - driver->command_pipeline_barrier(cl->command_buffer, src_stages, RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, {}, {}, VectorView(texture_barriers, texture_barrier_count)); - } - } - #if 0 { // Validate that textures bound are not attached as framebuffer bindings. uint32_t attachable_count = uniform_set->attachable_textures.size(); @@ -4901,6 +3961,7 @@ void RenderingDevice::compute_list_bind_uniform_set(ComputeListID p_list, RID p_ void RenderingDevice::compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size) { ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST); ERR_FAIL_NULL(compute_list); + ERR_FAIL_COND_MSG(p_data_size > MAX_PUSH_CONSTANT_SIZE, "Push constants can't be bigger than 128 bytes to maintain compatibility."); ComputeList *cl = compute_list; @@ -4912,7 +3973,13 @@ void RenderingDevice::compute_list_set_push_constant(ComputeListID p_list, const ERR_FAIL_COND_MSG(p_data_size != cl->validation.pipeline_push_constant_size, "This compute pipeline requires (" + itos(cl->validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")"); #endif - driver->command_bind_push_constants(cl->command_buffer, cl->state.pipeline_shader_driver_id, 0, VectorView((const uint32_t *)p_data, p_data_size / sizeof(uint32_t))); + + draw_graph.add_compute_list_set_push_constant(cl->state.pipeline_shader_driver_id, p_data, p_data_size); + + // Store it in the state in case we need to restart the compute list. + memcpy(cl->state.push_constant_data, p_data, p_data_size); + cl->state.push_constant_size = p_data_size; + #ifdef DEBUG_ENABLED cl->validation.pipeline_push_constant_supplied = true; #endif @@ -4970,19 +4037,24 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g } } #endif - driver->command_uniform_set_prepare_for_use(cl->command_buffer, cl->state.sets[i].uniform_set_driver_id, cl->state.pipeline_shader_driver_id, i); + draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); } for (uint32_t i = 0; i < cl->state.set_count; i++) { if (cl->state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. } if (!cl->state.sets[i].bound) { - driver->command_bind_compute_uniform_set(cl->command_buffer, cl->state.sets[i].uniform_set_driver_id, cl->state.pipeline_shader_driver_id, i); + // All good, see if this requires re-binding. + draw_graph.add_compute_list_bind_uniform_set(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + + UniformSet *uniform_set = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set); + draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); + cl->state.sets[i].bound = true; } } - driver->command_compute_dispatch(cl->command_buffer, p_x_groups, p_y_groups, p_z_groups); + draw_graph.add_compute_list_dispatch(p_x_groups, p_y_groups, p_z_groups); } void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) { @@ -5009,7 +4081,7 @@ void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32 #endif - compute_list_dispatch(p_list, (p_x_threads - 1) / cl->state.local_group_size[0] + 1, (p_y_threads - 1) / cl->state.local_group_size[1] + 1, (p_z_threads - 1) / cl->state.local_group_size[2] + 1); + compute_list_dispatch(p_list, Math::division_round_up(p_x_threads, cl->state.local_group_size[0]), Math::division_round_up(p_y_threads, cl->state.local_group_size[1]), Math::division_round_up(p_z_threads, cl->state.local_group_size[2])); } void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) { @@ -5058,106 +4130,56 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p } } #endif - driver->command_uniform_set_prepare_for_use(cl->command_buffer, cl->state.sets[i].uniform_set_driver_id, cl->state.pipeline_shader_driver_id, i); + draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); } for (uint32_t i = 0; i < cl->state.set_count; i++) { if (cl->state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. } if (!cl->state.sets[i].bound) { - driver->command_bind_compute_uniform_set(cl->command_buffer, cl->state.sets[i].uniform_set_driver_id, cl->state.pipeline_shader_driver_id, i); + // All good, see if this requires re-binding. + draw_graph.add_compute_list_bind_uniform_set(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + + UniformSet *uniform_set = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set); + draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); + cl->state.sets[i].bound = true; } } - driver->command_compute_dispatch_indirect(cl->command_buffer, buffer->driver_id, p_offset); + draw_graph.add_compute_list_dispatch_indirect(buffer->driver_id, p_offset); + + if (buffer->draw_tracker != nullptr) { + draw_graph.add_compute_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ); + } } void RenderingDevice::compute_list_add_barrier(ComputeListID p_list) { // Must be called within a compute list, the class mutex is locked during that time - BitField<RDD::PipelineStageBits> stages(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - BitField<RDD::BarrierAccessBits> access(RDD::BARRIER_ACCESS_SHADER_READ_BIT); - _compute_list_add_barrier(BARRIER_MASK_COMPUTE, stages, access); -} - -void RenderingDevice::_compute_list_add_barrier(BitField<BarrierMask> p_post_barrier, BitField<RDD::PipelineStageBits> p_stages, BitField<RDD::BarrierAccessBits> p_access) { - ERR_FAIL_NULL(compute_list); - - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::TextureBarrier *texture_barriers = nullptr; - - uint32_t texture_barrier_count = compute_list->state.textures_to_sampled_layout.size(); - - if (texture_barrier_count) { - texture_barriers = (RDD::TextureBarrier *)alloca(sizeof(RDD::TextureBarrier) * texture_barrier_count); - } - - texture_barrier_count = 0; // We'll count how many we end up issuing. - - for (Texture *E : compute_list->state.textures_to_sampled_layout) { - if (E->layout != RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - RDD::TextureBarrier &tb = texture_barriers[texture_barrier_count++]; - tb.texture = E->driver_id; - tb.src_access = RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT; - tb.dst_access = p_access; - tb.prev_layout = E->layout; - tb.next_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - tb.subresources.aspect = E->read_aspect_flags; - tb.subresources.base_mipmap = E->base_mipmap; - tb.subresources.mipmap_count = E->mipmaps; - tb.subresources.base_layer = E->base_layer; - tb.subresources.layer_count = E->layers; - - E->layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - if (E->used_in_frame != frames_drawn) { - E->used_in_transfer = false; - E->used_in_raster = false; - E->used_in_compute = false; - E->used_in_frame = frames_drawn; - } - } + compute_list_barrier_state = compute_list->state; + compute_list_end(); + compute_list_begin(); - if (p_stages) { - RDD::MemoryBarrier mb; - mb.src_access = RDD::BARRIER_ACCESS_SHADER_WRITE_BIT; - mb.dst_access = p_access; - driver->command_pipeline_barrier(compute_list->command_buffer, RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, p_stages, mb, {}, VectorView(texture_barriers, texture_barrier_count)); + if (compute_list_barrier_state.pipeline.is_valid()) { + compute_list_bind_compute_pipeline(p_list, compute_list_barrier_state.pipeline); + } - } else if (texture_barrier_count) { - driver->command_pipeline_barrier(compute_list->command_buffer, RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, {}, {}, VectorView(texture_barriers, texture_barrier_count)); + for (uint32_t i = 0; i < compute_list_barrier_state.set_count; i++) { + if (compute_list_barrier_state.sets[i].uniform_set.is_valid()) { + compute_list_bind_uniform_set(p_list, compute_list_barrier_state.sets[i].uniform_set, i); } } -#ifdef FORCE_FULL_BARRIER - _full_barrier(true); -#endif + if (compute_list_barrier_state.push_constant_size > 0) { + compute_list_set_push_constant(p_list, compute_list_barrier_state.push_constant_data, compute_list_barrier_state.push_constant_size); + } } -void RenderingDevice::compute_list_end(BitField<BarrierMask> p_post_barrier) { +void RenderingDevice::compute_list_end() { ERR_FAIL_NULL(compute_list); - BitField<RDD::PipelineStageBits> stages; - BitField<RDD::BarrierAccessBits> access; - if (p_post_barrier.has_flag(BARRIER_MASK_COMPUTE)) { - stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_VERTEX)) { - stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT).set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT).set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_INDEX_READ_BIT).set_flag(RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT).set_flag(RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_FRAGMENT)) { - stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT).set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); - access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT); - } - if (p_post_barrier.has_flag(BARRIER_MASK_TRANSFER)) { - stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_TRANSFER_READ_BIT); - } - _compute_list_add_barrier(p_post_barrier, stages, access); + draw_graph.add_compute_list_end(); memdelete(compute_list); compute_list = nullptr; @@ -5166,66 +4188,168 @@ void RenderingDevice::compute_list_end(BitField<BarrierMask> p_post_barrier) { _THREAD_SAFE_UNLOCK_ } +#ifndef DISABLE_DEPRECATED void RenderingDevice::barrier(BitField<BarrierMask> p_from, BitField<BarrierMask> p_to) { - if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - return; - } + WARN_PRINT("Deprecated. Barriers are automatically inserted by RenderingDevice."); +} - BitField<RDD::PipelineStageBits> src_stages; - BitField<RDD::BarrierAccessBits> src_access; +void RenderingDevice::full_barrier() { + WARN_PRINT("Deprecated. Barriers are automatically inserted by RenderingDevice."); +} +#endif - if (p_from == 0) { - src_stages.set_flag(RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT); +/***********************/ +/**** COMMAND GRAPH ****/ +/***********************/ + +bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id) { + if (p_texture->draw_tracker != nullptr) { + // Texture already has a tracker. + return false; } else { - if (p_from.has_flag(BARRIER_MASK_COMPUTE)) { - src_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - src_access.set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_from.has_flag(BARRIER_MASK_FRAGMENT)) { - src_stages.set_flag(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT).set_flag(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT).set_flag(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); - src_access.set_flag(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + if (p_texture->owner.is_valid()) { + // Texture has an owner. + Texture *owner_texture = texture_owner.get_or_null(p_texture->owner); + ERR_FAIL_COND_V(!owner_texture, false); + + if (owner_texture->draw_tracker != nullptr) { + // Create a tracker for this dependency in particular. + if (p_texture->slice_type == TEXTURE_SLICE_MAX) { + // Shared texture. + p_texture->draw_tracker = owner_texture->draw_tracker; + p_texture->draw_tracker->reference_count++; + } else { + // Slice texture. + HashMap<Rect2i, RDG::ResourceTracker *>::ConstIterator draw_tracker_iterator = owner_texture->slice_trackers.find(p_texture->slice_rect); + RDG::ResourceTracker *draw_tracker = nullptr; + if (draw_tracker_iterator != owner_texture->slice_trackers.end()) { + // Reuse the tracker at the matching rectangle. + draw_tracker = draw_tracker_iterator->value; + } else { + // Create a new tracker and store it on the map. + draw_tracker = RDG::resource_tracker_create(); + draw_tracker->parent = owner_texture->draw_tracker; + draw_tracker->texture_driver_id = p_texture->driver_id; + draw_tracker->texture_subresources = p_texture->barrier_range(); + draw_tracker->texture_slice_or_dirty_rect = p_texture->slice_rect; + owner_texture->slice_trackers[p_texture->slice_rect] = draw_tracker; + } + + p_texture->slice_trackers.clear(); + p_texture->draw_tracker = draw_tracker; + p_texture->draw_tracker->reference_count++; + } + + if (p_texture_id.is_valid()) { + _dependencies_make_mutable(p_texture_id, p_texture->draw_tracker); + } + } else { + // Delegate this to the owner instead, as it'll make all its dependencies mutable. + _texture_make_mutable(owner_texture, p_texture->owner); + } + } else { + // Regular texture. + p_texture->draw_tracker = RDG::resource_tracker_create(); + p_texture->draw_tracker->texture_driver_id = p_texture->driver_id; + p_texture->draw_tracker->texture_subresources = p_texture->barrier_range(); + p_texture->draw_tracker->reference_count = 1; + + if (p_texture_id.is_valid()) { + if (p_texture->has_initial_data) { + // If the texture was initialized with initial data but wasn't made mutable from the start, assume the texture sampling usage. + p_texture->draw_tracker->usage = RDG::RESOURCE_USAGE_TEXTURE_SAMPLE; + } + + _dependencies_make_mutable(p_texture_id, p_texture->draw_tracker); + } } - if (p_from.has_flag(BARRIER_MASK_TRANSFER)) { - src_stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - src_access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT); + + return true; + } +} + +bool RenderingDevice::_buffer_make_mutable(Buffer *p_buffer, RID p_buffer_id) { + if (p_buffer->draw_tracker != nullptr) { + // Buffer already has a tracker. + return false; + } else { + // Create a tracker for the buffer and make all its dependencies mutable. + p_buffer->draw_tracker = RDG::resource_tracker_create(); + p_buffer->draw_tracker->buffer_driver_id = p_buffer->driver_id; + if (p_buffer_id.is_valid()) { + _dependencies_make_mutable(p_buffer_id, p_buffer->draw_tracker); } + + return true; } +} - BitField<RDD::PipelineStageBits> dst_stages; - BitField<RDD::BarrierAccessBits> dst_access; +bool RenderingDevice::_vertex_array_make_mutable(VertexArray *p_vertex_array, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker) { + if (!p_vertex_array->untracked_buffers.has(p_resource_id)) { + // Vertex array thinks the buffer is already tracked or does not use it. + return false; + } else { + // Vertex array is aware of the buffer but it isn't being tracked. + p_vertex_array->draw_trackers.push_back(p_resource_tracker); + p_vertex_array->untracked_buffers.erase(p_resource_id); + return true; + } +} - if (p_to == 0) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); +bool RenderingDevice::_index_array_make_mutable(IndexArray *p_index_array, RDG::ResourceTracker *p_resource_tracker) { + if (p_index_array->draw_tracker != nullptr) { + // Index array already has a tracker. + return false; } else { - if (p_to.has_flag(BARRIER_MASK_COMPUTE)) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); - } - if (p_to.has_flag(BARRIER_MASK_VERTEX)) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT).set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT).set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_INDEX_READ_BIT).set_flag(RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT).set_flag(RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT); - } - if (p_to.has_flag(BARRIER_MASK_FRAGMENT)) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT).set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_SHADER_READ_BIT).set_flag(RDD::BARRIER_ACCESS_SHADER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT); - } - if (p_to.has_flag(BARRIER_MASK_TRANSFER)) { - dst_stages.set_flag(RDD::PIPELINE_STAGE_TRANSFER_BIT); - dst_access.set_flag(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT).set_flag(RDD::BARRIER_ACCESS_TRANSFER_READ_BIT); - } + // Index array should assign the tracker from the buffer. + p_index_array->draw_tracker = p_resource_tracker; + return true; } +} - RDD::MemoryBarrier mb; - mb.src_access = src_access; - mb.dst_access = dst_access; - driver->command_pipeline_barrier(frames[frame].draw_command_buffer, src_stages, dst_stages, mb, {}, {}); +bool RenderingDevice::_uniform_set_make_mutable(UniformSet *p_uniform_set, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker) { + HashMap<RID, RDG::ResourceUsage>::Iterator E = p_uniform_set->untracked_usage.find(p_resource_id); + if (!E) { + // Uniform set thinks the resource is already tracked or does not use it. + return false; + } else { + // Uniform set has seen the resource but hasn't added its tracker yet. + p_uniform_set->draw_trackers.push_back(p_resource_tracker); + p_uniform_set->draw_trackers_usage.push_back(E->value); + p_uniform_set->untracked_usage.remove(E); + return true; + } } -void RenderingDevice::full_barrier() { -#ifndef DEBUG_ENABLED - ERR_PRINT("Full barrier is debug-only, should not be used in production"); -#endif - _full_barrier(true); +bool RenderingDevice::_dependency_make_mutable(RID p_id, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker) { + if (texture_owner.owns(p_id)) { + Texture *texture = texture_owner.get_or_null(p_id); + return _texture_make_mutable(texture, p_id); + } else if (vertex_array_owner.owns(p_id)) { + VertexArray *vertex_array = vertex_array_owner.get_or_null(p_id); + return _vertex_array_make_mutable(vertex_array, p_resource_id, p_resource_tracker); + } else if (index_array_owner.owns(p_id)) { + IndexArray *index_array = index_array_owner.get_or_null(p_id); + return _index_array_make_mutable(index_array, p_resource_tracker); + } else if (uniform_set_owner.owns(p_id)) { + UniformSet *uniform_set = uniform_set_owner.get_or_null(p_id); + return _uniform_set_make_mutable(uniform_set, p_resource_id, p_resource_tracker); + } else { + DEV_ASSERT(false && "Unknown resource type to make mutable."); + return false; + } +} + +bool RenderingDevice::_dependencies_make_mutable(RID p_id, RDG::ResourceTracker *p_resource_tracker) { + bool made_mutable = false; + HashMap<RID, HashSet<RID>>::Iterator E = dependency_map.find(p_id); + if (E) { + for (RID rid : E->value) { + made_mutable = _dependency_make_mutable(rid, p_id, p_resource_tracker) || made_mutable; + } + } + + return made_mutable; } /**************************/ @@ -5251,6 +4375,22 @@ void RenderingDevice::_free_internal(RID p_id) { // Push everything so it's disposed of next time this frame index is processed (means, it's safe to do it). if (texture_owner.owns(p_id)) { Texture *texture = texture_owner.get_or_null(p_id); + RDG::ResourceTracker *draw_tracker = texture->draw_tracker; + if (draw_tracker != nullptr) { + draw_tracker->reference_count--; + if (draw_tracker->reference_count == 0) { + RDG::resource_tracker_free(draw_tracker); + + if (texture->owner.is_valid() && (texture->slice_type != TEXTURE_SLICE_MAX)) { + // If this was a texture slice, erase the tracker from the map. + Texture *owner_texture = texture_owner.get_or_null(texture->owner); + if (owner_texture != nullptr) { + owner_texture->slice_trackers.erase(texture->slice_rect); + } + } + } + } + frames[frame].textures_to_dispose_of.push_back(*texture); texture_owner.free(p_id); } else if (framebuffer_owner.owns(p_id)) { @@ -5268,12 +4408,14 @@ void RenderingDevice::_free_internal(RID p_id) { sampler_owner.free(p_id); } else if (vertex_buffer_owner.owns(p_id)) { Buffer *vertex_buffer = vertex_buffer_owner.get_or_null(p_id); + RDG::resource_tracker_free(vertex_buffer->draw_tracker); frames[frame].buffers_to_dispose_of.push_back(*vertex_buffer); vertex_buffer_owner.free(p_id); } else if (vertex_array_owner.owns(p_id)) { vertex_array_owner.free(p_id); } else if (index_buffer_owner.owns(p_id)) { IndexBuffer *index_buffer = index_buffer_owner.get_or_null(p_id); + RDG::resource_tracker_free(index_buffer->draw_tracker); frames[frame].buffers_to_dispose_of.push_back(*index_buffer); index_buffer_owner.free(p_id); } else if (index_array_owner.owns(p_id)) { @@ -5286,14 +4428,17 @@ void RenderingDevice::_free_internal(RID p_id) { shader_owner.free(p_id); } else if (uniform_buffer_owner.owns(p_id)) { Buffer *uniform_buffer = uniform_buffer_owner.get_or_null(p_id); + RDG::resource_tracker_free(uniform_buffer->draw_tracker); frames[frame].buffers_to_dispose_of.push_back(*uniform_buffer); uniform_buffer_owner.free(p_id); } else if (texture_buffer_owner.owns(p_id)) { Buffer *texture_buffer = texture_buffer_owner.get_or_null(p_id); + RDG::resource_tracker_free(texture_buffer->draw_tracker); frames[frame].buffers_to_dispose_of.push_back(*texture_buffer); texture_buffer_owner.free(p_id); } else if (storage_buffer_owner.owns(p_id)) { Buffer *storage_buffer = storage_buffer_owner.get_or_null(p_id); + RDG::resource_tracker_free(storage_buffer->draw_tracker); frames[frame].buffers_to_dispose_of.push_back(*storage_buffer); storage_buffer_owner.free(p_id); } else if (uniform_set_owner.owns(p_id)) { @@ -5370,18 +4515,21 @@ void RenderingDevice::set_resource_name(RID p_id, const String &p_name) { } void RenderingDevice::draw_command_begin_label(String p_label_name, const Color &p_color) { - _THREAD_SAFE_METHOD_ - context->command_begin_label(frames[frame].draw_command_buffer, p_label_name, p_color); + if (!context->is_debug_utils_enabled()) { + return; + } + + draw_graph.begin_label(p_label_name, p_color); } +#ifndef DISABLE_DEPRECATED void RenderingDevice::draw_command_insert_label(String p_label_name, const Color &p_color) { - _THREAD_SAFE_METHOD_ - context->command_insert_label(frames[frame].draw_command_buffer, p_label_name, p_color); + WARN_PRINT("Deprecated. Inserting labels no longer applies due to command reordering."); } +#endif void RenderingDevice::draw_command_end_label() { - _THREAD_SAFE_METHOD_ - context->command_end_label(frames[frame].draw_command_buffer); + draw_graph.end_label(); } String RenderingDevice::get_device_vendor_name() const { @@ -5404,7 +4552,7 @@ String RenderingDevice::get_device_pipeline_cache_uuid() const { return context->get_device_pipeline_cache_uuid(); } -void RenderingDevice::_finalize_command_bufers() { +void RenderingDevice::_finalize_command_buffers(bool p_postpare) { if (draw_list) { ERR_PRINT("Found open draw list at the end of the frame, this should never happen (further drawing will likely not work)."); } @@ -5413,7 +4561,13 @@ void RenderingDevice::_finalize_command_bufers() { ERR_PRINT("Found open compute list at the end of the frame, this should never happen (further compute will likely not work)."); } - { + { // Complete the setup buffer (that needs to be processed before anything else). + draw_graph.end(frames[frame].draw_command_buffer, RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS); + + if (p_postpare) { + context->postpare_buffers(frames[frame].draw_command_buffer); + } + driver->end_segment(); driver->command_buffer_end(frames[frame].setup_command_buffer); driver->command_buffer_end(frames[frame].draw_command_buffer); @@ -5421,6 +4575,8 @@ void RenderingDevice::_finalize_command_bufers() { } void RenderingDevice::_begin_frame() { + draw_graph.begin(); + // Erase pending resources. _free_pending_resources(frame); @@ -5464,12 +4620,15 @@ void RenderingDevice::swap_buffers() { ERR_FAIL_COND_MSG(local_device.is_valid(), "Local devices can't swap buffers."); _THREAD_SAFE_METHOD_ - context->postpare_buffers(frames[frame].draw_command_buffer); - _finalize_command_bufers(); + _finalize_command_buffers(true); - screen_prepared = false; // Swap buffers. - context->swap_buffers(); + if (!screen_prepared) { + context->flush(true, true, false); + } else { + screen_prepared = false; + context->swap_buffers(); + } frame = (frame + 1) % frame_count; @@ -5482,7 +4641,7 @@ void RenderingDevice::submit() { ERR_FAIL_COND_MSG(local_device.is_null(), "Only local devices can submit and sync."); ERR_FAIL_COND_MSG(local_device_processing, "device already submitted, call sync to wait until done."); - _finalize_command_bufers(); + _finalize_command_buffers(false); RDD::CommandBufferID command_buffers[2] = { frames[frame].setup_command_buffer, frames[frame].draw_command_buffer }; context->local_device_push_command_buffers(local_device, command_buffers, 2); @@ -5614,11 +4773,14 @@ void RenderingDevice::_flush(bool p_current_frame) { if (local_device.is_valid() && !p_current_frame) { return; // Flushing previous frames has no effect with local device. } + // Not doing this crashes RADV (undefined behavior). if (p_current_frame) { + draw_graph.end(frames[frame].draw_command_buffer, RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS); driver->end_segment(); driver->command_buffer_end(frames[frame].setup_command_buffer); driver->command_buffer_end(frames[frame].draw_command_buffer); + draw_graph.begin(); } if (local_device.is_valid()) { @@ -5739,7 +4901,6 @@ void RenderingDevice::initialize(ApiContextRD *p_context, bool p_local_device) { draw_list = nullptr; draw_list_count = 0; - draw_list_split = false; compute_list = nullptr; @@ -5756,6 +4917,8 @@ void RenderingDevice::initialize(ApiContextRD *p_context, bool p_local_device) { pipelines_cache_size = driver->pipeline_cache_query_size(); print_verbose(vformat("Startup PSO cache (%.1f MiB)", pipelines_cache_size / (1024.0f * 1024.0f))); } + + draw_graph.initialize(driver, frame_count, SECONDARY_COMMAND_BUFFERS_PER_FRAME); } Vector<uint8_t> RenderingDevice::_load_pipeline_cache() { @@ -5853,46 +5016,11 @@ void RenderingDevice::_free_rids(T &p_owner, const char *p_type) { void RenderingDevice::capture_timestamp(const String &p_name) { ERR_FAIL_COND_MSG(draw_list != nullptr, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name); + ERR_FAIL_COND_MSG(compute_list != nullptr, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name); ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements); - // This should be optional for profiling, else it will slow things down. - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - RDD::MemoryBarrier mb; - mb.src_access = (RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT | - RDD::BARRIER_ACCESS_INDEX_READ_BIT | - RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | - RDD::BARRIER_ACCESS_UNIFORM_READ_BIT | - RDD::BARRIER_ACCESS_INPUT_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_SHADER_READ_BIT | - RDD::BARRIER_ACCESS_SHADER_WRITE_BIT | - RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | - RDD::BARRIER_ACCESS_TRANSFER_READ_BIT | - RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT | - RDD::BARRIER_ACCESS_HOST_READ_BIT | - RDD::BARRIER_ACCESS_HOST_WRITE_BIT); - mb.dst_access = (RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT | - RDD::BARRIER_ACCESS_INDEX_READ_BIT | - RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | - RDD::BARRIER_ACCESS_UNIFORM_READ_BIT | - RDD::BARRIER_ACCESS_INPUT_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_SHADER_READ_BIT | - RDD::BARRIER_ACCESS_SHADER_WRITE_BIT | - RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | - RDD::BARRIER_ACCESS_TRANSFER_READ_BIT | - RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT | - RDD::BARRIER_ACCESS_HOST_READ_BIT | - RDD::BARRIER_ACCESS_HOST_WRITE_BIT); - - driver->command_pipeline_barrier(frames[frame].draw_command_buffer, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, mb, {}, {}); - } - - driver->command_timestamp_write(frames[frame].draw_command_buffer, frames[frame].timestamp_pool, frames[frame].timestamp_count); + draw_graph.add_capture_timestamp(frames[frame].timestamp_pool, frames[frame].timestamp_count); + frames[frame].timestamp_names[frames[frame].timestamp_count] = p_name; frames[frame].timestamp_cpu_values[frames[frame].timestamp_count] = OS::get_singleton()->get_ticks_usec(); frames[frame].timestamp_count++; @@ -6060,10 +5188,6 @@ void RenderingDevice::finalize() { driver->pipeline_cache_free(); } - for (int i = 0; i < split_draw_list_allocators.size(); i++) { - driver->command_pool_free(split_draw_list_allocators[i].command_pool); - } - frames.clear(); for (int i = 0; i < staging_buffer_blocks.size(); i++) { @@ -6102,7 +5226,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "mipmaps", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(1), DEFVAL(TEXTURE_SLICE_2D)); ClassDB::bind_method(D_METHOD("texture_create_from_extension", "type", "format", "samples", "usage_flags", "image", "width", "height", "depth", "layers"), &RenderingDevice::texture_create_from_extension); - ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::texture_update, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data"), &RenderingDevice::texture_update); ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "layer"), &RenderingDevice::texture_get_data); ClassDB::bind_method(D_METHOD("texture_is_format_supported_for_usage", "format", "usage_flags"), &RenderingDevice::texture_is_format_supported_for_usage); @@ -6110,9 +5234,9 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_is_shared", "texture"), &RenderingDevice::texture_is_shared); ClassDB::bind_method(D_METHOD("texture_is_valid", "texture"), &RenderingDevice::texture_is_valid); - ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer", "post_barrier"), &RenderingDevice::texture_copy, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); - ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::texture_clear, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); - ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::texture_resolve_multisample, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer"), &RenderingDevice::texture_copy); + ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count"), &RenderingDevice::texture_clear); + ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture"), &RenderingDevice::texture_resolve_multisample); ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &RenderingDevice::_texture_get_format); #ifndef DISABLE_DEPRECATED @@ -6154,8 +5278,9 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("uniform_set_create", "uniforms", "shader", "shader_set"), &RenderingDevice::_uniform_set_create); ClassDB::bind_method(D_METHOD("uniform_set_is_valid", "uniform_set"), &RenderingDevice::uniform_set_is_valid); - ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "post_barrier"), &RenderingDevice::_buffer_update_bind, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); - ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("buffer_copy", "src_buffer", "dst_buffer", "src_offset", "dst_offset", "size"), &RenderingDevice::buffer_copy); + ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data"), &RenderingDevice::_buffer_update_bind); + ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes"), &RenderingDevice::buffer_clear); ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer", "offset_bytes", "size_bytes"), &RenderingDevice::buffer_get_data, DEFVAL(0), DEFVAL(0)); ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass", "specialization_constants"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0), DEFVAL(TypedArray<RDPipelineSpecializationConstant>())); @@ -6170,8 +5295,10 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color())); - ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); + ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2())); +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); +#endif ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants); ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline); @@ -6186,17 +5313,19 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor); ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass"), &RenderingDevice::draw_list_switch_to_next_pass); +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass_split", "splits"), &RenderingDevice::_draw_list_switch_to_next_pass_split); +#endif - ClassDB::bind_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::draw_list_end, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("draw_list_end"), &RenderingDevice::draw_list_end); - ClassDB::bind_method(D_METHOD("compute_list_begin", "allow_draw_overlap"), &RenderingDevice::compute_list_begin, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("compute_list_begin"), &RenderingDevice::compute_list_begin); ClassDB::bind_method(D_METHOD("compute_list_bind_compute_pipeline", "compute_list", "compute_pipeline"), &RenderingDevice::compute_list_bind_compute_pipeline); ClassDB::bind_method(D_METHOD("compute_list_set_push_constant", "compute_list", "buffer", "size_bytes"), &RenderingDevice::_compute_list_set_push_constant); ClassDB::bind_method(D_METHOD("compute_list_bind_uniform_set", "compute_list", "uniform_set", "set_index"), &RenderingDevice::compute_list_bind_uniform_set); ClassDB::bind_method(D_METHOD("compute_list_dispatch", "compute_list", "x_groups", "y_groups", "z_groups"), &RenderingDevice::compute_list_dispatch); ClassDB::bind_method(D_METHOD("compute_list_add_barrier", "compute_list"), &RenderingDevice::compute_list_add_barrier); - ClassDB::bind_method(D_METHOD("compute_list_end", "post_barrier"), &RenderingDevice::compute_list_end, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("compute_list_end"), &RenderingDevice::compute_list_end); ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingDevice::free); @@ -6212,15 +5341,19 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("submit"), &RenderingDevice::submit); ClassDB::bind_method(D_METHOD("sync"), &RenderingDevice::sync); +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("barrier", "from", "to"), &RenderingDevice::barrier, DEFVAL(BARRIER_MASK_ALL_BARRIERS), DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("full_barrier"), &RenderingDevice::full_barrier); +#endif ClassDB::bind_method(D_METHOD("create_local_device"), &RenderingDevice::create_local_device); ClassDB::bind_method(D_METHOD("set_resource_name", "id", "name"), &RenderingDevice::set_resource_name); ClassDB::bind_method(D_METHOD("draw_command_begin_label", "name", "color"), &RenderingDevice::draw_command_begin_label); +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("draw_command_insert_label", "name", "color"), &RenderingDevice::draw_command_insert_label); +#endif ClassDB::bind_method(D_METHOD("draw_command_end_label"), &RenderingDevice::draw_command_end_label); ClassDB::bind_method(D_METHOD("get_device_vendor_name"), &RenderingDevice::get_device_vendor_name); @@ -6487,6 +5620,7 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM); BIND_ENUM_CONSTANT(DATA_FORMAT_MAX); +#ifndef DISABLE_DEPRECATED BIND_BITFIELD_FLAG(BARRIER_MASK_VERTEX); BIND_BITFIELD_FLAG(BARRIER_MASK_FRAGMENT); BIND_BITFIELD_FLAG(BARRIER_MASK_COMPUTE); @@ -6494,6 +5628,7 @@ void RenderingDevice::_bind_methods() { BIND_BITFIELD_FLAG(BARRIER_MASK_RASTER); BIND_BITFIELD_FLAG(BARRIER_MASK_ALL_BARRIERS); BIND_BITFIELD_FLAG(BARRIER_MASK_NO_BARRIER); +#endif BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D); BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D); @@ -6668,18 +5803,25 @@ void RenderingDevice::_bind_methods() { BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_WRITE_MASK); BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_REFERENCE); - BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR); //start rendering and clear the framebuffer (supply params) - BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION); //start rendering and clear the framebuffer (supply params) - BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION_CONTINUE); //continue rendering and clear the framebuffer (supply params) - BIND_ENUM_CONSTANT(INITIAL_ACTION_KEEP); //start rendering); but keep attached color texture contents (depth will be cleared) - BIND_ENUM_CONSTANT(INITIAL_ACTION_DROP); //start rendering); ignore what is there); just write above it - BIND_ENUM_CONSTANT(INITIAL_ACTION_CONTINUE); //continue rendering (framebuffer must have been left in "continue" state as final action previously) + BIND_ENUM_CONSTANT(INITIAL_ACTION_LOAD); + BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR); + BIND_ENUM_CONSTANT(INITIAL_ACTION_DISCARD); BIND_ENUM_CONSTANT(INITIAL_ACTION_MAX); +#ifndef DISABLE_DEPRECATED + BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION); + BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION_CONTINUE); + BIND_ENUM_CONSTANT(INITIAL_ACTION_KEEP); + BIND_ENUM_CONSTANT(INITIAL_ACTION_DROP); + BIND_ENUM_CONSTANT(INITIAL_ACTION_CONTINUE); +#endif - BIND_ENUM_CONSTANT(FINAL_ACTION_READ); //will no longer render to it); allows attached textures to be read again); but depth buffer contents will be dropped (Can't be read from) - BIND_ENUM_CONSTANT(FINAL_ACTION_DISCARD); // discard contents after rendering - BIND_ENUM_CONSTANT(FINAL_ACTION_CONTINUE); //will continue rendering later); attached textures can't be read until re-bound with "finish" + BIND_ENUM_CONSTANT(FINAL_ACTION_STORE); + BIND_ENUM_CONSTANT(FINAL_ACTION_DISCARD); BIND_ENUM_CONSTANT(FINAL_ACTION_MAX); +#ifndef DISABLE_DEPRECATED + BIND_ENUM_CONSTANT(FINAL_ACTION_READ); + BIND_ENUM_CONSTANT(FINAL_ACTION_CONTINUE); +#endif BIND_ENUM_CONSTANT(SHADER_STAGE_VERTEX); BIND_ENUM_CONSTANT(SHADER_STAGE_FRAGMENT); @@ -6946,8 +6088,8 @@ RID RenderingDevice::_uniform_set_create(const TypedArray<RDUniform> &p_uniforms return uniform_set_create(uniforms, p_shader, p_shader_set); } -Error RenderingDevice::_buffer_update_bind(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier) { - return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_post_barrier); +Error RenderingDevice::_buffer_update_bind(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data) { + return buffer_update(p_buffer, p_offset, p_size, p_data.ptr()); } static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constants(const TypedArray<RDPipelineSpecializationConstant> &p_constants) { @@ -7018,47 +6160,15 @@ RID RenderingDevice::_compute_pipeline_create(RID p_shader, const TypedArray<RDP return compute_pipeline_create(p_shader, _get_spec_constants(p_specialization_constants)); } -RenderingDevice::DrawListID RenderingDevice::_draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) { - Vector<RID> stextures; - for (int i = 0; i < p_storage_textures.size(); i++) { - stextures.push_back(p_storage_textures[i]); - } - return draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, stextures); -} - +#ifndef DISABLE_DEPRECATED Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) { - Vector<DrawListID> splits; - splits.resize(p_splits); - Vector<RID> stextures; - for (int i = 0; i < p_storage_textures.size(); i++) { - stextures.push_back(p_storage_textures[i]); - } - draw_list_begin_split(p_framebuffer, p_splits, splits.ptrw(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, stextures); - - Vector<int64_t> split_ids; - split_ids.resize(splits.size()); - for (int i = 0; i < splits.size(); i++) { - split_ids.write[i] = splits[i]; - } - - return split_ids; + ERR_FAIL_V_MSG(Vector<int64_t>(), "Deprecated. Split draw lists are used automatically by RenderingDevice."); } Vector<int64_t> RenderingDevice::_draw_list_switch_to_next_pass_split(uint32_t p_splits) { - Vector<DrawListID> splits; - splits.resize(p_splits); - - Error err = draw_list_switch_to_next_pass_split(p_splits, splits.ptrw()); - ERR_FAIL_COND_V(err != OK, Vector<int64_t>()); - - Vector<int64_t> split_ids; - split_ids.resize(splits.size()); - for (int i = 0; i < splits.size(); i++) { - split_ids.write[i] = splits[i]; - } - - return split_ids; + ERR_FAIL_V_MSG(Vector<int64_t>(), "Deprecated. Split draw lists are used automatically by RenderingDevice."); } +#endif void RenderingDevice::_draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size) { ERR_FAIL_COND((uint32_t)p_data.size() > p_data_size); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 90ed2828c0..2ccef66308 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -42,6 +42,7 @@ #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_device_commons.h" #include "servers/rendering/rendering_device_driver.h" +#include "servers/rendering/rendering_device_graph.h" class RDTextureFormat; class RDTextureView; @@ -93,6 +94,9 @@ public: uint32_t version_minor = 0; }; + typedef int64_t DrawListID; + typedef int64_t ComputeListID; + typedef String (*ShaderSPIRVGetCacheKeyFunction)(const RenderingDevice *p_render_device); typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device); typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language); @@ -131,8 +135,7 @@ public: ID_TYPE_FRAMEBUFFER_FORMAT, ID_TYPE_VERTEX_FORMAT, ID_TYPE_DRAW_LIST, - ID_TYPE_SPLIT_DRAW_LIST, - ID_TYPE_COMPUTE_LIST, + ID_TYPE_COMPUTE_LIST = 4, ID_TYPE_MAX, ID_BASE_SHIFT = 58, // 5 bits for ID types. ID_MASK = (ID_BASE_SHIFT - 1), @@ -145,25 +148,7 @@ private: void _add_dependency(RID p_id, RID p_depends_on); void _free_dependencies(RID p_id); - /*****************/ - /**** BARRIER ****/ - /*****************/ - -public: - enum BarrierMask { - BARRIER_MASK_VERTEX = 1, - BARRIER_MASK_FRAGMENT = 8, - BARRIER_MASK_COMPUTE = 2, - BARRIER_MASK_TRANSFER = 4, - - BARRIER_MASK_RASTER = BARRIER_MASK_VERTEX | BARRIER_MASK_FRAGMENT, // 9, - BARRIER_MASK_ALL_BARRIERS = 0x7FFF, // all flags set - BARRIER_MASK_NO_BARRIER = 0x8000, - }; - private: - void _full_barrier(bool p_sync_with_draw); - /***************************/ /**** BUFFER MANAGEMENT ****/ /***************************/ @@ -201,26 +186,34 @@ private: uint64_t staging_buffer_max_size = 0; bool staging_buffer_used = false; - Error _staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, bool p_can_segment = true); + enum StagingRequiredAction { + STAGING_REQUIRED_ACTION_NONE, + STAGING_REQUIRED_ACTION_FLUSH_CURRENT, + STAGING_REQUIRED_ACTION_FLUSH_OLDER + }; + + Error _staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, StagingRequiredAction &r_required_action, bool p_can_segment = true); + void _staging_buffer_execute_required_action(StagingRequiredAction p_required_action); Error _insert_staging_block(); struct Buffer { RDD::BufferID driver_id; uint32_t size = 0; BitField<RDD::BufferUsageBits> usage; + RDG::ResourceTracker *draw_tracker = nullptr; }; - Buffer *_get_buffer_from_owner(RID p_buffer, BitField<RDD::PipelineStageBits> &r_stages, BitField<RDD::BarrierAccessBits> &r_access, BitField<BarrierMask> p_post_barrier); - Error _buffer_update(Buffer *p_buffer, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_command_buffer = false, uint32_t p_required_align = 32); + Buffer *_get_buffer_from_owner(RID p_buffer); + Error _buffer_update(Buffer *p_buffer, RID p_buffer_id, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_queue = false, uint32_t p_required_align = 32); RID_Owner<Buffer> uniform_buffer_owner; RID_Owner<Buffer> storage_buffer_owner; RID_Owner<Buffer> texture_buffer_owner; public: - Error buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t p_src_offset, uint32_t p_dst_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); - Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); - Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); + Error buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t p_src_offset, uint32_t p_dst_offset, uint32_t p_size); + Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data); + Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size); Vector<uint8_t> buffer_get_data(RID p_buffer, uint32_t p_offset = 0, uint32_t p_size = 0); // This causes stall, only use to retrieve large buffers for saving. /*****************/ @@ -245,6 +238,8 @@ public: TextureType type = TEXTURE_TYPE_MAX; DataFormat format = DATA_FORMAT_MAX; TextureSamples samples = TEXTURE_SAMPLES_MAX; + TextureSliceType slice_type = TEXTURE_SLICE_MAX; + Rect2i slice_rect; uint32_t width = 0; uint32_t height = 0; uint32_t depth = 0; @@ -256,26 +251,33 @@ public: Vector<DataFormat> allowed_shared_formats; - RDD::TextureLayout layout = RDD::TEXTURE_LAYOUT_UNDEFINED; - - uint64_t used_in_frame = 0; - bool used_in_transfer = false; - bool used_in_raster = false; - bool used_in_compute = false; - bool is_resolve_buffer = false; + bool has_initial_data = false; BitField<RDD::TextureAspectBits> read_aspect_flags; BitField<RDD::TextureAspectBits> barrier_aspect_flags; - bool bound = false; // Bound to framebffer. + bool bound = false; // Bound to framebuffer. RID owner; + + RDG::ResourceTracker *draw_tracker = nullptr; + HashMap<Rect2i, RDG::ResourceTracker *> slice_trackers; + + RDD::TextureSubresourceRange barrier_range() const { + RDD::TextureSubresourceRange r; + r.aspect = barrier_aspect_flags; + r.base_mipmap = base_mipmap; + r.mipmap_count = mipmaps; + r.base_layer = base_layer; + r.layer_count = layers; + return r; + } }; RID_Owner<Texture> texture_owner; uint32_t texture_upload_region_size_px = 0; Vector<uint8_t> _texture_get_data(Texture *tex, uint32_t p_layer, bool p_2d = false); - Error _texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier, bool p_use_setup_queue); + Error _texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, bool p_use_setup_queue, bool p_validate_can_update); public: struct TextureView { @@ -306,7 +308,7 @@ public: RID texture_create_shared(const TextureView &p_view, RID p_with_texture); RID texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, BitField<RenderingDevice::TextureUsageBits> p_usage, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers); RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D, uint32_t p_layers = 0); - Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); + Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data); Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer); // CPU textures will return immediately, while GPU textures will most likely force a flush bool texture_is_format_supported_for_usage(DataFormat p_format, BitField<TextureUsageBits> p_usage) const; @@ -318,29 +320,36 @@ public: uint64_t texture_get_native_handle(RID p_texture); #endif - Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); - Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); - Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); + Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer); + Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers); + Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture); /************************/ /**** DRAW LISTS (I) ****/ /************************/ enum InitialAction { - INITIAL_ACTION_CLEAR, // Start rendering and clear the whole framebuffer. - INITIAL_ACTION_CLEAR_REGION, // Start rendering and clear the framebuffer in the specified region. - INITIAL_ACTION_CLEAR_REGION_CONTINUE, // Continue rendering and clear the framebuffer in the specified region. Framebuffer must have been left in `FINAL_ACTION_CONTINUE` state as the final action previously. - INITIAL_ACTION_KEEP, // Start rendering, but keep attached color texture contents. If the framebuffer was previously used to read in a shader, this will automatically insert a layout transition. - INITIAL_ACTION_DROP, // Start rendering, ignore what is there; write above it. In general, this is the fastest option when you will be writing every single pixel and you don't need a clear color. - INITIAL_ACTION_CONTINUE, // Continue rendering. Framebuffer must have been left in `FINAL_ACTION_CONTINUE` state as the final action previously. - INITIAL_ACTION_MAX + INITIAL_ACTION_LOAD, + INITIAL_ACTION_CLEAR, + INITIAL_ACTION_DISCARD, + INITIAL_ACTION_MAX, +#ifndef DISABLE_DEPRECATED + INITIAL_ACTION_CLEAR_REGION = INITIAL_ACTION_CLEAR, + INITIAL_ACTION_CLEAR_REGION_CONTINUE = INITIAL_ACTION_CLEAR, + INITIAL_ACTION_KEEP = INITIAL_ACTION_LOAD, + INITIAL_ACTION_DROP = INITIAL_ACTION_DISCARD, + INITIAL_ACTION_CONTINUE = INITIAL_ACTION_LOAD, +#endif }; enum FinalAction { - FINAL_ACTION_READ, // Store the texture for reading and make it read-only if it has the `TEXTURE_USAGE_SAMPLING_BIT` bit (only applies to color, depth and stencil attachments). - FINAL_ACTION_DISCARD, // Discard the texture data and make it read-only if it has the `TEXTURE_USAGE_SAMPLING_BIT` bit (only applies to color, depth and stencil attachments). - FINAL_ACTION_CONTINUE, // Store the texture and continue for further processing. Similar to `FINAL_ACTION_READ`, but does not make the texture read-only if it has the `TEXTURE_USAGE_SAMPLING_BIT` bit. - FINAL_ACTION_MAX + FINAL_ACTION_STORE, + FINAL_ACTION_DISCARD, + FINAL_ACTION_MAX, +#ifndef DISABLE_DEPRECATED + FINAL_ACTION_READ = FINAL_ACTION_STORE, + FINAL_ACTION_CONTINUE = FINAL_ACTION_STORE, +#endif }; /*********************/ @@ -668,7 +677,9 @@ private: uint32_t max_instances_allowed = 0; Vector<RDD::BufferID> buffers; // Not owned, just referenced. + Vector<RDG::ResourceTracker *> draw_trackers; // Not owned, just referenced. Vector<uint64_t> offsets; + HashSet<RID> untracked_buffers; }; RID_Owner<VertexArray> vertex_array_owner; @@ -685,6 +696,7 @@ private: struct IndexArray { uint32_t max_index = 0; // Remember the maximum index here too, for validation. RDD::BufferID driver_id; // Not owned, inherited from index buffer. + RDG::ResourceTracker *draw_tracker = nullptr; // Not owned, inherited from index buffer. uint32_t offset = 0; uint32_t indices = 0; IndexBufferFormat format = INDEX_BUFFER_FORMAT_UINT16; @@ -762,6 +774,7 @@ private: String name; // Used for debug. RDD::ShaderID driver_id; uint32_t layout_hash = 0; + BitField<RDD::PipelineStageBits> stage_bits; Vector<uint32_t> set_formats; }; @@ -770,10 +783,42 @@ private: RID_Owner<Shader> shader_owner; #ifndef DISABLE_DEPRECATED - BitField<BarrierMask> _convert_barrier_mask_81356(BitField<BarrierMask> p_old_barrier); +public: + enum BarrierMask{ + BARRIER_MASK_VERTEX = 1, + BARRIER_MASK_FRAGMENT = 8, + BARRIER_MASK_COMPUTE = 2, + BARRIER_MASK_TRANSFER = 4, + + BARRIER_MASK_RASTER = BARRIER_MASK_VERTEX | BARRIER_MASK_FRAGMENT, // 9, + BARRIER_MASK_ALL_BARRIERS = 0x7FFF, // all flags set + BARRIER_MASK_NO_BARRIER = 0x8000, + }; + + void barrier(BitField<BarrierMask> p_from = BARRIER_MASK_ALL_BARRIERS, BitField<BarrierMask> p_to = BARRIER_MASK_ALL_BARRIERS); + void full_barrier(); + void draw_command_insert_label(String p_label_name, const Color &p_color = Color(1, 1, 1, 1)); + Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); + Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids); + Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>()); + Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits); + +private: void _draw_list_end_bind_compat_81356(BitField<BarrierMask> p_post_barrier); void _compute_list_end_bind_compat_81356(BitField<BarrierMask> p_post_barrier); void _barrier_bind_compat_81356(BitField<BarrierMask> p_from, BitField<BarrierMask> p_to); + void _draw_list_end_bind_compat_84976(BitField<BarrierMask> p_post_barrier); + void _compute_list_end_bind_compat_84976(BitField<BarrierMask> p_post_barrier); + InitialAction _convert_initial_action_84976(InitialAction p_old_initial_action); + FinalAction _convert_final_action_84976(FinalAction p_old_final_action); + DrawListID _draw_list_begin_bind_compat_84976(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures); + ComputeListID _compute_list_begin_bind_compat_84976(bool p_allow_draw_overlap); + Error _buffer_update_bind_compat_84976(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier); + Error _buffer_clear_bind_compat_84976(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier); + Error _texture_update_bind_compat_84976(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier); + Error _texture_copy_bind_compat_84976(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier); + Error _texture_clear_bind_compat_84976(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier); + Error _texture_resolve_multisample_bind_compat_84976(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier); #endif public: @@ -875,6 +920,9 @@ public: }; private: + static const uint32_t MAX_UNIFORM_SETS = 16; + static const uint32_t MAX_PUSH_CONSTANT_SIZE = 128; + // This structure contains the descriptor set. They _need_ to be allocated // for a shader (and will be erased when this shader is erased), but should // work for other shaders as long as the hash matches. This covers using @@ -894,8 +942,9 @@ private: }; LocalVector<AttachableTexture> attachable_textures; // Used for validation. - Vector<Texture *> mutable_sampled_textures; // Used for layout change. - Vector<Texture *> mutable_storage_textures; // Used for layout change. + Vector<RDG::ResourceTracker *> draw_trackers; + Vector<RDG::ResourceUsage> draw_trackers_usage; + HashMap<RID, RDG::ResourceUsage> untracked_usage; InvalidationCallback invalidated_callback = nullptr; void *invalidated_callback_userdata = nullptr; }; @@ -941,6 +990,7 @@ private: uint32_t shader_layout_hash = 0; Vector<uint32_t> set_formats; RDD::PipelineID driver_id; + BitField<RDD::PipelineStageBits> stage_bits; uint32_t push_constant_size = 0; }; @@ -986,8 +1036,6 @@ public: /**** DRAW LISTS (II) ****/ /*************************/ - typedef int64_t DrawListID; - private: // Draw list contains both the command buffer // used for drawing as well as a LOT of @@ -995,20 +1043,7 @@ private: // validation is cheap so most of it can // also run in release builds. - // When using split command lists, this is - // implemented internally using secondary command - // buffers. As they can be created in threads, - // each needs its own command pool. - - struct SplitDrawListAllocator { - RDD::CommandPoolID command_pool; - Vector<RDD::CommandBufferID> command_buffers; // One for each frame. - }; - - Vector<SplitDrawListAllocator> split_draw_list_allocators; - struct DrawList { - RDD::CommandBufferID command_buffer; // If persistent, this is owned, otherwise it's shared with the ringbuffer. Rect2i viewport; bool viewport_set = false; @@ -1040,9 +1075,8 @@ private: uint32_t vertex_array_size = 0; uint32_t vertex_max_instances_allowed = 0xFFFFFFFF; bool index_buffer_uses_restart_indices = false; - uint32_t index_array_size = 0; + uint32_t index_array_count = 0; uint32_t index_array_max_index = 0; - uint32_t index_array_offset = 0; Vector<uint32_t> set_formats; Vector<bool> set_bound; Vector<RID> set_rids; @@ -1060,13 +1094,12 @@ private: #else struct Validation { uint32_t vertex_array_size = 0; - uint32_t index_array_size = 0; - uint32_t index_array_offset; + uint32_t index_array_count = 0; } validation; #endif }; - DrawList *draw_list = nullptr; // One for regular draw lists, multiple for split. + DrawList *draw_list = nullptr; uint32_t draw_list_subpass_count = 0; uint32_t draw_list_count = 0; RDD::RenderPassID draw_list_render_pass; @@ -1076,23 +1109,20 @@ private: #endif uint32_t draw_list_current_subpass = 0; - bool draw_list_split = false; Vector<RID> draw_list_bound_textures; - Vector<RID> draw_list_storage_textures; - bool draw_list_unbind_color_textures = false; - bool draw_list_unbind_depth_textures = false; void _draw_list_insert_clear_region(DrawList *p_draw_list, Framebuffer *p_framebuffer, Point2i p_viewport_offset, Point2i p_viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil); Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, RDD::FramebufferID *r_framebuffer, RDD::RenderPassID *r_render_pass, uint32_t *r_subpass_count); - Error _draw_list_render_pass_begin(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i p_viewport_offset, Point2i p_viewport_size, RDD::FramebufferID p_framebuffer_driver_id, RDD::RenderPassID p_render_pass, RDD::CommandBufferID p_command_buffer, RDD::CommandBufferType p_cmd_buffer_mode, const Vector<RID> &p_storage_textures, bool p_constrained_to_region); + Error _draw_list_render_pass_begin(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i p_viewport_offset, Point2i p_viewport_size, RDD::FramebufferID p_framebuffer_driver_id, RDD::RenderPassID p_render_pass); + void _draw_list_set_viewport(Rect2i p_rect); + void _draw_list_set_scissor(Rect2i p_rect); _FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id); - Error _draw_list_allocate(const Rect2i &p_viewport, uint32_t p_splits, uint32_t p_subpass); + Error _draw_list_allocate(const Rect2i &p_viewport, uint32_t p_subpass); void _draw_list_free(Rect2i *r_last_viewport = nullptr); public: DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()); - DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); - Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); + DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color); void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline); @@ -1109,20 +1139,15 @@ public: uint32_t draw_list_get_current_pass(); DrawListID draw_list_switch_to_next_pass(); - Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids); - void draw_list_end(BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); + void draw_list_end(); +private: /***********************/ /**** COMPUTE LISTS ****/ /***********************/ - typedef int64_t ComputeListID; - -private: struct ComputeList { - RDD::CommandBufferID command_buffer; // If persistent, this is owned, otherwise it's shared with the ringbuffer. - struct SetState { uint32_t pipeline_expected_format = 0; uint32_t uniform_set_format = 0; @@ -1132,7 +1157,6 @@ private: }; struct State { - HashSet<Texture *> textures_to_sampled_layout; SetState sets[MAX_UNIFORM_SETS]; uint32_t set_count = 0; RID pipeline; @@ -1140,7 +1164,8 @@ private: RDD::ShaderID pipeline_shader_driver_id; uint32_t pipeline_shader_layout_hash = 0; uint32_t local_group_size[3] = { 0, 0, 0 }; - bool allow_draw_overlap; + uint8_t push_constant_data[MAX_PUSH_CONSTANT_SIZE] = {}; + uint32_t push_constant_size = 0; } state; #ifdef DEBUG_ENABLED @@ -1160,11 +1185,10 @@ private: }; ComputeList *compute_list = nullptr; - - void _compute_list_add_barrier(BitField<BarrierMask> p_post_barrier, BitField<RDD::PipelineStageBits> p_stages, BitField<RDD::BarrierAccessBits> p_access); + ComputeList::State compute_list_barrier_state; public: - ComputeListID compute_list_begin(bool p_allow_draw_overlap = false); + ComputeListID compute_list_begin(); void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline); void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index); void compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size); @@ -1173,10 +1197,22 @@ public: void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset); void compute_list_add_barrier(ComputeListID p_list); - void compute_list_end(BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); + void compute_list_end(); - void barrier(BitField<BarrierMask> p_from = BARRIER_MASK_ALL_BARRIERS, BitField<BarrierMask> p_to = BARRIER_MASK_ALL_BARRIERS); - void full_barrier(); +private: + /***********************/ + /**** COMMAND GRAPH ****/ + /***********************/ + + bool _texture_make_mutable(Texture *p_texture, RID p_texture_id); + bool _buffer_make_mutable(Buffer *p_buffer, RID p_buffer_id); + bool _vertex_array_make_mutable(VertexArray *p_vertex_array, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker); + bool _index_array_make_mutable(IndexArray *p_index_array, RDG::ResourceTracker *p_resource_tracker); + bool _uniform_set_make_mutable(UniformSet *p_uniform_set, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker); + bool _dependency_make_mutable(RID p_id, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker); + bool _dependencies_make_mutable(RID p_id, RDG::ResourceTracker *p_resource_tracker); + + RenderingDeviceGraph draw_graph; /**************************/ /**** FRAME MANAGEMENT ****/ @@ -1258,7 +1294,7 @@ private: template <class T> void _free_rids(T &p_owner, const char *p_type); - void _finalize_command_bufers(); + void _finalize_command_buffers(bool p_postpare); void _begin_frame(); #ifdef DEV_ENABLED @@ -1311,7 +1347,6 @@ public: void set_resource_name(RID p_id, const String &p_name); void draw_command_begin_label(String p_label_name, const Color &p_color = Color(1, 1, 1, 1)); - void draw_command_insert_label(String p_label_name, const Color &p_color = Color(1, 1, 1, 1)); void draw_command_end_label(); String get_device_vendor_name() const; @@ -1353,16 +1388,13 @@ private: RID _uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set); - Error _buffer_update_bind(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); + Error _buffer_update_bind(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data); RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants); RID _compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants); - DrawListID _draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>()); - Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>()); void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size); void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size); - Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits); }; VARIANT_ENUM_CAST(RenderingDevice::DeviceType) @@ -1371,7 +1403,6 @@ VARIANT_ENUM_CAST(RenderingDevice::ShaderStage) VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage) VARIANT_ENUM_CAST(RenderingDevice::CompareOperator) VARIANT_ENUM_CAST(RenderingDevice::DataFormat) -VARIANT_BITFIELD_CAST(RenderingDevice::BarrierMask); VARIANT_ENUM_CAST(RenderingDevice::TextureType) VARIANT_ENUM_CAST(RenderingDevice::TextureSamples) VARIANT_BITFIELD_CAST(RenderingDevice::TextureUsageBits) @@ -1399,6 +1430,10 @@ VARIANT_ENUM_CAST(RenderingDevice::Limit) VARIANT_ENUM_CAST(RenderingDevice::MemoryType) VARIANT_ENUM_CAST(RenderingDevice::Features) +#ifndef DISABLE_DEPRECATED +VARIANT_BITFIELD_CAST(RenderingDevice::BarrierMask); +#endif + typedef RenderingDevice RD; #endif // RENDERING_DEVICE_H diff --git a/servers/rendering/rendering_device_commons.h b/servers/rendering/rendering_device_commons.h index dabd0c0867..a8936f8cca 100644 --- a/servers/rendering/rendering_device_commons.h +++ b/servers/rendering/rendering_device_commons.h @@ -379,6 +379,7 @@ public: TEXTURE_SLICE_CUBEMAP, TEXTURE_SLICE_3D, TEXTURE_SLICE_2D_ARRAY, + TEXTURE_SLICE_MAX }; /*****************/ @@ -910,6 +911,7 @@ protected: Vector<Vector<ShaderUniform>> uniform_sets; Vector<ShaderSpecializationConstant> specialization_constants; + Vector<ShaderStage> stages; }; struct ShaderReflection : public ShaderDescription { diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h index bb71a29bbc..663222e69d 100644 --- a/servers/rendering/rendering_device_driver.h +++ b/servers/rendering/rendering_device_driver.h @@ -181,6 +181,10 @@ public: BUFFER_USAGE_INDIRECT_BIT = (1 << 8), }; + enum { + BUFFER_WHOLE_SIZE = ~0ULL + }; + virtual BufferID buffer_create(uint64_t p_size, BitField<BufferUsageBits> p_usage, MemoryAllocationType p_allocation_type) = 0; // Only for a buffer with BUFFER_USAGE_TEXEL_BIT. virtual bool buffer_set_texel_format(BufferID p_buffer, DataFormat p_format) = 0; @@ -535,6 +539,8 @@ public: float depth; uint32_t stencil; }; + + RenderPassClearValue() {} }; struct AttachmentClear { @@ -621,6 +627,13 @@ public: virtual void command_timestamp_write(CommandBufferID p_cmd_buffer, QueryPoolID p_pool_id, uint32_t p_index) = 0; /****************/ + /**** LABELS ****/ + /****************/ + + virtual void command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) = 0; + virtual void command_end_label(CommandBufferID p_cmd_buffer) = 0; + + /****************/ /**** SCREEN ****/ /****************/ diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp new file mode 100644 index 0000000000..bfacd38065 --- /dev/null +++ b/servers/rendering/rendering_device_graph.cpp @@ -0,0 +1,1930 @@ +/**************************************************************************/ +/* rendering_device_graph.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "rendering_device_graph.h" + +#define PRINT_RENDER_GRAPH 0 +#define FORCE_FULL_ACCESS_BITS 0 +#define PRINT_RESOURCE_TRACKER_TOTAL 0 + +RenderingDeviceGraph::RenderingDeviceGraph() { + // Default initialization. +} + +RenderingDeviceGraph::~RenderingDeviceGraph() { + _wait_for_secondary_command_buffer_tasks(); + + for (Frame &f : frames) { + for (SecondaryCommandBuffer &secondary : f.secondary_command_buffers) { + if (secondary.command_pool.id != 0) { + driver->command_pool_free(secondary.command_pool); + } + } + } +} + +bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) { + switch (p_usage) { + case RESOURCE_USAGE_TRANSFER_FROM: + case RESOURCE_USAGE_UNIFORM_BUFFER_READ: + case RESOURCE_USAGE_INDIRECT_BUFFER_READ: + case RESOURCE_USAGE_TEXTURE_BUFFER_READ: + case RESOURCE_USAGE_STORAGE_BUFFER_READ: + case RESOURCE_USAGE_VERTEX_BUFFER_READ: + case RESOURCE_USAGE_INDEX_BUFFER_READ: + case RESOURCE_USAGE_TEXTURE_SAMPLE: + case RESOURCE_USAGE_STORAGE_IMAGE_READ: + case RESOURCE_USAGE_ATTACHMENT_COLOR_READ: + case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ: + return false; + case RESOURCE_USAGE_TRANSFER_TO: + case RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE: + case RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE: + case RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE: + case RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE: + case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE: + return true; + default: + DEV_ASSERT(false && "Invalid resource tracker usage."); + return false; + } +} + +RDD::TextureLayout RenderingDeviceGraph::_usage_to_image_layout(ResourceUsage p_usage) { + switch (p_usage) { + case RESOURCE_USAGE_TRANSFER_FROM: + return RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL; + case RESOURCE_USAGE_TRANSFER_TO: + return RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL; + case RESOURCE_USAGE_TEXTURE_SAMPLE: + return RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + case RESOURCE_USAGE_STORAGE_IMAGE_READ: + case RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE: + return RDD::TEXTURE_LAYOUT_GENERAL; + case RESOURCE_USAGE_ATTACHMENT_COLOR_READ: + case RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE: + return RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ: + return RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE: + return RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + case RESOURCE_USAGE_NONE: + return RDD::TEXTURE_LAYOUT_UNDEFINED; + default: + DEV_ASSERT(false && "Invalid resource tracker usage or not an image usage."); + return RDD::TEXTURE_LAYOUT_UNDEFINED; + } +} + +RDD::BarrierAccessBits RenderingDeviceGraph::_usage_to_access_bits(ResourceUsage p_usage) { +#if FORCE_FULL_ACCESS_BITS + return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_MEMORY_READ_BIT | RDD::BARRIER_ACCESS_MEMORY_WRITE_BIT); +#else + switch (p_usage) { + case RESOURCE_USAGE_NONE: + return RDD::BarrierAccessBits(0); + case RESOURCE_USAGE_TRANSFER_FROM: + return RDD::BARRIER_ACCESS_TRANSFER_READ_BIT; + case RESOURCE_USAGE_TRANSFER_TO: + return RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT; + case RESOURCE_USAGE_UNIFORM_BUFFER_READ: + return RDD::BARRIER_ACCESS_UNIFORM_READ_BIT; + case RESOURCE_USAGE_INDIRECT_BUFFER_READ: + return RDD::BARRIER_ACCESS_INDIRECT_COMMAND_READ_BIT; + case RESOURCE_USAGE_STORAGE_BUFFER_READ: + case RESOURCE_USAGE_STORAGE_IMAGE_READ: + case RESOURCE_USAGE_TEXTURE_BUFFER_READ: + case RESOURCE_USAGE_TEXTURE_SAMPLE: + return RDD::BARRIER_ACCESS_SHADER_READ_BIT; + case RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE: + case RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE: + case RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE: + return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_SHADER_READ_BIT | RDD::BARRIER_ACCESS_SHADER_WRITE_BIT); + case RESOURCE_USAGE_VERTEX_BUFFER_READ: + return RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + case RESOURCE_USAGE_INDEX_BUFFER_READ: + return RDD::BARRIER_ACCESS_INDEX_READ_BIT; + case RESOURCE_USAGE_ATTACHMENT_COLOR_READ: + return RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT; + case RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE: + return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT | RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ: + return RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE: + return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + default: + DEV_ASSERT(false && "Invalid usage."); + return RDD::BarrierAccessBits(0); + } +#endif +} + +int32_t RenderingDeviceGraph::_add_to_command_list(int32_t p_command_index, int32_t p_list_index) { + DEV_ASSERT(p_command_index < int32_t(command_count)); + DEV_ASSERT(p_list_index < int32_t(command_list_nodes.size())); + + int32_t next_index = int32_t(command_list_nodes.size()); + command_list_nodes.resize(next_index + 1); + + RecordedCommandListNode &new_node = command_list_nodes[next_index]; + new_node.command_index = p_command_index; + new_node.next_list_index = p_list_index; + return next_index; +} + +void RenderingDeviceGraph::_add_adjacent_command(int32_t p_previous_command_index, int32_t p_command_index, RecordedCommand *r_command) { + const uint32_t previous_command_data_offset = command_data_offsets[p_previous_command_index]; + RecordedCommand &previous_command = *reinterpret_cast<RecordedCommand *>(&command_data[previous_command_data_offset]); + previous_command.adjacent_command_list_index = _add_to_command_list(p_command_index, previous_command.adjacent_command_list_index); + r_command->src_stages = r_command->src_stages | previous_command.dst_stages; +} + +int32_t RenderingDeviceGraph::_add_to_write_list(int32_t p_command_index, Rect2i suberesources, int32_t p_list_index) { + DEV_ASSERT(p_command_index < int32_t(command_count)); + DEV_ASSERT(p_list_index < int32_t(write_list_nodes.size())); + + int32_t next_index = int32_t(write_list_nodes.size()); + write_list_nodes.resize(next_index + 1); + + RecordedWriteListNode &new_node = write_list_nodes[next_index]; + new_node.command_index = p_command_index; + new_node.next_list_index = p_list_index; + new_node.subresources = suberesources; + return next_index; +} + +RenderingDeviceGraph::RecordedCommand *RenderingDeviceGraph::_allocate_command(uint32_t p_command_size, int32_t &r_command_index) { + uint32_t command_data_offset = command_data.size(); + command_data_offsets.push_back(command_data_offset); + command_data.resize(command_data_offset + p_command_size); + r_command_index = command_count++; + RecordedCommand *new_command = reinterpret_cast<RecordedCommand *>(&command_data[command_data_offset]); + *new_command = RecordedCommand(); + return new_command; +} + +RenderingDeviceGraph::DrawListInstruction *RenderingDeviceGraph::_allocate_draw_list_instruction(uint32_t p_instruction_size) { + uint32_t draw_list_data_offset = draw_instruction_list.data.size(); + draw_instruction_list.data.resize(draw_list_data_offset + p_instruction_size); + return reinterpret_cast<DrawListInstruction *>(&draw_instruction_list.data[draw_list_data_offset]); +} + +RenderingDeviceGraph::ComputeListInstruction *RenderingDeviceGraph::_allocate_compute_list_instruction(uint32_t p_instruction_size) { + uint32_t compute_list_data_offset = compute_instruction_list.data.size(); + compute_instruction_list.data.resize(compute_list_data_offset + p_instruction_size); + return reinterpret_cast<ComputeListInstruction *>(&compute_instruction_list.data[compute_list_data_offset]); +} + +void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_trackers, ResourceUsage *p_resource_usages, uint32_t p_resource_count, int32_t p_command_index, RecordedCommand *r_command) { + if (command_label_index >= 0) { + // If a label is active, tag the command with the label. + r_command->label_index = command_label_index; + } + + if (r_command->type == RecordedCommand::TYPE_CAPTURE_TIMESTAMP) { + // All previous commands starting from the previous timestamp should be adjacent to this command. + int32_t start_command_index = uint32_t(MAX(command_timestamp_index, 0)); + for (int32_t i = start_command_index; i < p_command_index; i++) { + _add_adjacent_command(i, p_command_index, r_command); + } + + // Make this command the new active timestamp command. + command_timestamp_index = p_command_index; + } else if (command_timestamp_index >= 0) { + // Timestamp command should be adjacent to this command. + _add_adjacent_command(command_timestamp_index, p_command_index, r_command); + } + + if (command_synchronization_pending) { + // All previous commands should be adjacent to this command. + int32_t start_command_index = uint32_t(MAX(command_synchronization_index, 0)); + for (int32_t i = start_command_index; i < p_command_index; i++) { + _add_adjacent_command(i, p_command_index, r_command); + } + + command_synchronization_index = p_command_index; + command_synchronization_pending = false; + } else if (command_synchronization_index >= 0) { + // Synchronization command should be adjacent to this command. + _add_adjacent_command(command_synchronization_index, p_command_index, r_command); + } + + for (uint32_t i = 0; i < p_resource_count; i++) { + ResourceTracker *resource_tracker = p_resource_trackers[i]; + DEV_ASSERT(resource_tracker != nullptr); + + resource_tracker->reset_if_outdated(tracking_frame); + + ResourceUsage new_resource_usage = p_resource_usages[i]; + bool write_usage = _is_write_usage(new_resource_usage); + BitField<RDD::BarrierAccessBits> new_usage_access = _usage_to_access_bits(new_resource_usage); + bool is_resource_a_slice = resource_tracker->parent != nullptr; + if (is_resource_a_slice) { + // This resource depends on a parent resource. + resource_tracker->parent->reset_if_outdated(tracking_frame); + + if (resource_tracker->texture_slice_command_index != p_command_index) { + // Indicate this slice has been used by this command. + resource_tracker->texture_slice_command_index = p_command_index; + } + + if (resource_tracker->parent->usage == RESOURCE_USAGE_NONE) { + if (resource_tracker->parent->texture_driver_id != 0) { + // If the resource is a texture, we transition it entirely to the layout determined by the first slice that uses it. + _add_texture_barrier_to_command(resource_tracker->parent->texture_driver_id, RDD::BarrierAccessBits(0), new_usage_access, RDG::RESOURCE_USAGE_NONE, new_resource_usage, resource_tracker->parent->texture_subresources, command_normalization_barriers, r_command->normalization_barrier_index, r_command->normalization_barrier_count); + } + + // If the parent hasn't been used yet, we assign the usage of the slice to the entire resource. + resource_tracker->parent->usage = new_resource_usage; + + // Also assign the usage to the slice and consider it a write operation. + resource_tracker->usage = new_resource_usage; + write_usage = true; + } else if (resource_tracker->in_parent_dirty_list) { + if (resource_tracker->parent->usage == new_resource_usage) { + // The slice will be transitioned to the resource of the parent and can be deleted from the dirty list. + ResourceTracker *previous_tracker = nullptr; + ResourceTracker *current_tracker = resource_tracker->parent->dirty_shared_list; + bool initialized_dirty_rect = false; + while (current_tracker != nullptr) { + if (current_tracker == resource_tracker) { + current_tracker->in_parent_dirty_list = false; + + if (previous_tracker != nullptr) { + previous_tracker->next_shared = current_tracker->next_shared; + } else { + resource_tracker->parent->dirty_shared_list = current_tracker->next_shared; + } + + current_tracker = current_tracker->next_shared; + } else { + if (initialized_dirty_rect) { + resource_tracker->parent->texture_slice_or_dirty_rect = resource_tracker->parent->texture_slice_or_dirty_rect.merge(current_tracker->texture_slice_or_dirty_rect); + } else { + resource_tracker->parent->texture_slice_or_dirty_rect = current_tracker->texture_slice_or_dirty_rect; + initialized_dirty_rect = true; + } + + previous_tracker = current_tracker; + current_tracker = current_tracker->next_shared; + } + } + } + } else { + if (resource_tracker->parent->dirty_shared_list != nullptr && resource_tracker->parent->texture_slice_or_dirty_rect.intersects(resource_tracker->texture_slice_or_dirty_rect)) { + // There's an intersection with the current dirty area of the parent and the slice. We must verify if the intersection is against a slice + // that was used in this command or not. Any slice we can find that wasn't used by this command must be reverted to the layout of the parent. + ResourceTracker *previous_tracker = nullptr; + ResourceTracker *current_tracker = resource_tracker->parent->dirty_shared_list; + bool initialized_dirty_rect = false; + while (current_tracker != nullptr) { + if (current_tracker->texture_slice_or_dirty_rect.intersects(resource_tracker->texture_slice_or_dirty_rect)) { + if (current_tracker->command_frame == tracking_frame && current_tracker->texture_slice_command_index == p_command_index) { + ERR_FAIL_MSG("Texture slices that overlap can't be used in the same command."); + } else { + // Delete the slice from the dirty list and revert it to the usage of the parent. + if (current_tracker->texture_driver_id != 0) { + _add_texture_barrier_to_command(current_tracker->texture_driver_id, current_tracker->usage_access, new_usage_access, current_tracker->usage, resource_tracker->parent->usage, current_tracker->texture_subresources, command_normalization_barriers, r_command->normalization_barrier_index, r_command->normalization_barrier_count); + } + + current_tracker->in_parent_dirty_list = false; + + if (previous_tracker != nullptr) { + previous_tracker->next_shared = current_tracker->next_shared; + } else { + resource_tracker->parent->dirty_shared_list = current_tracker->next_shared; + } + + current_tracker = current_tracker->next_shared; + } + } else { + // Recalculate the dirty rect of the parent so the deleted slices are excluded. + if (initialized_dirty_rect) { + resource_tracker->parent->texture_slice_or_dirty_rect = resource_tracker->parent->texture_slice_or_dirty_rect.merge(current_tracker->texture_slice_or_dirty_rect); + } else { + resource_tracker->parent->texture_slice_or_dirty_rect = current_tracker->texture_slice_or_dirty_rect; + initialized_dirty_rect = true; + } + + previous_tracker = current_tracker; + current_tracker = current_tracker->next_shared; + } + } + } + + // If it wasn't in the list, assume the usage is the same as the parent. + resource_tracker->usage = resource_tracker->parent->usage; + + if (resource_tracker->usage != new_resource_usage) { + // Insert to the dirty list if the requested usage is different. + resource_tracker->next_shared = resource_tracker->parent->dirty_shared_list; + resource_tracker->parent->dirty_shared_list = resource_tracker; + resource_tracker->in_parent_dirty_list = true; + if (resource_tracker->parent->dirty_shared_list != nullptr) { + resource_tracker->parent->texture_slice_or_dirty_rect = resource_tracker->parent->texture_slice_or_dirty_rect.merge(resource_tracker->texture_slice_or_dirty_rect); + } else { + resource_tracker->parent->texture_slice_or_dirty_rect = resource_tracker->texture_slice_or_dirty_rect; + } + } + } + } else { + if (resource_tracker->dirty_shared_list != nullptr) { + // Consider the usage as write if we must transition any of the slices. + write_usage = true; + } + + while (resource_tracker->dirty_shared_list != nullptr) { + if (resource_tracker->dirty_shared_list->texture_driver_id != 0) { + // Transition all slices to the layout of the parent resource. + _add_texture_barrier_to_command(resource_tracker->dirty_shared_list->texture_driver_id, resource_tracker->dirty_shared_list->usage_access, new_usage_access, resource_tracker->dirty_shared_list->usage, resource_tracker->usage, resource_tracker->dirty_shared_list->texture_subresources, command_normalization_barriers, r_command->normalization_barrier_index, r_command->normalization_barrier_count); + } + + resource_tracker->dirty_shared_list->in_parent_dirty_list = false; + resource_tracker->dirty_shared_list = resource_tracker->dirty_shared_list->next_shared; + } + } + + // Use the resource's parent tracker directly for all search operations. + bool resource_has_parent = resource_tracker->parent != nullptr; + ResourceTracker *search_tracker = resource_has_parent ? resource_tracker->parent : resource_tracker; + const RDD::TextureSubresourceRange &subresources = resource_tracker->texture_subresources; + Rect2i resource_tracker_rect(subresources.base_mipmap, subresources.base_layer, subresources.mipmap_count, subresources.layer_count); + bool different_usage = resource_tracker->usage != new_resource_usage; + bool write_usage_after_write = (write_usage && search_tracker->write_command_or_list_index >= 0); + if (different_usage || write_usage_after_write) { + // A barrier must be pushed if the usage is different of it's a write usage and there was already a command that wrote to this resource previously. + if (resource_tracker->texture_driver_id.id != 0) { + if (resource_tracker->usage_access.is_empty()) { + // FIXME: If the tracker does not know the previous type of usage, assume the generic memory write one. + // Tracking access bits across texture slices can be tricky, so this failsafe can be removed once that's improved. + resource_tracker->usage_access = RDD::BARRIER_ACCESS_MEMORY_WRITE_BIT; + } + + _add_texture_barrier_to_command(resource_tracker->texture_driver_id, resource_tracker->usage_access, new_usage_access, resource_tracker->usage, new_resource_usage, resource_tracker->texture_subresources, command_transition_barriers, r_command->transition_barrier_index, r_command->transition_barrier_count); + } else if (resource_tracker->buffer_driver_id.id != 0) { +#if USE_BUFFER_BARRIERS + _add_buffer_barrier_to_command(resource_tracker->buffer_driver_id, resource_tracker->usage_access, new_usage_access, r_command->buffer_barrier_index, r_command->buffer_barrier_count); +#endif + // FIXME: Memory barriers are currently pushed regardless of whether buffer barriers are being used or not. Refer to the comment on the + // definition of USE_BUFFER_BARRIERS for the reason behind this. This can be fixed to be one case or the other once it's been confirmed + // the buffer and memory barrier behavior discrepancy has been solved. + r_command->memory_barrier.src_access = resource_tracker->usage_access; + r_command->memory_barrier.dst_access = new_usage_access; + } else { + DEV_ASSERT(false && "Resource tracker does not contain a valid buffer or texture ID."); + } + } + + // Always update the access of the tracker according to the latest usage. + resource_tracker->usage_access = new_usage_access; + + if (different_usage) { + // Even if the usage of the resource isn't a write usage explicitly, a different usage implies a transition and it should therefore be considered a write. + write_usage = true; + resource_tracker->usage = new_resource_usage; + } + + if (search_tracker->write_command_or_list_index >= 0) { + if (search_tracker->write_command_list_enabled) { + // Make this command adjacent to any commands that wrote to this resource and intersect with the slice if it applies. + // For buffers or textures that never use slices, this list will only be one element long at most. + int32_t previous_write_list_index = -1; + int32_t write_list_index = search_tracker->write_command_or_list_index; + while (write_list_index >= 0) { + const RecordedWriteListNode &write_list_node = write_list_nodes[write_list_index]; + if (!resource_has_parent || resource_tracker_rect.intersects(write_list_node.subresources)) { + if (write_list_node.command_index == p_command_index) { + ERR_FAIL_COND_MSG(!resource_has_parent, "Command can't have itself as a dependency."); + } else { + // Command is dependent on this command. Add this command to the adjacency list of the write command. + _add_adjacent_command(write_list_node.command_index, p_command_index, r_command); + + if (resource_has_parent && write_usage && resource_tracker_rect.encloses(write_list_node.subresources)) { + // Eliminate redundant writes from the list. + if (previous_write_list_index >= 0) { + RecordedWriteListNode &previous_list_node = write_list_nodes[previous_write_list_index]; + previous_list_node.next_list_index = write_list_node.next_list_index; + } else { + search_tracker->write_command_or_list_index = write_list_node.next_list_index; + } + + write_list_index = write_list_node.next_list_index; + continue; + } + } + } + + previous_write_list_index = write_list_index; + write_list_index = write_list_node.next_list_index; + } + } else { + // The index is just the latest command index that wrote to the resource. + if (search_tracker->write_command_or_list_index == p_command_index) { + ERR_FAIL_MSG("Command can't have itself as a dependency."); + } else { + _add_adjacent_command(search_tracker->write_command_or_list_index, p_command_index, r_command); + } + } + } + + if (write_usage) { + if (resource_has_parent) { + if (!search_tracker->write_command_list_enabled && search_tracker->write_command_or_list_index >= 0) { + // Write command list was not being used but there was a write command recorded. Add a new node with the entire parent resource's subresources and the recorded command index to the list. + const RDD::TextureSubresourceRange &tracker_subresources = search_tracker->texture_subresources; + Rect2i tracker_rect(tracker_subresources.base_mipmap, tracker_subresources.base_layer, tracker_subresources.mipmap_count, tracker_subresources.layer_count); + search_tracker->write_command_or_list_index = _add_to_write_list(search_tracker->write_command_or_list_index, tracker_rect, -1); + } + + search_tracker->write_command_or_list_index = _add_to_write_list(p_command_index, resource_tracker_rect, search_tracker->write_command_or_list_index); + search_tracker->write_command_list_enabled = true; + } else { + search_tracker->write_command_or_list_index = p_command_index; + search_tracker->write_command_list_enabled = false; + } + + // We add this command to the adjacency list of all commands that were reading from this resource. We clear the list in the process. + int32_t previous_command_list_index = -1; + int32_t read_command_list_index = search_tracker->read_command_list_index; + while (read_command_list_index >= 0) { + const RecordedCommandListNode &command_list_node = command_list_nodes[read_command_list_index]; + if (command_list_node.command_index == p_command_index) { + if (!resource_has_parent) { + // Slices are allowed to be in different usages in the same command as they are guaranteed to have no overlap in the same command. + ERR_FAIL_MSG("Command can't have itself as a dependency."); + } else { + // Advance to the next element. + read_command_list_index = command_list_node.next_list_index; + previous_command_list_index = read_command_list_index; + } + } else { + if (previous_command_list_index >= 0) { + // Erase this element and connect the previous one to the next element. + command_list_nodes[previous_command_list_index].next_list_index = command_list_node.next_list_index; + read_command_list_index = command_list_node.next_list_index; + previous_command_list_index = read_command_list_index; + } else { + // Erase this element from the head of the list. + DEV_ASSERT(search_tracker->read_command_list_index == read_command_list_index); + read_command_list_index = command_list_node.next_list_index; + search_tracker->read_command_list_index = read_command_list_index; + } + + // Add this command to the adjacency list of each command that was reading this resource. + _add_adjacent_command(command_list_node.command_index, p_command_index, r_command); + } + } + } else { + // We add a read dependency to the tracker to indicate this command reads from the resource. + search_tracker->read_command_list_index = _add_to_command_list(p_command_index, search_tracker->read_command_list_index); + } + } +} + +void RenderingDeviceGraph::_add_texture_barrier_to_command(RDD::TextureID p_texture_id, BitField<RDD::BarrierAccessBits> p_src_access, BitField<RDD::BarrierAccessBits> p_dst_access, ResourceUsage p_prev_usage, ResourceUsage p_next_usage, RDD::TextureSubresourceRange p_subresources, LocalVector<RDD::TextureBarrier> &r_barrier_vector, int32_t &r_barrier_index, int32_t &r_barrier_count) { + if (!driver_honors_barriers) { + return; + } + + if (r_barrier_index < 0) { + r_barrier_index = r_barrier_vector.size(); + } + + RDD::TextureBarrier texture_barrier; + texture_barrier.texture = p_texture_id; + texture_barrier.src_access = p_src_access; + texture_barrier.dst_access = p_dst_access; + texture_barrier.prev_layout = _usage_to_image_layout(p_prev_usage); + texture_barrier.next_layout = _usage_to_image_layout(p_next_usage); + texture_barrier.subresources = p_subresources; + r_barrier_vector.push_back(texture_barrier); + r_barrier_count++; +} + +#if USE_BUFFER_BARRIERS +void RenderingDeviceGraph::_add_buffer_barrier_to_command(RDD::BufferID p_buffer_id, BitField<RDD::BarrierAccessBits> p_src_access, BitField<RDD::BarrierAccessBits> p_dst_access, int32_t &r_barrier_index, int32_t &r_barrier_count) { + if (!driver_honors_barriers) { + return; + } + + if (r_barrier_index < 0) { + r_barrier_index = command_buffer_barriers.size(); + } + + RDD::BufferBarrier buffer_barrier; + buffer_barrier.buffer = p_buffer_id; + buffer_barrier.src_access = p_src_access; + buffer_barrier.dst_access = p_dst_access; + buffer_barrier.offset = 0; + buffer_barrier.size = RDD::BUFFER_WHOLE_SIZE; + command_buffer_barriers.push_back(buffer_barrier); + r_barrier_count++; +} +#endif + +void RenderingDeviceGraph::_run_compute_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) { + uint32_t instruction_data_cursor = 0; + while (instruction_data_cursor < p_instruction_data_size) { + DEV_ASSERT((instruction_data_cursor + sizeof(ComputeListInstruction)) <= p_instruction_data_size); + + const ComputeListInstruction *instruction = reinterpret_cast<const ComputeListInstruction *>(&p_instruction_data[instruction_data_cursor]); + switch (instruction->type) { + case ComputeListInstruction::TYPE_BIND_PIPELINE: { + const ComputeListBindPipelineInstruction *bind_pipeline_instruction = reinterpret_cast<const ComputeListBindPipelineInstruction *>(instruction); + driver->command_bind_compute_pipeline(p_command_buffer, bind_pipeline_instruction->pipeline); + instruction_data_cursor += sizeof(ComputeListBindPipelineInstruction); + } break; + case ComputeListInstruction::TYPE_BIND_UNIFORM_SET: { + const ComputeListBindUniformSetInstruction *bind_uniform_set_instruction = reinterpret_cast<const ComputeListBindUniformSetInstruction *>(instruction); + driver->command_bind_compute_uniform_set(p_command_buffer, bind_uniform_set_instruction->uniform_set, bind_uniform_set_instruction->shader, bind_uniform_set_instruction->set_index); + instruction_data_cursor += sizeof(ComputeListBindUniformSetInstruction); + } break; + case ComputeListInstruction::TYPE_DISPATCH: { + const ComputeListDispatchInstruction *dispatch_instruction = reinterpret_cast<const ComputeListDispatchInstruction *>(instruction); + driver->command_compute_dispatch(p_command_buffer, dispatch_instruction->x_groups, dispatch_instruction->y_groups, dispatch_instruction->z_groups); + instruction_data_cursor += sizeof(ComputeListDispatchInstruction); + } break; + case ComputeListInstruction::TYPE_DISPATCH_INDIRECT: { + const ComputeListDispatchIndirectInstruction *dispatch_indirect_instruction = reinterpret_cast<const ComputeListDispatchIndirectInstruction *>(instruction); + driver->command_compute_dispatch_indirect(p_command_buffer, dispatch_indirect_instruction->buffer, dispatch_indirect_instruction->offset); + instruction_data_cursor += sizeof(ComputeListDispatchIndirectInstruction); + } break; + case ComputeListInstruction::TYPE_SET_PUSH_CONSTANT: { + const ComputeListSetPushConstantInstruction *set_push_constant_instruction = reinterpret_cast<const ComputeListSetPushConstantInstruction *>(instruction); + const VectorView push_constant_data_view(reinterpret_cast<const uint32_t *>(set_push_constant_instruction->data()), set_push_constant_instruction->size / sizeof(uint32_t)); + driver->command_bind_push_constants(p_command_buffer, set_push_constant_instruction->shader, 0, push_constant_data_view); + instruction_data_cursor += sizeof(ComputeListSetPushConstantInstruction); + instruction_data_cursor += set_push_constant_instruction->size; + } break; + case ComputeListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE: { + const ComputeListUniformSetPrepareForUseInstruction *uniform_set_prepare_for_use_instruction = reinterpret_cast<const ComputeListUniformSetPrepareForUseInstruction *>(instruction); + driver->command_uniform_set_prepare_for_use(p_command_buffer, uniform_set_prepare_for_use_instruction->uniform_set, uniform_set_prepare_for_use_instruction->shader, uniform_set_prepare_for_use_instruction->set_index); + instruction_data_cursor += sizeof(ComputeListUniformSetPrepareForUseInstruction); + } break; + default: + DEV_ASSERT(false && "Unknown compute list instruction type."); + return; + } + } +} + +void RenderingDeviceGraph::_run_draw_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) { + uint32_t instruction_data_cursor = 0; + while (instruction_data_cursor < p_instruction_data_size) { + DEV_ASSERT((instruction_data_cursor + sizeof(DrawListInstruction)) <= p_instruction_data_size); + + const DrawListInstruction *instruction = reinterpret_cast<const DrawListInstruction *>(&p_instruction_data[instruction_data_cursor]); + switch (instruction->type) { + case DrawListInstruction::TYPE_BIND_INDEX_BUFFER: { + const DrawListBindIndexBufferInstruction *bind_index_buffer_instruction = reinterpret_cast<const DrawListBindIndexBufferInstruction *>(instruction); + driver->command_render_bind_index_buffer(p_command_buffer, bind_index_buffer_instruction->buffer, bind_index_buffer_instruction->format, bind_index_buffer_instruction->offset); + instruction_data_cursor += sizeof(DrawListBindIndexBufferInstruction); + } break; + case DrawListInstruction::TYPE_BIND_PIPELINE: { + const DrawListBindPipelineInstruction *bind_pipeline_instruction = reinterpret_cast<const DrawListBindPipelineInstruction *>(instruction); + driver->command_bind_render_pipeline(p_command_buffer, bind_pipeline_instruction->pipeline); + instruction_data_cursor += sizeof(DrawListBindPipelineInstruction); + } break; + case DrawListInstruction::TYPE_BIND_UNIFORM_SET: { + const DrawListBindUniformSetInstruction *bind_uniform_set_instruction = reinterpret_cast<const DrawListBindUniformSetInstruction *>(instruction); + driver->command_bind_render_uniform_set(p_command_buffer, bind_uniform_set_instruction->uniform_set, bind_uniform_set_instruction->shader, bind_uniform_set_instruction->set_index); + instruction_data_cursor += sizeof(DrawListBindUniformSetInstruction); + } break; + case DrawListInstruction::TYPE_BIND_VERTEX_BUFFERS: { + const DrawListBindVertexBuffersInstruction *bind_vertex_buffers_instruction = reinterpret_cast<const DrawListBindVertexBuffersInstruction *>(instruction); + driver->command_render_bind_vertex_buffers(p_command_buffer, bind_vertex_buffers_instruction->vertex_buffers_count, bind_vertex_buffers_instruction->vertex_buffers(), bind_vertex_buffers_instruction->vertex_buffer_offsets()); + instruction_data_cursor += sizeof(DrawListBindVertexBuffersInstruction); + instruction_data_cursor += sizeof(RDD::BufferID) * bind_vertex_buffers_instruction->vertex_buffers_count; + instruction_data_cursor += sizeof(uint64_t) * bind_vertex_buffers_instruction->vertex_buffers_count; + } break; + case DrawListInstruction::TYPE_CLEAR_ATTACHMENTS: { + const DrawListClearAttachmentsInstruction *clear_attachments_instruction = reinterpret_cast<const DrawListClearAttachmentsInstruction *>(instruction); + const VectorView attachments_clear_view(clear_attachments_instruction->attachments_clear(), clear_attachments_instruction->attachments_clear_count); + const VectorView attachments_clear_rect_view(clear_attachments_instruction->attachments_clear_rect(), clear_attachments_instruction->attachments_clear_rect_count); + driver->command_render_clear_attachments(p_command_buffer, attachments_clear_view, attachments_clear_rect_view); + instruction_data_cursor += sizeof(DrawListClearAttachmentsInstruction); + instruction_data_cursor += sizeof(RDD::AttachmentClear) * clear_attachments_instruction->attachments_clear_count; + instruction_data_cursor += sizeof(Rect2i) * clear_attachments_instruction->attachments_clear_rect_count; + } break; + case DrawListInstruction::TYPE_DRAW: { + const DrawListDrawInstruction *draw_instruction = reinterpret_cast<const DrawListDrawInstruction *>(instruction); + driver->command_render_draw(p_command_buffer, draw_instruction->vertex_count, draw_instruction->instance_count, 0, 0); + instruction_data_cursor += sizeof(DrawListDrawInstruction); + } break; + case DrawListInstruction::TYPE_DRAW_INDEXED: { + const DrawListDrawIndexedInstruction *draw_indexed_instruction = reinterpret_cast<const DrawListDrawIndexedInstruction *>(instruction); + driver->command_render_draw_indexed(p_command_buffer, draw_indexed_instruction->index_count, draw_indexed_instruction->instance_count, draw_indexed_instruction->first_index, 0, 0); + instruction_data_cursor += sizeof(DrawListDrawIndexedInstruction); + } break; + case DrawListInstruction::TYPE_EXECUTE_COMMANDS: { + const DrawListExecuteCommandsInstruction *execute_commands_instruction = reinterpret_cast<const DrawListExecuteCommandsInstruction *>(instruction); + driver->command_buffer_execute_secondary(p_command_buffer, execute_commands_instruction->command_buffer); + instruction_data_cursor += sizeof(DrawListExecuteCommandsInstruction); + } break; + case DrawListInstruction::TYPE_NEXT_SUBPASS: { + const DrawListNextSubpassInstruction *next_subpass_instruction = reinterpret_cast<const DrawListNextSubpassInstruction *>(instruction); + driver->command_next_render_subpass(p_command_buffer, next_subpass_instruction->command_buffer_type); + instruction_data_cursor += sizeof(DrawListNextSubpassInstruction); + } break; + case DrawListInstruction::TYPE_SET_BLEND_CONSTANTS: { + const DrawListSetBlendConstantsInstruction *set_blend_constants_instruction = reinterpret_cast<const DrawListSetBlendConstantsInstruction *>(instruction); + driver->command_render_set_blend_constants(p_command_buffer, set_blend_constants_instruction->color); + instruction_data_cursor += sizeof(DrawListSetBlendConstantsInstruction); + } break; + case DrawListInstruction::TYPE_SET_LINE_WIDTH: { + const DrawListSetLineWidthInstruction *set_line_width_instruction = reinterpret_cast<const DrawListSetLineWidthInstruction *>(instruction); + driver->command_render_set_line_width(p_command_buffer, set_line_width_instruction->width); + instruction_data_cursor += sizeof(DrawListSetLineWidthInstruction); + } break; + case DrawListInstruction::TYPE_SET_PUSH_CONSTANT: { + const DrawListSetPushConstantInstruction *set_push_constant_instruction = reinterpret_cast<const DrawListSetPushConstantInstruction *>(instruction); + const VectorView push_constant_data_view(reinterpret_cast<const uint32_t *>(set_push_constant_instruction->data()), set_push_constant_instruction->size / sizeof(uint32_t)); + driver->command_bind_push_constants(p_command_buffer, set_push_constant_instruction->shader, 0, push_constant_data_view); + instruction_data_cursor += sizeof(DrawListSetPushConstantInstruction); + instruction_data_cursor += set_push_constant_instruction->size; + } break; + case DrawListInstruction::TYPE_SET_SCISSOR: { + const DrawListSetScissorInstruction *set_scissor_instruction = reinterpret_cast<const DrawListSetScissorInstruction *>(instruction); + driver->command_render_set_scissor(p_command_buffer, set_scissor_instruction->rect); + instruction_data_cursor += sizeof(DrawListSetScissorInstruction); + } break; + case DrawListInstruction::TYPE_SET_VIEWPORT: { + const DrawListSetViewportInstruction *set_viewport_instruction = reinterpret_cast<const DrawListSetViewportInstruction *>(instruction); + driver->command_render_set_viewport(p_command_buffer, set_viewport_instruction->rect); + instruction_data_cursor += sizeof(DrawListSetViewportInstruction); + } break; + case DrawListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE: { + const DrawListUniformSetPrepareForUseInstruction *uniform_set_prepare_for_use_instruction = reinterpret_cast<const DrawListUniformSetPrepareForUseInstruction *>(instruction); + driver->command_uniform_set_prepare_for_use(p_command_buffer, uniform_set_prepare_for_use_instruction->uniform_set, uniform_set_prepare_for_use_instruction->shader, uniform_set_prepare_for_use_instruction->set_index); + instruction_data_cursor += sizeof(DrawListUniformSetPrepareForUseInstruction); + } break; + default: + DEV_ASSERT(false && "Unknown draw list instruction type."); + return; + } + } +} + +void RenderingDeviceGraph::_run_secondary_command_buffer_task(const SecondaryCommandBuffer *p_secondary) { + driver->command_buffer_begin_secondary(p_secondary->command_buffer, p_secondary->render_pass, 0, p_secondary->framebuffer); + _run_draw_list_command(p_secondary->command_buffer, p_secondary->instruction_data.ptr(), p_secondary->instruction_data.size()); + driver->command_buffer_end(p_secondary->command_buffer); +} + +void RenderingDeviceGraph::_wait_for_secondary_command_buffer_tasks() { + for (uint32_t i = 0; i < frames[frame].secondary_command_buffers_used; i++) { + WorkerThreadPool::TaskID &task = frames[frame].secondary_command_buffers[i].task; + if (task != WorkerThreadPool::INVALID_TASK_ID) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(task); + task = WorkerThreadPool::INVALID_TASK_ID; + } + } +} + +void RenderingDeviceGraph::_run_render_commands(RDD::CommandBufferID p_command_buffer, int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level) { + for (uint32_t i = 0; i < p_sorted_commands_count; i++) { + const uint32_t command_index = p_sorted_commands[i].index; + const uint32_t command_data_offset = command_data_offsets[command_index]; + const RecordedCommand *command = reinterpret_cast<RecordedCommand *>(&command_data[command_data_offset]); + _run_label_command_change(p_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level); + + switch (command->type) { + case RecordedCommand::TYPE_BUFFER_CLEAR: { + const RecordedBufferClearCommand *buffer_clear_command = reinterpret_cast<const RecordedBufferClearCommand *>(command); + driver->command_clear_buffer(p_command_buffer, buffer_clear_command->buffer, buffer_clear_command->offset, buffer_clear_command->size); + } break; + case RecordedCommand::TYPE_BUFFER_COPY: { + const RecordedBufferCopyCommand *buffer_copy_command = reinterpret_cast<const RecordedBufferCopyCommand *>(command); + driver->command_copy_buffer(p_command_buffer, buffer_copy_command->source, buffer_copy_command->destination, buffer_copy_command->region); + } break; + case RecordedCommand::TYPE_BUFFER_GET_DATA: { + const RecordedBufferGetDataCommand *buffer_get_data_command = reinterpret_cast<const RecordedBufferGetDataCommand *>(command); + driver->command_copy_buffer(p_command_buffer, buffer_get_data_command->source, buffer_get_data_command->destination, buffer_get_data_command->region); + } break; + case RecordedCommand::TYPE_BUFFER_UPDATE: { + const RecordedBufferUpdateCommand *buffer_update_command = reinterpret_cast<const RecordedBufferUpdateCommand *>(command); + const RecordedBufferCopy *command_buffer_copies = buffer_update_command->buffer_copies(); + for (uint32_t j = 0; j < buffer_update_command->buffer_copies_count; j++) { + driver->command_copy_buffer(p_command_buffer, command_buffer_copies[j].source, buffer_update_command->destination, command_buffer_copies[j].region); + } + } break; + case RecordedCommand::TYPE_COMPUTE_LIST: { + const RecordedComputeListCommand *compute_list_command = reinterpret_cast<const RecordedComputeListCommand *>(command); + _run_compute_list_command(p_command_buffer, compute_list_command->instruction_data(), compute_list_command->instruction_data_size); + } break; + case RecordedCommand::TYPE_DRAW_LIST: { + const RecordedDrawListCommand *draw_list_command = reinterpret_cast<const RecordedDrawListCommand *>(command); + const VectorView clear_values(draw_list_command->clear_values(), draw_list_command->clear_values_count); + driver->command_begin_render_pass(p_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values); + _run_draw_list_command(p_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size); + driver->command_end_render_pass(p_command_buffer); + } break; + case RecordedCommand::TYPE_TEXTURE_CLEAR: { + const RecordedTextureClearCommand *texture_clear_command = reinterpret_cast<const RecordedTextureClearCommand *>(command); + driver->command_clear_color_texture(p_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range); + } break; + case RecordedCommand::TYPE_TEXTURE_COPY: { + const RecordedTextureCopyCommand *texture_copy_command = reinterpret_cast<const RecordedTextureCopyCommand *>(command); + driver->command_copy_texture(p_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_copy_command->region); + } break; + case RecordedCommand::TYPE_TEXTURE_GET_DATA: { + const RecordedTextureGetDataCommand *texture_get_data_command = reinterpret_cast<const RecordedTextureGetDataCommand *>(command); + const VectorView<RDD::BufferTextureCopyRegion> command_buffer_texture_copy_regions_view(texture_get_data_command->buffer_texture_copy_regions(), texture_get_data_command->buffer_texture_copy_regions_count); + driver->command_copy_texture_to_buffer(p_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view); + } break; + case RecordedCommand::TYPE_TEXTURE_RESOLVE: { + const RecordedTextureResolveCommand *texture_resolve_command = reinterpret_cast<const RecordedTextureResolveCommand *>(command); + driver->command_resolve_texture(p_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap); + } break; + case RecordedCommand::TYPE_TEXTURE_UPDATE: { + const RecordedTextureUpdateCommand *texture_update_command = reinterpret_cast<const RecordedTextureUpdateCommand *>(command); + const RecordedBufferToTextureCopy *command_buffer_to_texture_copies = texture_update_command->buffer_to_texture_copies(); + for (uint32_t j = 0; j < texture_update_command->buffer_to_texture_copies_count; j++) { + driver->command_copy_buffer_to_texture(p_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, command_buffer_to_texture_copies[j].region); + } + } break; + case RecordedCommand::TYPE_CAPTURE_TIMESTAMP: { + const RecordedCaptureTimestampCommand *texture_capture_timestamp_command = reinterpret_cast<const RecordedCaptureTimestampCommand *>(command); + driver->command_timestamp_write(p_command_buffer, texture_capture_timestamp_command->pool, texture_capture_timestamp_command->index); + } break; + default: { + DEV_ASSERT(false && "Unknown recorded command type."); + return; + } + } + } +} + +void RenderingDeviceGraph::_run_label_command_change(RDD::CommandBufferID p_command_buffer, int32_t p_new_label_index, int32_t p_new_level, bool p_ignore_previous_value, bool p_use_label_for_empty, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level) { + if (command_label_count == 0) { + // Ignore any label operations if no labels were pushed. + return; + } + + if (p_ignore_previous_value || p_new_label_index != r_current_label_index || p_new_level != r_current_label_level) { + if (!p_ignore_previous_value && (p_use_label_for_empty || r_current_label_index >= 0)) { + // End the current label. + driver->command_end_label(p_command_buffer); + } + + String label_name; + Color label_color; + if (p_new_label_index >= 0) { + const char *label_chars = &command_label_chars[command_label_offsets[p_new_label_index]]; + label_name.parse_utf8(label_chars); + label_color = command_label_colors[p_new_label_index]; + } else if (p_use_label_for_empty) { + label_name = "Command graph"; + label_color = Color(1, 1, 1, 1); + } + + // Add the level to the name. + label_name += " (L" + itos(p_new_level) + ")"; + + if (p_sorted_commands != nullptr && p_sorted_commands_count > 0) { + // Analyze the commands in the level that have the same label to detect what type of operations are performed. + bool copy_commands = false; + bool compute_commands = false; + bool draw_commands = false; + for (uint32_t i = 0; i < p_sorted_commands_count; i++) { + const uint32_t command_index = p_sorted_commands[i].index; + const uint32_t command_data_offset = command_data_offsets[command_index]; + const RecordedCommand *command = reinterpret_cast<RecordedCommand *>(&command_data[command_data_offset]); + if (command->label_index != p_new_label_index) { + break; + } + + switch (command->type) { + case RecordedCommand::TYPE_BUFFER_CLEAR: + case RecordedCommand::TYPE_BUFFER_COPY: + case RecordedCommand::TYPE_BUFFER_GET_DATA: + case RecordedCommand::TYPE_BUFFER_UPDATE: + case RecordedCommand::TYPE_TEXTURE_CLEAR: + case RecordedCommand::TYPE_TEXTURE_COPY: + case RecordedCommand::TYPE_TEXTURE_GET_DATA: + case RecordedCommand::TYPE_TEXTURE_RESOLVE: + case RecordedCommand::TYPE_TEXTURE_UPDATE: { + copy_commands = true; + } break; + case RecordedCommand::TYPE_COMPUTE_LIST: { + compute_commands = true; + } break; + case RecordedCommand::TYPE_DRAW_LIST: { + draw_commands = true; + } break; + default: { + // Ignore command. + } break; + } + + if (copy_commands && compute_commands && draw_commands) { + // There's no more command types to find. + break; + } + } + + if (copy_commands || compute_commands || draw_commands) { + // Add the operations to the name. + bool plus_after_copy = copy_commands && (compute_commands || draw_commands); + bool plus_after_compute = compute_commands && draw_commands; + label_name += " ("; + label_name += copy_commands ? "Copy" : ""; + label_name += plus_after_copy ? "+" : ""; + label_name += compute_commands ? "Compute" : ""; + label_name += plus_after_compute ? "+" : ""; + label_name += draw_commands ? "Draw" : ""; + label_name += ")"; + } + } + + // Start the new label. + CharString label_name_utf8 = label_name.utf8(); + driver->command_begin_label(p_command_buffer, label_name_utf8.get_data(), label_color); + + r_current_label_index = p_new_label_index; + r_current_label_level = p_new_level; + } +} + +void RenderingDeviceGraph::_boost_priority_for_render_commands(RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, uint32_t &r_boosted_priority) { + if (p_sorted_commands_count == 0) { + return; + } + + const uint32_t boosted_priority_value = 0; + if (r_boosted_priority > 0) { + bool perform_sort = false; + for (uint32_t j = 0; j < p_sorted_commands_count; j++) { + if (p_sorted_commands[j].priority == r_boosted_priority) { + p_sorted_commands[j].priority = boosted_priority_value; + perform_sort = true; + } + } + + if (perform_sort) { + SortArray<RecordedCommandSort> command_sorter; + command_sorter.sort(p_sorted_commands, p_sorted_commands_count); + } + } + + if (p_sorted_commands[p_sorted_commands_count - 1].priority != boosted_priority_value) { + r_boosted_priority = p_sorted_commands[p_sorted_commands_count - 1].priority; + } +} + +void RenderingDeviceGraph::_group_barriers_for_render_commands(RDD::CommandBufferID p_command_buffer, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, bool p_full_memory_barrier) { + if (!driver_honors_barriers) { + return; + } + + barrier_group.clear(); + barrier_group.src_stages = RDD::PIPELINE_STAGE_TOP_OF_PIPE_BIT; + barrier_group.dst_stages = RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + + for (uint32_t i = 0; i < p_sorted_commands_count; i++) { + const uint32_t command_index = p_sorted_commands[i].index; + const uint32_t command_data_offset = command_data_offsets[command_index]; + const RecordedCommand *command = reinterpret_cast<RecordedCommand *>(&command_data[command_data_offset]); + + // Merge command's stage bits with the barrier group. + barrier_group.src_stages = barrier_group.src_stages | command->src_stages; + barrier_group.dst_stages = barrier_group.dst_stages | command->dst_stages; + + // Merge command's memory barrier bits with the barrier group. + barrier_group.memory_barrier.src_access = barrier_group.memory_barrier.src_access | command->memory_barrier.src_access; + barrier_group.memory_barrier.dst_access = barrier_group.memory_barrier.dst_access | command->memory_barrier.dst_access; + + // Gather texture barriers. + for (int32_t j = 0; j < command->normalization_barrier_count; j++) { + const RDD::TextureBarrier &recorded_barrier = command_normalization_barriers[command->normalization_barrier_index + j]; + barrier_group.normalization_barriers.push_back(recorded_barrier); + } + + for (int32_t j = 0; j < command->transition_barrier_count; j++) { + const RDD::TextureBarrier &recorded_barrier = command_transition_barriers[command->transition_barrier_index + j]; + barrier_group.transition_barriers.push_back(recorded_barrier); + } + +#if USE_BUFFER_BARRIERS + // Gather buffer barriers. + for (int32_t j = 0; j < command->buffer_barrier_count; j++) { + const RDD::BufferBarrier &recorded_barrier = command_buffer_barriers[command->buffer_barrier_index + j]; + barrier_group.buffer_barriers.push_back(recorded_barrier); + } +#endif + } + + if (p_full_memory_barrier) { + barrier_group.src_stages = RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT; + barrier_group.dst_stages = RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT; + barrier_group.memory_barrier.src_access = RDD::BARRIER_ACCESS_MEMORY_READ_BIT | RDD::BARRIER_ACCESS_MEMORY_WRITE_BIT; + barrier_group.memory_barrier.dst_access = RDD::BARRIER_ACCESS_MEMORY_READ_BIT | RDD::BARRIER_ACCESS_MEMORY_WRITE_BIT; + } + + const bool is_memory_barrier_empty = barrier_group.memory_barrier.src_access.is_empty() && barrier_group.memory_barrier.dst_access.is_empty(); + const bool are_texture_barriers_empty = barrier_group.normalization_barriers.is_empty() && barrier_group.transition_barriers.is_empty(); +#if USE_BUFFER_BARRIERS + const bool are_buffer_barriers_empty = barrier_group.buffer_barriers.is_empty(); +#else + const bool are_buffer_barriers_empty = true; +#endif + if (is_memory_barrier_empty && are_texture_barriers_empty && are_buffer_barriers_empty) { + // Commands don't require synchronization. + return; + } + + const VectorView<RDD::MemoryBarrier> memory_barriers = !is_memory_barrier_empty ? barrier_group.memory_barrier : VectorView<RDD::MemoryBarrier>(); + const VectorView<RDD::TextureBarrier> texture_barriers = barrier_group.normalization_barriers.is_empty() ? barrier_group.transition_barriers : barrier_group.normalization_barriers; +#if USE_BUFFER_BARRIERS + const VectorView<RDD::BufferBarrier> buffer_barriers = !are_buffer_barriers_empty ? barrier_group.buffer_barriers : VectorView<RDD::BufferBarrier>(); +#else + const VectorView<RDD::BufferBarrier> buffer_barriers = VectorView<RDD::BufferBarrier>(); +#endif + + driver->command_pipeline_barrier(p_command_buffer, barrier_group.src_stages, barrier_group.dst_stages, memory_barriers, buffer_barriers, texture_barriers); + + bool separate_texture_barriers = !barrier_group.normalization_barriers.is_empty() && !barrier_group.transition_barriers.is_empty(); + if (separate_texture_barriers) { + driver->command_pipeline_barrier(p_command_buffer, barrier_group.src_stages, barrier_group.dst_stages, VectorView<RDD::MemoryBarrier>(), VectorView<RDD::BufferBarrier>(), barrier_group.transition_barriers); + } +} + +void RenderingDeviceGraph::_print_render_commands(const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count) { + for (uint32_t i = 0; i < p_sorted_commands_count; i++) { + const uint32_t command_index = p_sorted_commands[i].index; + const uint32_t command_level = p_sorted_commands[i].level; + const uint32_t command_data_offset = command_data_offsets[command_index]; + const RecordedCommand *command = reinterpret_cast<RecordedCommand *>(&command_data[command_data_offset]); + switch (command->type) { + case RecordedCommand::TYPE_BUFFER_CLEAR: { + const RecordedBufferClearCommand *buffer_clear_command = reinterpret_cast<const RecordedBufferClearCommand *>(command); + print_line(command_index, "LEVEL", command_level, "BUFFER CLEAR DESTINATION", itos(buffer_clear_command->buffer.id)); + } break; + case RecordedCommand::TYPE_BUFFER_COPY: { + const RecordedBufferCopyCommand *buffer_copy_command = reinterpret_cast<const RecordedBufferCopyCommand *>(command); + print_line(command_index, "LEVEL", command_level, "BUFFER COPY SOURCE", itos(buffer_copy_command->source.id), "DESTINATION", itos(buffer_copy_command->destination.id)); + } break; + case RecordedCommand::TYPE_BUFFER_GET_DATA: { + const RecordedBufferGetDataCommand *buffer_get_data_command = reinterpret_cast<const RecordedBufferGetDataCommand *>(command); + print_line(command_index, "LEVEL", command_level, "BUFFER GET DATA DESTINATION", itos(buffer_get_data_command->destination.id)); + } break; + case RecordedCommand::TYPE_BUFFER_UPDATE: { + const RecordedBufferUpdateCommand *buffer_update_command = reinterpret_cast<const RecordedBufferUpdateCommand *>(command); + print_line(command_index, "LEVEL", command_level, "BUFFER UPDATE DESTINATION", itos(buffer_update_command->destination.id), "COPIES", buffer_update_command->buffer_copies_count); + } break; + case RecordedCommand::TYPE_COMPUTE_LIST: { + const RecordedComputeListCommand *compute_list_command = reinterpret_cast<const RecordedComputeListCommand *>(command); + print_line(command_index, "LEVEL", command_level, "COMPUTE LIST SIZE", compute_list_command->instruction_data_size); + } break; + case RecordedCommand::TYPE_DRAW_LIST: { + const RecordedDrawListCommand *draw_list_command = reinterpret_cast<const RecordedDrawListCommand *>(command); + print_line(command_index, "LEVEL", command_level, "DRAW LIST SIZE", draw_list_command->instruction_data_size); + } break; + case RecordedCommand::TYPE_TEXTURE_CLEAR: { + const RecordedTextureClearCommand *texture_clear_command = reinterpret_cast<const RecordedTextureClearCommand *>(command); + print_line(command_index, "LEVEL", command_level, "TEXTURE CLEAR", itos(texture_clear_command->texture.id), "COLOR", texture_clear_command->color); + } break; + case RecordedCommand::TYPE_TEXTURE_COPY: { + const RecordedTextureCopyCommand *texture_copy_command = reinterpret_cast<const RecordedTextureCopyCommand *>(command); + print_line(command_index, "LEVEL", command_level, "TEXTURE COPY FROM", itos(texture_copy_command->from_texture.id), "TO", itos(texture_copy_command->to_texture.id)); + } break; + case RecordedCommand::TYPE_TEXTURE_GET_DATA: { + print_line(command_index, "LEVEL", command_level, "TEXTURE GET DATA"); + } break; + case RecordedCommand::TYPE_TEXTURE_RESOLVE: { + const RecordedTextureResolveCommand *texture_resolve_command = reinterpret_cast<const RecordedTextureResolveCommand *>(command); + print_line(command_index, "LEVEL", command_level, "TEXTURE RESOLVE FROM", itos(texture_resolve_command->from_texture.id), "TO", itos(texture_resolve_command->to_texture.id)); + } break; + case RecordedCommand::TYPE_TEXTURE_UPDATE: { + const RecordedTextureUpdateCommand *texture_update_command = reinterpret_cast<const RecordedTextureUpdateCommand *>(command); + print_line(command_index, "LEVEL", command_level, "TEXTURE UPDATE TO", itos(texture_update_command->to_texture.id)); + } break; + case RecordedCommand::TYPE_CAPTURE_TIMESTAMP: { + const RecordedCaptureTimestampCommand *texture_capture_timestamp_command = reinterpret_cast<const RecordedCaptureTimestampCommand *>(command); + print_line(command_index, "LEVEL", command_level, "CAPTURE TIMESTAMP POOL", itos(texture_capture_timestamp_command->pool.id), "INDEX", texture_capture_timestamp_command->index); + } break; + default: + DEV_ASSERT(false && "Unknown recorded command type."); + return; + } + } +} + +void RenderingDeviceGraph::_print_draw_list(const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) { + uint32_t instruction_data_cursor = 0; + while (instruction_data_cursor < p_instruction_data_size) { + DEV_ASSERT((instruction_data_cursor + sizeof(DrawListInstruction)) <= p_instruction_data_size); + + const DrawListInstruction *instruction = reinterpret_cast<const DrawListInstruction *>(&p_instruction_data[instruction_data_cursor]); + switch (instruction->type) { + case DrawListInstruction::TYPE_BIND_INDEX_BUFFER: { + const DrawListBindIndexBufferInstruction *bind_index_buffer_instruction = reinterpret_cast<const DrawListBindIndexBufferInstruction *>(instruction); + print_line("\tBIND INDEX BUFFER ID", itos(bind_index_buffer_instruction->buffer.id), "FORMAT", bind_index_buffer_instruction->format, "OFFSET", bind_index_buffer_instruction->offset); + instruction_data_cursor += sizeof(DrawListBindIndexBufferInstruction); + } break; + case DrawListInstruction::TYPE_BIND_PIPELINE: { + const DrawListBindPipelineInstruction *bind_pipeline_instruction = reinterpret_cast<const DrawListBindPipelineInstruction *>(instruction); + print_line("\tBIND PIPELINE ID", itos(bind_pipeline_instruction->pipeline.id)); + instruction_data_cursor += sizeof(DrawListBindPipelineInstruction); + } break; + case DrawListInstruction::TYPE_BIND_UNIFORM_SET: { + const DrawListBindUniformSetInstruction *bind_uniform_set_instruction = reinterpret_cast<const DrawListBindUniformSetInstruction *>(instruction); + print_line("\tBIND UNIFORM SET ID", itos(bind_uniform_set_instruction->uniform_set.id), "SET INDEX", bind_uniform_set_instruction->set_index); + instruction_data_cursor += sizeof(DrawListBindUniformSetInstruction); + } break; + case DrawListInstruction::TYPE_BIND_VERTEX_BUFFERS: { + const DrawListBindVertexBuffersInstruction *bind_vertex_buffers_instruction = reinterpret_cast<const DrawListBindVertexBuffersInstruction *>(instruction); + print_line("\tBIND VERTEX BUFFERS COUNT", bind_vertex_buffers_instruction->vertex_buffers_count); + instruction_data_cursor += sizeof(DrawListBindVertexBuffersInstruction); + instruction_data_cursor += sizeof(RDD::BufferID) * bind_vertex_buffers_instruction->vertex_buffers_count; + instruction_data_cursor += sizeof(uint64_t) * bind_vertex_buffers_instruction->vertex_buffers_count; + } break; + case DrawListInstruction::TYPE_CLEAR_ATTACHMENTS: { + const DrawListClearAttachmentsInstruction *clear_attachments_instruction = reinterpret_cast<const DrawListClearAttachmentsInstruction *>(instruction); + print_line("\tATTACHMENTS CLEAR COUNT", clear_attachments_instruction->attachments_clear_count, "RECT COUNT", clear_attachments_instruction->attachments_clear_rect_count); + instruction_data_cursor += sizeof(DrawListClearAttachmentsInstruction); + instruction_data_cursor += sizeof(RDD::AttachmentClear) * clear_attachments_instruction->attachments_clear_count; + instruction_data_cursor += sizeof(Rect2i) * clear_attachments_instruction->attachments_clear_rect_count; + } break; + case DrawListInstruction::TYPE_DRAW: { + const DrawListDrawInstruction *draw_instruction = reinterpret_cast<const DrawListDrawInstruction *>(instruction); + print_line("\tDRAW VERTICES", draw_instruction->vertex_count, "INSTANCES", draw_instruction->instance_count); + instruction_data_cursor += sizeof(DrawListDrawInstruction); + } break; + case DrawListInstruction::TYPE_DRAW_INDEXED: { + const DrawListDrawIndexedInstruction *draw_indexed_instruction = reinterpret_cast<const DrawListDrawIndexedInstruction *>(instruction); + print_line("\tDRAW INDICES", draw_indexed_instruction->index_count, "INSTANCES", draw_indexed_instruction->instance_count, "FIRST INDEX", draw_indexed_instruction->first_index); + instruction_data_cursor += sizeof(DrawListDrawIndexedInstruction); + } break; + case DrawListInstruction::TYPE_EXECUTE_COMMANDS: { + print_line("\tEXECUTE COMMANDS"); + instruction_data_cursor += sizeof(DrawListExecuteCommandsInstruction); + } break; + case DrawListInstruction::TYPE_NEXT_SUBPASS: { + print_line("\tNEXT SUBPASS"); + instruction_data_cursor += sizeof(DrawListNextSubpassInstruction); + } break; + case DrawListInstruction::TYPE_SET_BLEND_CONSTANTS: { + const DrawListSetBlendConstantsInstruction *set_blend_constants_instruction = reinterpret_cast<const DrawListSetBlendConstantsInstruction *>(instruction); + print_line("\tSET BLEND CONSTANTS COLOR", set_blend_constants_instruction->color); + instruction_data_cursor += sizeof(DrawListSetBlendConstantsInstruction); + } break; + case DrawListInstruction::TYPE_SET_LINE_WIDTH: { + const DrawListSetLineWidthInstruction *set_line_width_instruction = reinterpret_cast<const DrawListSetLineWidthInstruction *>(instruction); + print_line("\tSET LINE WIDTH", set_line_width_instruction->width); + instruction_data_cursor += sizeof(DrawListSetLineWidthInstruction); + } break; + case DrawListInstruction::TYPE_SET_PUSH_CONSTANT: { + const DrawListSetPushConstantInstruction *set_push_constant_instruction = reinterpret_cast<const DrawListSetPushConstantInstruction *>(instruction); + print_line("\tSET PUSH CONSTANT SIZE", set_push_constant_instruction->size); + instruction_data_cursor += sizeof(DrawListSetPushConstantInstruction); + instruction_data_cursor += set_push_constant_instruction->size; + } break; + case DrawListInstruction::TYPE_SET_SCISSOR: { + const DrawListSetScissorInstruction *set_scissor_instruction = reinterpret_cast<const DrawListSetScissorInstruction *>(instruction); + print_line("\tSET SCISSOR", set_scissor_instruction->rect); + instruction_data_cursor += sizeof(DrawListSetScissorInstruction); + } break; + case DrawListInstruction::TYPE_SET_VIEWPORT: { + const DrawListSetViewportInstruction *set_viewport_instruction = reinterpret_cast<const DrawListSetViewportInstruction *>(instruction); + print_line("\tSET VIEWPORT", set_viewport_instruction->rect); + instruction_data_cursor += sizeof(DrawListSetViewportInstruction); + } break; + case DrawListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE: { + const DrawListUniformSetPrepareForUseInstruction *uniform_set_prepare_for_use_instruction = reinterpret_cast<const DrawListUniformSetPrepareForUseInstruction *>(instruction); + print_line("\tUNIFORM SET PREPARE FOR USE ID", itos(uniform_set_prepare_for_use_instruction->uniform_set.id), "SHADER ID", itos(uniform_set_prepare_for_use_instruction->shader.id), "INDEX", uniform_set_prepare_for_use_instruction->set_index); + instruction_data_cursor += sizeof(DrawListUniformSetPrepareForUseInstruction); + } break; + default: + DEV_ASSERT(false && "Unknown draw list instruction type."); + return; + } + } +} + +void RenderingDeviceGraph::_print_compute_list(const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) { + uint32_t instruction_data_cursor = 0; + while (instruction_data_cursor < p_instruction_data_size) { + DEV_ASSERT((instruction_data_cursor + sizeof(ComputeListInstruction)) <= p_instruction_data_size); + + const ComputeListInstruction *instruction = reinterpret_cast<const ComputeListInstruction *>(&p_instruction_data[instruction_data_cursor]); + switch (instruction->type) { + case ComputeListInstruction::TYPE_BIND_PIPELINE: { + const ComputeListBindPipelineInstruction *bind_pipeline_instruction = reinterpret_cast<const ComputeListBindPipelineInstruction *>(instruction); + print_line("\tBIND PIPELINE ID", itos(bind_pipeline_instruction->pipeline.id)); + instruction_data_cursor += sizeof(ComputeListBindPipelineInstruction); + } break; + case ComputeListInstruction::TYPE_BIND_UNIFORM_SET: { + const ComputeListBindUniformSetInstruction *bind_uniform_set_instruction = reinterpret_cast<const ComputeListBindUniformSetInstruction *>(instruction); + print_line("\tBIND UNIFORM SET ID", itos(bind_uniform_set_instruction->uniform_set.id), "SHADER ID", itos(bind_uniform_set_instruction->shader.id)); + instruction_data_cursor += sizeof(ComputeListBindUniformSetInstruction); + } break; + case ComputeListInstruction::TYPE_DISPATCH: { + const ComputeListDispatchInstruction *dispatch_instruction = reinterpret_cast<const ComputeListDispatchInstruction *>(instruction); + print_line("\tDISPATCH", dispatch_instruction->x_groups, dispatch_instruction->y_groups, dispatch_instruction->z_groups); + instruction_data_cursor += sizeof(ComputeListDispatchInstruction); + } break; + case ComputeListInstruction::TYPE_DISPATCH_INDIRECT: { + const ComputeListDispatchIndirectInstruction *dispatch_indirect_instruction = reinterpret_cast<const ComputeListDispatchIndirectInstruction *>(instruction); + print_line("\tDISPATCH INDIRECT BUFFER ID", itos(dispatch_indirect_instruction->buffer.id), "OFFSET", dispatch_indirect_instruction->offset); + instruction_data_cursor += sizeof(ComputeListDispatchIndirectInstruction); + } break; + case ComputeListInstruction::TYPE_SET_PUSH_CONSTANT: { + const ComputeListSetPushConstantInstruction *set_push_constant_instruction = reinterpret_cast<const ComputeListSetPushConstantInstruction *>(instruction); + print_line("\tSET PUSH CONSTANT SIZE", set_push_constant_instruction->size); + instruction_data_cursor += sizeof(ComputeListSetPushConstantInstruction); + instruction_data_cursor += set_push_constant_instruction->size; + } break; + case ComputeListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE: { + const ComputeListUniformSetPrepareForUseInstruction *uniform_set_prepare_for_use_instruction = reinterpret_cast<const ComputeListUniformSetPrepareForUseInstruction *>(instruction); + print_line("\tUNIFORM SET PREPARE FOR USE ID", itos(uniform_set_prepare_for_use_instruction->uniform_set.id), "SHADER ID", itos(uniform_set_prepare_for_use_instruction->shader.id), "INDEX", itos(uniform_set_prepare_for_use_instruction->set_index)); + instruction_data_cursor += sizeof(ComputeListUniformSetPrepareForUseInstruction); + } break; + default: + DEV_ASSERT(false && "Unknown compute list instruction type."); + return; + } + } +} + +void RenderingDeviceGraph::initialize(RDD *p_driver, uint32_t p_frame_count, uint32_t p_secondary_command_buffers_per_frame) { + driver = p_driver; + frames.resize(p_frame_count); + + for (uint32_t i = 0; i < p_frame_count; i++) { + frames[i].secondary_command_buffers.resize(p_secondary_command_buffers_per_frame); + + for (uint32_t j = 0; j < p_secondary_command_buffers_per_frame; j++) { + SecondaryCommandBuffer &secondary = frames[i].secondary_command_buffers[j]; + secondary.command_pool = driver->command_pool_create(RDD::COMMAND_BUFFER_TYPE_SECONDARY); + secondary.command_buffer = driver->command_buffer_create(RDD::COMMAND_BUFFER_TYPE_SECONDARY, secondary.command_pool); + secondary.task = WorkerThreadPool::INVALID_TASK_ID; + } + } + + driver_honors_barriers = driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS); +} + +void RenderingDeviceGraph::begin() { + command_data.clear(); + command_data_offsets.clear(); + command_normalization_barriers.clear(); + command_transition_barriers.clear(); + command_label_chars.clear(); + command_label_colors.clear(); + command_label_offsets.clear(); + command_list_nodes.clear(); + write_list_nodes.clear(); + command_count = 0; + command_label_count = 0; + command_timestamp_index = -1; + command_synchronization_index = -1; + command_synchronization_pending = false; + command_label_index = -1; + frames[frame].secondary_command_buffers_used = 0; + draw_instruction_list.index = 0; + compute_instruction_list.index = 0; + tracking_frame++; + +#ifdef DEV_ENABLED + write_dependency_counters.clear(); +#endif +} + +void RenderingDeviceGraph::add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size) { + DEV_ASSERT(p_dst_tracker != nullptr); + + int32_t command_index; + RecordedBufferClearCommand *command = static_cast<RecordedBufferClearCommand *>(_allocate_command(sizeof(RecordedBufferClearCommand), command_index)); + command->type = RecordedCommand::TYPE_BUFFER_CLEAR; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->buffer = p_dst; + command->offset = p_offset; + command->size = p_size; + + ResourceUsage usage = RESOURCE_USAGE_TRANSFER_TO; + _add_command_to_graph(&p_dst_tracker, &usage, 1, command_index, command); +} + +void RenderingDeviceGraph::add_buffer_copy(RDD::BufferID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, RDD::BufferCopyRegion p_region) { + // Source tracker is allowed to be null as it could be a read-only buffer. + DEV_ASSERT(p_dst_tracker != nullptr); + + int32_t command_index; + RecordedBufferCopyCommand *command = static_cast<RecordedBufferCopyCommand *>(_allocate_command(sizeof(RecordedBufferCopyCommand), command_index)); + command->type = RecordedCommand::TYPE_BUFFER_COPY; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->source = p_src; + command->destination = p_dst; + command->region = p_region; + + ResourceTracker *trackers[2] = { p_dst_tracker, p_src_tracker }; + ResourceUsage usages[2] = { RESOURCE_USAGE_TRANSFER_TO, RESOURCE_USAGE_TRANSFER_FROM }; + _add_command_to_graph(trackers, usages, p_src_tracker != nullptr ? 2 : 1, command_index, command); +} + +void RenderingDeviceGraph::add_buffer_get_data(RDD::BufferID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, RDD::BufferCopyRegion p_region) { + // Source tracker is allowed to be null as it could be a read-only buffer. + int32_t command_index; + RecordedBufferGetDataCommand *command = static_cast<RecordedBufferGetDataCommand *>(_allocate_command(sizeof(RecordedBufferGetDataCommand), command_index)); + command->type = RecordedCommand::TYPE_BUFFER_GET_DATA; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->source = p_src; + command->destination = p_dst; + command->region = p_region; + + if (p_src_tracker != nullptr) { + ResourceUsage usage = RESOURCE_USAGE_TRANSFER_FROM; + _add_command_to_graph(&p_src_tracker, &usage, 1, command_index, command); + } else { + _add_command_to_graph(nullptr, nullptr, 0, command_index, command); + } +} + +void RenderingDeviceGraph::add_buffer_update(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, VectorView<RecordedBufferCopy> p_buffer_copies) { + DEV_ASSERT(p_dst_tracker != nullptr); + + size_t buffer_copies_size = p_buffer_copies.size() * sizeof(RecordedBufferCopy); + uint64_t command_size = sizeof(RecordedBufferUpdateCommand) + buffer_copies_size; + int32_t command_index; + RecordedBufferUpdateCommand *command = static_cast<RecordedBufferUpdateCommand *>(_allocate_command(command_size, command_index)); + command->type = RecordedCommand::TYPE_BUFFER_UPDATE; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->destination = p_dst; + command->buffer_copies_count = p_buffer_copies.size(); + + RecordedBufferCopy *buffer_copies = command->buffer_copies(); + for (uint32_t i = 0; i < command->buffer_copies_count; i++) { + buffer_copies[i] = p_buffer_copies[i]; + } + + ResourceUsage buffer_usage = RESOURCE_USAGE_TRANSFER_TO; + _add_command_to_graph(&p_dst_tracker, &buffer_usage, 1, command_index, command); +} + +void RenderingDeviceGraph::add_compute_list_begin() { + compute_instruction_list.clear(); + compute_instruction_list.index++; +} + +void RenderingDeviceGraph::add_compute_list_bind_pipeline(RDD::PipelineID p_pipeline) { + ComputeListBindPipelineInstruction *instruction = reinterpret_cast<ComputeListBindPipelineInstruction *>(_allocate_compute_list_instruction(sizeof(ComputeListBindPipelineInstruction))); + instruction->type = ComputeListInstruction::TYPE_BIND_PIPELINE; + instruction->pipeline = p_pipeline; + compute_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT); +} + +void RenderingDeviceGraph::add_compute_list_bind_uniform_set(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index) { + ComputeListBindUniformSetInstruction *instruction = reinterpret_cast<ComputeListBindUniformSetInstruction *>(_allocate_compute_list_instruction(sizeof(ComputeListBindUniformSetInstruction))); + instruction->type = ComputeListInstruction::TYPE_BIND_UNIFORM_SET; + instruction->shader = p_shader; + instruction->uniform_set = p_uniform_set; + instruction->set_index = set_index; +} + +void RenderingDeviceGraph::add_compute_list_dispatch(uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) { + ComputeListDispatchInstruction *instruction = reinterpret_cast<ComputeListDispatchInstruction *>(_allocate_compute_list_instruction(sizeof(ComputeListDispatchInstruction))); + instruction->type = ComputeListInstruction::TYPE_DISPATCH; + instruction->x_groups = p_x_groups; + instruction->y_groups = p_y_groups; + instruction->z_groups = p_z_groups; +} + +void RenderingDeviceGraph::add_compute_list_dispatch_indirect(RDD::BufferID p_buffer, uint32_t p_offset) { + ComputeListDispatchIndirectInstruction *instruction = reinterpret_cast<ComputeListDispatchIndirectInstruction *>(_allocate_compute_list_instruction(sizeof(ComputeListDispatchIndirectInstruction))); + instruction->type = ComputeListInstruction::TYPE_DISPATCH_INDIRECT; + instruction->buffer = p_buffer; + instruction->offset = p_offset; + compute_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); +} + +void RenderingDeviceGraph::add_compute_list_set_push_constant(RDD::ShaderID p_shader, const void *p_data, uint32_t p_data_size) { + uint32_t instruction_size = sizeof(ComputeListSetPushConstantInstruction) + p_data_size; + ComputeListSetPushConstantInstruction *instruction = reinterpret_cast<ComputeListSetPushConstantInstruction *>(_allocate_compute_list_instruction(instruction_size)); + instruction->type = ComputeListInstruction::TYPE_SET_PUSH_CONSTANT; + instruction->size = p_data_size; + instruction->shader = p_shader; + memcpy(instruction->data(), p_data, p_data_size); +} + +void RenderingDeviceGraph::add_compute_list_uniform_set_prepare_for_use(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index) { + ComputeListUniformSetPrepareForUseInstruction *instruction = reinterpret_cast<ComputeListUniformSetPrepareForUseInstruction *>(_allocate_compute_list_instruction(sizeof(ComputeListUniformSetPrepareForUseInstruction))); + instruction->type = ComputeListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE; + instruction->shader = p_shader; + instruction->uniform_set = p_uniform_set; + instruction->set_index = set_index; +} + +void RenderingDeviceGraph::add_compute_list_usage(ResourceTracker *p_tracker, ResourceUsage p_usage) { + DEV_ASSERT(p_tracker != nullptr); + + p_tracker->reset_if_outdated(tracking_frame); + + if (p_tracker->compute_list_index != compute_instruction_list.index) { + compute_instruction_list.command_trackers.push_back(p_tracker); + compute_instruction_list.command_tracker_usages.push_back(p_usage); + p_tracker->compute_list_index = compute_instruction_list.index; + } +} + +void RenderingDeviceGraph::add_compute_list_usages(VectorView<ResourceTracker *> p_trackers, VectorView<ResourceUsage> p_usages) { + DEV_ASSERT(p_trackers.size() == p_usages.size()); + + for (uint32_t i = 0; i < p_trackers.size(); i++) { + add_compute_list_usage(p_trackers[i], p_usages[i]); + } +} + +void RenderingDeviceGraph::add_compute_list_end() { + int32_t command_index; + uint32_t instruction_data_size = compute_instruction_list.data.size(); + uint32_t command_size = sizeof(RecordedComputeListCommand) + instruction_data_size; + RecordedComputeListCommand *command = static_cast<RecordedComputeListCommand *>(_allocate_command(command_size, command_index)); + command->type = RecordedCommand::TYPE_COMPUTE_LIST; + command->dst_stages = compute_instruction_list.stages; + command->instruction_data_size = instruction_data_size; + memcpy(command->instruction_data(), compute_instruction_list.data.ptr(), instruction_data_size); + _add_command_to_graph(compute_instruction_list.command_trackers.ptr(), compute_instruction_list.command_tracker_usages.ptr(), compute_instruction_list.command_trackers.size(), command_index, command); +} + +void RenderingDeviceGraph::add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<RDD::RenderPassClearValue> p_clear_values, bool p_uses_color, bool p_uses_depth) { + draw_instruction_list.clear(); + draw_instruction_list.index++; + draw_instruction_list.render_pass = p_render_pass; + draw_instruction_list.framebuffer = p_framebuffer; + draw_instruction_list.region = p_region; + draw_instruction_list.clear_values.resize(p_clear_values.size()); + for (uint32_t i = 0; i < p_clear_values.size(); i++) { + draw_instruction_list.clear_values[i] = p_clear_values[i]; + } + + if (p_uses_color) { + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + } + + if (p_uses_depth) { + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); + } +} + +void RenderingDeviceGraph::add_draw_list_bind_index_buffer(RDD::BufferID p_buffer, RDD::IndexBufferFormat p_format, uint32_t p_offset) { + DrawListBindIndexBufferInstruction *instruction = reinterpret_cast<DrawListBindIndexBufferInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListBindIndexBufferInstruction))); + instruction->type = DrawListInstruction::TYPE_BIND_INDEX_BUFFER; + instruction->buffer = p_buffer; + instruction->format = p_format; + instruction->offset = p_offset; + + if (instruction->buffer.id != 0) { + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT); + } +} + +void RenderingDeviceGraph::add_draw_list_bind_pipeline(RDD::PipelineID p_pipeline, BitField<RDD::PipelineStageBits> p_pipeline_stage_bits) { + DrawListBindPipelineInstruction *instruction = reinterpret_cast<DrawListBindPipelineInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListBindPipelineInstruction))); + instruction->type = DrawListInstruction::TYPE_BIND_PIPELINE; + instruction->pipeline = p_pipeline; + draw_instruction_list.stages = draw_instruction_list.stages | p_pipeline_stage_bits; +} + +void RenderingDeviceGraph::add_draw_list_bind_uniform_set(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index) { + DrawListBindUniformSetInstruction *instruction = reinterpret_cast<DrawListBindUniformSetInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListBindUniformSetInstruction))); + instruction->type = DrawListInstruction::TYPE_BIND_UNIFORM_SET; + instruction->shader = p_shader; + instruction->uniform_set = p_uniform_set; + instruction->set_index = set_index; +} + +void RenderingDeviceGraph::add_draw_list_bind_vertex_buffers(VectorView<RDD::BufferID> p_vertex_buffers, VectorView<uint64_t> p_vertex_buffer_offsets) { + DEV_ASSERT(p_vertex_buffers.size() == p_vertex_buffer_offsets.size()); + + uint32_t instruction_size = sizeof(DrawListBindVertexBuffersInstruction) + sizeof(RDD::BufferID) * p_vertex_buffers.size() + sizeof(uint64_t) * p_vertex_buffer_offsets.size(); + DrawListBindVertexBuffersInstruction *instruction = reinterpret_cast<DrawListBindVertexBuffersInstruction *>(_allocate_draw_list_instruction(instruction_size)); + instruction->type = DrawListInstruction::TYPE_BIND_VERTEX_BUFFERS; + instruction->vertex_buffers_count = p_vertex_buffers.size(); + + RDD::BufferID *vertex_buffers = instruction->vertex_buffers(); + uint64_t *vertex_buffer_offsets = instruction->vertex_buffer_offsets(); + for (uint32_t i = 0; i < instruction->vertex_buffers_count; i++) { + vertex_buffers[i] = p_vertex_buffers[i]; + vertex_buffer_offsets[i] = p_vertex_buffer_offsets[i]; + } + + if (instruction->vertex_buffers_count > 0) { + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_VERTEX_INPUT_BIT); + } +} + +void RenderingDeviceGraph::add_draw_list_clear_attachments(VectorView<RDD::AttachmentClear> p_attachments_clear, VectorView<Rect2i> p_attachments_clear_rect) { + uint32_t instruction_size = sizeof(DrawListClearAttachmentsInstruction) + sizeof(RDD::AttachmentClear) * p_attachments_clear.size() + sizeof(Rect2i) * p_attachments_clear_rect.size(); + DrawListClearAttachmentsInstruction *instruction = reinterpret_cast<DrawListClearAttachmentsInstruction *>(_allocate_draw_list_instruction(instruction_size)); + instruction->type = DrawListInstruction::TYPE_CLEAR_ATTACHMENTS; + instruction->attachments_clear_count = p_attachments_clear.size(); + instruction->attachments_clear_rect_count = p_attachments_clear_rect.size(); + + RDD::AttachmentClear *attachments_clear = instruction->attachments_clear(); + Rect2i *attachments_clear_rect = instruction->attachments_clear_rect(); + for (uint32_t i = 0; i < instruction->attachments_clear_count; i++) { + attachments_clear[i] = p_attachments_clear[i]; + } + + for (uint32_t i = 0; i < instruction->attachments_clear_rect_count; i++) { + attachments_clear_rect[i] = p_attachments_clear_rect[i]; + } +} + +void RenderingDeviceGraph::add_draw_list_draw(uint32_t p_vertex_count, uint32_t p_instance_count) { + DrawListDrawInstruction *instruction = reinterpret_cast<DrawListDrawInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListDrawInstruction))); + instruction->type = DrawListInstruction::TYPE_DRAW; + instruction->vertex_count = p_vertex_count; + instruction->instance_count = p_instance_count; +} + +void RenderingDeviceGraph::add_draw_list_draw_indexed(uint32_t p_index_count, uint32_t p_instance_count, uint32_t p_first_index) { + DrawListDrawIndexedInstruction *instruction = reinterpret_cast<DrawListDrawIndexedInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListDrawIndexedInstruction))); + instruction->type = DrawListInstruction::TYPE_DRAW_INDEXED; + instruction->index_count = p_index_count; + instruction->instance_count = p_instance_count; + instruction->first_index = p_first_index; +} + +void RenderingDeviceGraph::add_draw_list_execute_commands(RDD::CommandBufferID p_command_buffer) { + DrawListExecuteCommandsInstruction *instruction = reinterpret_cast<DrawListExecuteCommandsInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListExecuteCommandsInstruction))); + instruction->type = DrawListInstruction::TYPE_EXECUTE_COMMANDS; + instruction->command_buffer = p_command_buffer; +} + +void RenderingDeviceGraph::add_draw_list_next_subpass(RDD::CommandBufferType p_command_buffer_type) { + DrawListNextSubpassInstruction *instruction = reinterpret_cast<DrawListNextSubpassInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListNextSubpassInstruction))); + instruction->type = DrawListInstruction::TYPE_NEXT_SUBPASS; + instruction->command_buffer_type = p_command_buffer_type; +} + +void RenderingDeviceGraph::add_draw_list_set_blend_constants(const Color &p_color) { + DrawListSetBlendConstantsInstruction *instruction = reinterpret_cast<DrawListSetBlendConstantsInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListSetBlendConstantsInstruction))); + instruction->type = DrawListInstruction::TYPE_SET_BLEND_CONSTANTS; + instruction->color = p_color; +} + +void RenderingDeviceGraph::add_draw_list_set_line_width(float p_width) { + DrawListSetLineWidthInstruction *instruction = reinterpret_cast<DrawListSetLineWidthInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListSetLineWidthInstruction))); + instruction->type = DrawListInstruction::TYPE_SET_LINE_WIDTH; + instruction->width = p_width; +} + +void RenderingDeviceGraph::add_draw_list_set_push_constant(RDD::ShaderID p_shader, const void *p_data, uint32_t p_data_size) { + uint32_t instruction_size = sizeof(DrawListSetPushConstantInstruction) + p_data_size; + DrawListSetPushConstantInstruction *instruction = reinterpret_cast<DrawListSetPushConstantInstruction *>(_allocate_draw_list_instruction(instruction_size)); + instruction->type = DrawListInstruction::TYPE_SET_PUSH_CONSTANT; + instruction->size = p_data_size; + instruction->shader = p_shader; + memcpy(instruction->data(), p_data, p_data_size); +} + +void RenderingDeviceGraph::add_draw_list_set_scissor(Rect2i p_rect) { + DrawListSetScissorInstruction *instruction = reinterpret_cast<DrawListSetScissorInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListSetScissorInstruction))); + instruction->type = DrawListInstruction::TYPE_SET_SCISSOR; + instruction->rect = p_rect; +} + +void RenderingDeviceGraph::add_draw_list_set_viewport(Rect2i p_rect) { + DrawListSetViewportInstruction *instruction = reinterpret_cast<DrawListSetViewportInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListSetViewportInstruction))); + instruction->type = DrawListInstruction::TYPE_SET_VIEWPORT; + instruction->rect = p_rect; +} + +void RenderingDeviceGraph::add_draw_list_uniform_set_prepare_for_use(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index) { + DrawListUniformSetPrepareForUseInstruction *instruction = reinterpret_cast<DrawListUniformSetPrepareForUseInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListUniformSetPrepareForUseInstruction))); + instruction->type = DrawListInstruction::TYPE_UNIFORM_SET_PREPARE_FOR_USE; + instruction->shader = p_shader; + instruction->uniform_set = p_uniform_set; + instruction->set_index = set_index; +} + +void RenderingDeviceGraph::add_draw_list_usage(ResourceTracker *p_tracker, ResourceUsage p_usage) { + p_tracker->reset_if_outdated(tracking_frame); + + if (p_tracker->draw_list_index != draw_instruction_list.index) { + draw_instruction_list.command_trackers.push_back(p_tracker); + draw_instruction_list.command_tracker_usages.push_back(p_usage); + p_tracker->draw_list_index = draw_instruction_list.index; + } +} + +void RenderingDeviceGraph::add_draw_list_usages(VectorView<ResourceTracker *> p_trackers, VectorView<ResourceUsage> p_usages) { + DEV_ASSERT(p_trackers.size() == p_usages.size()); + + for (uint32_t i = 0; i < p_trackers.size(); i++) { + add_draw_list_usage(p_trackers[i], p_usages[i]); + } +} + +void RenderingDeviceGraph::add_draw_list_end() { + // Arbitrary size threshold to evaluate if it'd be best to record the draw list on the background as a secondary buffer. + const uint32_t instruction_data_threshold_for_secondary = 16384; + RDD::CommandBufferType command_buffer_type; + uint32_t &secondary_buffers_used = frames[frame].secondary_command_buffers_used; + if (draw_instruction_list.data.size() > instruction_data_threshold_for_secondary && secondary_buffers_used < frames[frame].secondary_command_buffers.size()) { + // Copy the current instruction list data into another array that will be used by the secondary command buffer worker. + SecondaryCommandBuffer &secondary = frames[frame].secondary_command_buffers[secondary_buffers_used]; + secondary.render_pass = draw_instruction_list.render_pass; + secondary.framebuffer = draw_instruction_list.framebuffer; + secondary.instruction_data.resize(draw_instruction_list.data.size()); + memcpy(secondary.instruction_data.ptr(), draw_instruction_list.data.ptr(), draw_instruction_list.data.size()); + + // Run a background task for recording the secondary command buffer. + secondary.task = WorkerThreadPool::get_singleton()->add_template_task(this, &RenderingDeviceGraph::_run_secondary_command_buffer_task, &secondary, true); + + // Clear the instruction list and add a single command for executing the secondary command buffer instead. + draw_instruction_list.data.clear(); + add_draw_list_execute_commands(secondary.command_buffer); + secondary_buffers_used++; + + command_buffer_type = RDD::COMMAND_BUFFER_TYPE_SECONDARY; + } else { + command_buffer_type = RDD::COMMAND_BUFFER_TYPE_PRIMARY; + } + + int32_t command_index; + uint32_t clear_values_size = sizeof(RDD::RenderPassClearValue) * draw_instruction_list.clear_values.size(); + uint32_t instruction_data_size = draw_instruction_list.data.size(); + uint32_t command_size = sizeof(RecordedDrawListCommand) + clear_values_size + instruction_data_size; + RecordedDrawListCommand *command = static_cast<RecordedDrawListCommand *>(_allocate_command(command_size, command_index)); + command->type = RecordedCommand::TYPE_DRAW_LIST; + command->dst_stages = draw_instruction_list.stages; + command->instruction_data_size = instruction_data_size; + command->render_pass = draw_instruction_list.render_pass; + command->framebuffer = draw_instruction_list.framebuffer; + command->command_buffer_type = command_buffer_type; + command->region = draw_instruction_list.region; + command->clear_values_count = draw_instruction_list.clear_values.size(); + + RDD::RenderPassClearValue *clear_values = command->clear_values(); + for (uint32_t i = 0; i < command->clear_values_count; i++) { + clear_values[i] = draw_instruction_list.clear_values[i]; + } + + memcpy(command->instruction_data(), draw_instruction_list.data.ptr(), instruction_data_size); + _add_command_to_graph(draw_instruction_list.command_trackers.ptr(), draw_instruction_list.command_tracker_usages.ptr(), draw_instruction_list.command_trackers.size(), command_index, command); +} + +void RenderingDeviceGraph::add_texture_clear(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, const Color &p_color, const RDD::TextureSubresourceRange &p_range) { + DEV_ASSERT(p_dst_tracker != nullptr); + + int32_t command_index; + RecordedTextureClearCommand *command = static_cast<RecordedTextureClearCommand *>(_allocate_command(sizeof(RecordedTextureClearCommand), command_index)); + command->type = RecordedCommand::TYPE_TEXTURE_CLEAR; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->texture = p_dst; + command->color = p_color; + command->range = p_range; + + ResourceUsage usage = RESOURCE_USAGE_TRANSFER_TO; + _add_command_to_graph(&p_dst_tracker, &usage, 1, command_index, command); +} + +void RenderingDeviceGraph::add_texture_copy(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, RDD::TextureCopyRegion p_region) { + DEV_ASSERT(p_src_tracker != nullptr); + DEV_ASSERT(p_dst_tracker != nullptr); + + int32_t command_index; + RecordedTextureCopyCommand *command = static_cast<RecordedTextureCopyCommand *>(_allocate_command(sizeof(RecordedTextureCopyCommand), command_index)); + command->type = RecordedCommand::TYPE_TEXTURE_COPY; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->from_texture = p_src; + command->to_texture = p_dst; + command->region = p_region; + + ResourceTracker *trackers[2] = { p_dst_tracker, p_src_tracker }; + ResourceUsage usages[2] = { RESOURCE_USAGE_TRANSFER_TO, RESOURCE_USAGE_TRANSFER_FROM }; + _add_command_to_graph(trackers, usages, 2, command_index, command); +} + +void RenderingDeviceGraph::add_texture_get_data(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, VectorView<RDD::BufferTextureCopyRegion> p_buffer_texture_copy_regions) { + DEV_ASSERT(p_src_tracker != nullptr); + + int32_t command_index; + uint64_t command_size = sizeof(RecordedTextureGetDataCommand) + p_buffer_texture_copy_regions.size() * sizeof(RDD::BufferTextureCopyRegion); + RecordedTextureGetDataCommand *command = static_cast<RecordedTextureGetDataCommand *>(_allocate_command(command_size, command_index)); + command->type = RecordedCommand::TYPE_TEXTURE_GET_DATA; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->from_texture = p_src; + command->to_buffer = p_dst; + command->buffer_texture_copy_regions_count = p_buffer_texture_copy_regions.size(); + + RDD::BufferTextureCopyRegion *buffer_texture_copy_regions = command->buffer_texture_copy_regions(); + for (uint32_t i = 0; i < command->buffer_texture_copy_regions_count; i++) { + buffer_texture_copy_regions[i] = p_buffer_texture_copy_regions[i]; + } + + ResourceUsage usage = RESOURCE_USAGE_TRANSFER_FROM; + _add_command_to_graph(&p_src_tracker, &usage, 1, command_index, command); +} + +void RenderingDeviceGraph::add_texture_resolve(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_src_layer, uint32_t p_src_mipmap, uint32_t p_dst_layer, uint32_t p_dst_mipmap) { + DEV_ASSERT(p_src_tracker != nullptr); + DEV_ASSERT(p_dst_tracker != nullptr); + + int32_t command_index; + RecordedTextureResolveCommand *command = static_cast<RecordedTextureResolveCommand *>(_allocate_command(sizeof(RecordedTextureResolveCommand), command_index)); + command->type = RecordedCommand::TYPE_TEXTURE_RESOLVE; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->from_texture = p_src; + command->to_texture = p_dst; + command->src_layer = p_src_layer; + command->src_mipmap = p_src_mipmap; + command->dst_layer = p_dst_layer; + command->dst_mipmap = p_dst_mipmap; + + ResourceTracker *trackers[2] = { p_dst_tracker, p_src_tracker }; + ResourceUsage usages[2] = { RESOURCE_USAGE_TRANSFER_TO, RESOURCE_USAGE_TRANSFER_FROM }; + _add_command_to_graph(trackers, usages, 2, command_index, command); +} + +void RenderingDeviceGraph::add_texture_update(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, VectorView<RecordedBufferToTextureCopy> p_buffer_copies) { + DEV_ASSERT(p_dst_tracker != nullptr); + + int32_t command_index; + uint64_t command_size = sizeof(RecordedTextureUpdateCommand) + p_buffer_copies.size() * sizeof(RecordedBufferToTextureCopy); + RecordedTextureUpdateCommand *command = static_cast<RecordedTextureUpdateCommand *>(_allocate_command(command_size, command_index)); + command->type = RecordedCommand::TYPE_TEXTURE_UPDATE; + command->dst_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT; + command->to_texture = p_dst; + command->buffer_to_texture_copies_count = p_buffer_copies.size(); + + RecordedBufferToTextureCopy *buffer_to_texture_copies = command->buffer_to_texture_copies(); + for (uint32_t i = 0; i < command->buffer_to_texture_copies_count; i++) { + buffer_to_texture_copies[i] = p_buffer_copies[i]; + } + + ResourceUsage usage = RESOURCE_USAGE_TRANSFER_TO; + _add_command_to_graph(&p_dst_tracker, &usage, 1, command_index, command); +} + +void RenderingDeviceGraph::add_capture_timestamp(RDD::QueryPoolID p_query_pool, uint32_t p_index) { + int32_t command_index; + RecordedCaptureTimestampCommand *command = static_cast<RecordedCaptureTimestampCommand *>(_allocate_command(sizeof(RecordedCaptureTimestampCommand), command_index)); + command->type = RecordedCommand::TYPE_CAPTURE_TIMESTAMP; + command->dst_stages = 0; + command->pool = p_query_pool; + command->index = p_index; + _add_command_to_graph(nullptr, nullptr, 0, command_index, command); +} + +void RenderingDeviceGraph::add_synchronization() { + // Synchronization is only acknowledged if commands have been recorded on the graph already. + if (command_count > 0) { + command_synchronization_pending = true; + } +} + +void RenderingDeviceGraph::begin_label(const String &p_label_name, const Color &p_color) { + uint32_t command_label_offset = command_label_chars.size(); + PackedByteArray command_label_utf8 = p_label_name.to_utf8_buffer(); + int command_label_utf8_size = command_label_utf8.size(); + command_label_chars.resize(command_label_offset + command_label_utf8_size + 1); + memcpy(&command_label_chars[command_label_offset], command_label_utf8.ptr(), command_label_utf8.size()); + command_label_chars[command_label_offset + command_label_utf8_size] = '\0'; + command_label_colors.push_back(p_color); + command_label_offsets.push_back(command_label_offset); + command_label_index = command_label_count; + command_label_count++; +} + +void RenderingDeviceGraph::end_label() { + command_label_index = -1; +} + +void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reorder_commands, bool p_full_barriers) { + if (command_count == 0) { + // No commands have been logged, do nothing. + return; + } + + thread_local LocalVector<RecordedCommandSort> commands_sorted; + if (p_reorder_commands) { + thread_local LocalVector<int64_t> command_stack; + thread_local LocalVector<int32_t> sorted_command_indices; + thread_local LocalVector<uint32_t> command_degrees; + int32_t adjacency_list_index = 0; + int32_t command_index; + + // Count all the incoming connections to every node by traversing their adjacency list. + command_degrees.resize(command_count); + memset(command_degrees.ptr(), 0, sizeof(uint32_t) * command_degrees.size()); + for (uint32_t i = 0; i < command_count; i++) { + const RecordedCommand &recorded_command = *reinterpret_cast<const RecordedCommand *>(&command_data[command_data_offsets[i]]); + adjacency_list_index = recorded_command.adjacent_command_list_index; + while (adjacency_list_index >= 0) { + const RecordedCommandListNode &command_list_node = command_list_nodes[adjacency_list_index]; + DEV_ASSERT((command_list_node.command_index != int32_t(i)) && "Command can't have itself as a dependency."); + command_degrees[command_list_node.command_index] += 1; + adjacency_list_index = command_list_node.next_list_index; + } + } + + // Push to the stack all nodes that have no incoming connections. + command_stack.clear(); + for (uint32_t i = 0; i < command_count; i++) { + if (command_degrees[i] == 0) { + command_stack.push_back(i); + } + } + + sorted_command_indices.clear(); + while (!command_stack.is_empty()) { + // Pop command from the stack. + command_index = command_stack[command_stack.size() - 1]; + command_stack.resize(command_stack.size() - 1); + + // Add it to the sorted commands. + sorted_command_indices.push_back(command_index); + + // Search for its adjacents and lower their degree for every visit. If the degree reaches zero, we push the command to the stack. + const uint32_t command_data_offset = command_data_offsets[command_index]; + const RecordedCommand &recorded_command = *reinterpret_cast<const RecordedCommand *>(&command_data[command_data_offset]); + adjacency_list_index = recorded_command.adjacent_command_list_index; + while (adjacency_list_index >= 0) { + const RecordedCommandListNode &command_list_node = command_list_nodes[adjacency_list_index]; + uint32_t &command_degree = command_degrees[command_list_node.command_index]; + DEV_ASSERT(command_degree > 0); + command_degree--; + if (command_degree == 0) { + command_stack.push_back(command_list_node.command_index); + } + + adjacency_list_index = command_list_node.next_list_index; + } + } + + // Batch buffer, texture, draw lists and compute operations together. + const uint32_t PriorityTable[RecordedCommand::TYPE_MAX] = { + 0, // TYPE_NONE + 1, // TYPE_BUFFER_CLEAR + 1, // TYPE_BUFFER_COPY + 1, // TYPE_BUFFER_GET_DATA + 1, // TYPE_BUFFER_UPDATE + 4, // TYPE_COMPUTE_LIST + 3, // TYPE_DRAW_LIST + 2, // TYPE_TEXTURE_CLEAR + 2, // TYPE_TEXTURE_COPY + 2, // TYPE_TEXTURE_GET_DATA + 2, // TYPE_TEXTURE_RESOLVE + 2, // TYPE_TEXTURE_UPDATE + }; + + commands_sorted.clear(); + commands_sorted.resize(command_count); + + for (uint32_t i = 0; i < command_count; i++) { + const int32_t sorted_command_index = sorted_command_indices[i]; + const uint32_t command_data_offset = command_data_offsets[sorted_command_index]; + const RecordedCommand recorded_command = *reinterpret_cast<const RecordedCommand *>(&command_data[command_data_offset]); + const uint32_t next_command_level = commands_sorted[sorted_command_index].level + 1; + adjacency_list_index = recorded_command.adjacent_command_list_index; + while (adjacency_list_index >= 0) { + const RecordedCommandListNode &command_list_node = command_list_nodes[adjacency_list_index]; + uint32_t &adjacent_command_level = commands_sorted[command_list_node.command_index].level; + if (adjacent_command_level < next_command_level) { + adjacent_command_level = next_command_level; + } + + adjacency_list_index = command_list_node.next_list_index; + } + + commands_sorted[sorted_command_index].index = sorted_command_index; + commands_sorted[sorted_command_index].priority = PriorityTable[recorded_command.type]; + } + } else { + commands_sorted.clear(); + commands_sorted.resize(command_count); + + for (uint32_t i = 0; i < command_count; i++) { + commands_sorted[i].index = i; + } + } + + _wait_for_secondary_command_buffer_tasks(); + + if (command_count > 0) { + int32_t current_label_index = -1; + int32_t current_label_level = -1; + _run_label_command_change(p_command_buffer, -1, -1, true, true, nullptr, 0, current_label_index, current_label_level); + + if (p_reorder_commands) { +#if PRINT_RENDER_GRAPH + print_line("BEFORE SORT"); + _print_render_commands(commands_sorted.ptr(), command_count); +#endif + + commands_sorted.sort(); + +#if PRINT_RENDER_GRAPH + print_line("AFTER SORT"); + _print_render_commands(commands_sorted.ptr(), command_count); +#endif + + uint32_t boosted_priority = 0; + uint32_t current_level = commands_sorted[0].level; + uint32_t current_level_start = 0; + for (uint32_t i = 0; i < command_count; i++) { + if (current_level != commands_sorted[i].level) { + RecordedCommandSort *level_command_ptr = &commands_sorted[current_level_start]; + uint32_t level_command_count = i - current_level_start; + _boost_priority_for_render_commands(level_command_ptr, level_command_count, boosted_priority); + _group_barriers_for_render_commands(p_command_buffer, level_command_ptr, level_command_count, p_full_barriers); + _run_render_commands(p_command_buffer, current_level, level_command_ptr, level_command_count, current_label_index, current_label_level); + current_level = commands_sorted[i].level; + current_level_start = i; + } + } + + RecordedCommandSort *level_command_ptr = &commands_sorted[current_level_start]; + uint32_t level_command_count = command_count - current_level_start; + _boost_priority_for_render_commands(level_command_ptr, level_command_count, boosted_priority); + _group_barriers_for_render_commands(p_command_buffer, level_command_ptr, level_command_count, p_full_barriers); + _run_render_commands(p_command_buffer, current_level, level_command_ptr, level_command_count, current_label_index, current_label_level); + +#if PRINT_RENDER_GRAPH + print_line("COMMANDS", command_count, "LEVELS", current_level + 1); +#endif + } else { + for (uint32_t i = 0; i < command_count; i++) { + _group_barriers_for_render_commands(p_command_buffer, &commands_sorted[i], 1, p_full_barriers); + _run_render_commands(p_command_buffer, i, &commands_sorted[i], 1, current_label_index, current_label_level); + } + } + + _run_label_command_change(p_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level); + } + + // Advance the frame counter. It's not necessary to do this if no commands are recorded because that means no secondary command buffers were used. + frame = (frame + 1) % frames.size(); +} + +#if PRINT_RESOURCE_TRACKER_TOTAL +static uint32_t resource_tracker_total = 0; +#endif + +RenderingDeviceGraph::ResourceTracker *RenderingDeviceGraph::resource_tracker_create() { +#if PRINT_RESOURCE_TRACKER_TOTAL + print_line("Resource trackers:", ++resource_tracker_total); +#endif + return memnew(ResourceTracker); +} + +void RenderingDeviceGraph::resource_tracker_free(ResourceTracker *tracker) { + if (tracker == nullptr) { + return; + } + + if (tracker->in_parent_dirty_list) { + // Delete the tracker from the parent's dirty linked list. + if (tracker->parent->dirty_shared_list == tracker) { + tracker->parent->dirty_shared_list = tracker->next_shared; + } else { + ResourceTracker *node = tracker->parent->dirty_shared_list; + while (node != nullptr) { + if (node->next_shared == tracker) { + node->next_shared = tracker->next_shared; + node = nullptr; + } else { + node = node->next_shared; + } + } + } + } + + memdelete(tracker); + +#if PRINT_RESOURCE_TRACKER_TOTAL + print_line("Resource trackers:", --resource_tracker_total); +#endif +} diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h new file mode 100644 index 0000000000..84fbe02095 --- /dev/null +++ b/servers/rendering/rendering_device_graph.h @@ -0,0 +1,668 @@ +/**************************************************************************/ +/* rendering_device_graph.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef RENDERING_DEVICE_GRAPH_H +#define RENDERING_DEVICE_GRAPH_H + +#include "core/object/worker_thread_pool.h" +#include "rendering_device_commons.h" +#include "rendering_device_driver.h" + +// Buffer barriers have not shown any significant improvement or shown to be +// even detrimental to performance. However, there are currently some known +// cases where using them can solve problems that using singular memory +// barriers does not, probably due to driver issues (see comment on PR #84976 +// https://github.com/godotengine/godot/pull/84976#issuecomment-1878566830). + +#define USE_BUFFER_BARRIERS 1 + +class RenderingDeviceGraph { +public: + struct ComputeListInstruction { + enum Type { + TYPE_NONE, + TYPE_BIND_PIPELINE, + TYPE_BIND_UNIFORM_SET, + TYPE_DISPATCH, + TYPE_DISPATCH_INDIRECT, + TYPE_SET_PUSH_CONSTANT, + TYPE_UNIFORM_SET_PREPARE_FOR_USE + }; + + Type type = TYPE_NONE; + }; + + struct DrawListInstruction { + enum Type { + TYPE_NONE, + TYPE_BIND_INDEX_BUFFER, + TYPE_BIND_PIPELINE, + TYPE_BIND_UNIFORM_SET, + TYPE_BIND_VERTEX_BUFFERS, + TYPE_CLEAR_ATTACHMENTS, + TYPE_DRAW, + TYPE_DRAW_INDEXED, + TYPE_EXECUTE_COMMANDS, + TYPE_NEXT_SUBPASS, + TYPE_SET_BLEND_CONSTANTS, + TYPE_SET_LINE_WIDTH, + TYPE_SET_PUSH_CONSTANT, + TYPE_SET_SCISSOR, + TYPE_SET_VIEWPORT, + TYPE_UNIFORM_SET_PREPARE_FOR_USE + }; + + Type type = TYPE_NONE; + }; + + struct RecordedCommand { + enum Type { + TYPE_NONE, + TYPE_BUFFER_CLEAR, + TYPE_BUFFER_COPY, + TYPE_BUFFER_GET_DATA, + TYPE_BUFFER_UPDATE, + TYPE_COMPUTE_LIST, + TYPE_DRAW_LIST, + TYPE_TEXTURE_CLEAR, + TYPE_TEXTURE_COPY, + TYPE_TEXTURE_GET_DATA, + TYPE_TEXTURE_RESOLVE, + TYPE_TEXTURE_UPDATE, + TYPE_CAPTURE_TIMESTAMP, + TYPE_MAX + }; + + Type type = TYPE_NONE; + int32_t adjacent_command_list_index = -1; + RDD::MemoryBarrier memory_barrier; + int32_t normalization_barrier_index = -1; + int normalization_barrier_count = 0; + int32_t transition_barrier_index = -1; + int32_t transition_barrier_count = 0; +#if USE_BUFFER_BARRIERS + int32_t buffer_barrier_index = -1; + int32_t buffer_barrier_count = 0; +#endif + int32_t label_index = -1; + BitField<RDD::PipelineStageBits> src_stages; + BitField<RDD::PipelineStageBits> dst_stages; + }; + + struct RecordedBufferCopy { + RDD::BufferID source; + RDD::BufferCopyRegion region; + }; + + struct RecordedBufferToTextureCopy { + RDD::BufferID from_buffer; + RDD::BufferTextureCopyRegion region; + }; + + enum ResourceUsage { + RESOURCE_USAGE_NONE, + RESOURCE_USAGE_TRANSFER_FROM, + RESOURCE_USAGE_TRANSFER_TO, + RESOURCE_USAGE_UNIFORM_BUFFER_READ, + RESOURCE_USAGE_INDIRECT_BUFFER_READ, + RESOURCE_USAGE_TEXTURE_BUFFER_READ, + RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE, + RESOURCE_USAGE_STORAGE_BUFFER_READ, + RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE, + RESOURCE_USAGE_VERTEX_BUFFER_READ, + RESOURCE_USAGE_INDEX_BUFFER_READ, + RESOURCE_USAGE_TEXTURE_SAMPLE, + RESOURCE_USAGE_STORAGE_IMAGE_READ, + RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE, + RESOURCE_USAGE_ATTACHMENT_COLOR_READ, + RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE, + RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ, + RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE + }; + + struct ResourceTracker { + uint32_t reference_count = 0; + int64_t command_frame = -1; + int32_t read_command_list_index = -1; + int32_t write_command_or_list_index = -1; + int32_t draw_list_index = -1; + int32_t compute_list_index = -1; + ResourceUsage usage = RESOURCE_USAGE_NONE; + BitField<RDD::BarrierAccessBits> usage_access; + RDD::BufferID buffer_driver_id; + RDD::TextureID texture_driver_id; + RDD::TextureSubresourceRange texture_subresources; + int32_t texture_slice_command_index = -1; + ResourceTracker *parent = nullptr; + ResourceTracker *dirty_shared_list = nullptr; + ResourceTracker *next_shared = nullptr; + Rect2i texture_slice_or_dirty_rect; + bool in_parent_dirty_list = false; + bool write_command_list_enabled = false; + + _FORCE_INLINE_ void reset_if_outdated(int64_t new_command_frame) { + if (new_command_frame != command_frame) { + usage_access.clear(); + command_frame = new_command_frame; + read_command_list_index = -1; + write_command_or_list_index = -1; + draw_list_index = -1; + compute_list_index = -1; + texture_slice_command_index = -1; + write_command_list_enabled = false; + } + } + }; + +private: + struct InstructionList { + LocalVector<uint8_t> data; + LocalVector<ResourceTracker *> command_trackers; + LocalVector<ResourceUsage> command_tracker_usages; + BitField<RDD::PipelineStageBits> stages; + int32_t index = 0; + + void clear() { + data.clear(); + command_trackers.clear(); + command_tracker_usages.clear(); + stages.clear(); + } + }; + + struct ComputeInstructionList : InstructionList { + // No extra contents. + }; + + struct DrawInstructionList : InstructionList { + RDD::RenderPassID render_pass; + RDD::FramebufferID framebuffer; + Rect2i region; + LocalVector<RDD::RenderPassClearValue> clear_values; + }; + + struct RecordedCommandSort { + uint32_t level = 0; + uint32_t priority = 0; + int32_t index = -1; + + RecordedCommandSort() = default; + + bool operator<(const RecordedCommandSort &p_other) const { + if (level < p_other.level) { + return true; + } else if (level > p_other.level) { + return false; + } + + if (priority < p_other.priority) { + return true; + } else if (priority > p_other.priority) { + return false; + } + + return index < p_other.index; + } + }; + + struct RecordedCommandListNode { + int32_t command_index = -1; + int32_t next_list_index = -1; + }; + + struct RecordedWriteListNode { + int32_t command_index = -1; + int32_t next_list_index = -1; + Rect2i subresources; + }; + + struct RecordedBufferClearCommand : RecordedCommand { + RDD::BufferID buffer; + uint32_t offset = 0; + uint32_t size = 0; + }; + + struct RecordedBufferCopyCommand : RecordedCommand { + RDD::BufferID source; + RDD::BufferID destination; + RDD::BufferCopyRegion region; + }; + + struct RecordedBufferGetDataCommand : RecordedCommand { + RDD::BufferID source; + RDD::BufferID destination; + RDD::BufferCopyRegion region; + }; + + struct RecordedBufferUpdateCommand : RecordedCommand { + RDD::BufferID destination; + uint32_t buffer_copies_count = 0; + + _FORCE_INLINE_ RecordedBufferCopy *buffer_copies() { + return reinterpret_cast<RecordedBufferCopy *>(&this[1]); + } + + _FORCE_INLINE_ const RecordedBufferCopy *buffer_copies() const { + return reinterpret_cast<const RecordedBufferCopy *>(&this[1]); + } + }; + + struct RecordedComputeListCommand : RecordedCommand { + uint32_t instruction_data_size = 0; + + _FORCE_INLINE_ uint8_t *instruction_data() { + return reinterpret_cast<uint8_t *>(&this[1]); + } + + _FORCE_INLINE_ const uint8_t *instruction_data() const { + return reinterpret_cast<const uint8_t *>(&this[1]); + } + }; + + struct RecordedDrawListCommand : RecordedCommand { + uint32_t instruction_data_size = 0; + RDD::RenderPassID render_pass; + RDD::FramebufferID framebuffer; + RDD::CommandBufferType command_buffer_type; + Rect2i region; + uint32_t clear_values_count = 0; + + _FORCE_INLINE_ RDD::RenderPassClearValue *clear_values() { + return reinterpret_cast<RDD::RenderPassClearValue *>(&this[1]); + } + + _FORCE_INLINE_ const RDD::RenderPassClearValue *clear_values() const { + return reinterpret_cast<const RDD::RenderPassClearValue *>(&this[1]); + } + + _FORCE_INLINE_ uint8_t *instruction_data() { + return reinterpret_cast<uint8_t *>(&clear_values()[clear_values_count]); + } + + _FORCE_INLINE_ const uint8_t *instruction_data() const { + return reinterpret_cast<const uint8_t *>(&clear_values()[clear_values_count]); + } + }; + + struct RecordedTextureClearCommand : RecordedCommand { + RDD::TextureID texture; + RDD::TextureSubresourceRange range; + Color color; + }; + + struct RecordedTextureCopyCommand : RecordedCommand { + RDD::TextureID from_texture; + RDD::TextureID to_texture; + RDD::TextureCopyRegion region; + }; + + struct RecordedTextureGetDataCommand : RecordedCommand { + RDD::TextureID from_texture; + RDD::BufferID to_buffer; + uint32_t buffer_texture_copy_regions_count = 0; + + _FORCE_INLINE_ RDD::BufferTextureCopyRegion *buffer_texture_copy_regions() { + return reinterpret_cast<RDD::BufferTextureCopyRegion *>(&this[1]); + } + + _FORCE_INLINE_ const RDD::BufferTextureCopyRegion *buffer_texture_copy_regions() const { + return reinterpret_cast<const RDD::BufferTextureCopyRegion *>(&this[1]); + } + }; + + struct RecordedTextureResolveCommand : RecordedCommand { + RDD::TextureID from_texture; + RDD::TextureID to_texture; + uint32_t src_layer = 0; + uint32_t src_mipmap = 0; + uint32_t dst_layer = 0; + uint32_t dst_mipmap = 0; + }; + + struct RecordedTextureUpdateCommand : RecordedCommand { + RDD::TextureID to_texture; + uint32_t buffer_to_texture_copies_count = 0; + + _FORCE_INLINE_ RecordedBufferToTextureCopy *buffer_to_texture_copies() { + return reinterpret_cast<RecordedBufferToTextureCopy *>(&this[1]); + } + + _FORCE_INLINE_ const RecordedBufferToTextureCopy *buffer_to_texture_copies() const { + return reinterpret_cast<const RecordedBufferToTextureCopy *>(&this[1]); + } + }; + + struct RecordedCaptureTimestampCommand : RecordedCommand { + RDD::QueryPoolID pool; + uint32_t index = 0; + }; + + struct DrawListBindIndexBufferInstruction : DrawListInstruction { + RDD::BufferID buffer; + RenderingDeviceCommons::IndexBufferFormat format; + uint32_t offset = 0; + }; + + struct DrawListBindPipelineInstruction : DrawListInstruction { + RDD::PipelineID pipeline; + }; + + struct DrawListBindUniformSetInstruction : DrawListInstruction { + RDD::UniformSetID uniform_set; + RDD::ShaderID shader; + uint32_t set_index = 0; + }; + + struct DrawListBindVertexBuffersInstruction : DrawListInstruction { + uint32_t vertex_buffers_count = 0; + + _FORCE_INLINE_ RDD::BufferID *vertex_buffers() { + return reinterpret_cast<RDD::BufferID *>(&this[1]); + } + + _FORCE_INLINE_ const RDD::BufferID *vertex_buffers() const { + return reinterpret_cast<const RDD::BufferID *>(&this[1]); + } + + _FORCE_INLINE_ uint64_t *vertex_buffer_offsets() { + return reinterpret_cast<uint64_t *>(&vertex_buffers()[vertex_buffers_count]); + } + + _FORCE_INLINE_ const uint64_t *vertex_buffer_offsets() const { + return reinterpret_cast<const uint64_t *>(&vertex_buffers()[vertex_buffers_count]); + } + }; + + struct DrawListClearAttachmentsInstruction : DrawListInstruction { + uint32_t attachments_clear_count = 0; + uint32_t attachments_clear_rect_count = 0; + + _FORCE_INLINE_ RDD::AttachmentClear *attachments_clear() { + return reinterpret_cast<RDD::AttachmentClear *>(&this[1]); + } + + _FORCE_INLINE_ const RDD::AttachmentClear *attachments_clear() const { + return reinterpret_cast<const RDD::AttachmentClear *>(&this[1]); + } + + _FORCE_INLINE_ Rect2i *attachments_clear_rect() { + return reinterpret_cast<Rect2i *>(&attachments_clear()[attachments_clear_count]); + } + + _FORCE_INLINE_ const Rect2i *attachments_clear_rect() const { + return reinterpret_cast<const Rect2i *>(&attachments_clear()[attachments_clear_count]); + } + }; + + struct DrawListDrawInstruction : DrawListInstruction { + uint32_t vertex_count = 0; + uint32_t instance_count = 0; + }; + + struct DrawListDrawIndexedInstruction : DrawListInstruction { + uint32_t index_count = 0; + uint32_t instance_count = 0; + uint32_t first_index = 0; + }; + + struct DrawListEndRenderPassInstruction : DrawListInstruction { + // No contents. + }; + + struct DrawListExecuteCommandsInstruction : DrawListInstruction { + RDD::CommandBufferID command_buffer; + }; + + struct DrawListSetPushConstantInstruction : DrawListInstruction { + uint32_t size = 0; + RDD::ShaderID shader; + + _FORCE_INLINE_ uint8_t *data() { + return reinterpret_cast<uint8_t *>(&this[1]); + } + + _FORCE_INLINE_ const uint8_t *data() const { + return reinterpret_cast<const uint8_t *>(&this[1]); + } + }; + + struct DrawListNextSubpassInstruction : DrawListInstruction { + RDD::CommandBufferType command_buffer_type; + }; + + struct DrawListSetBlendConstantsInstruction : DrawListInstruction { + Color color; + }; + + struct DrawListSetLineWidthInstruction : DrawListInstruction { + float width; + }; + + struct DrawListSetScissorInstruction : DrawListInstruction { + Rect2i rect; + }; + + struct DrawListSetViewportInstruction : DrawListInstruction { + Rect2i rect; + }; + + struct DrawListUniformSetPrepareForUseInstruction : DrawListInstruction { + RDD::UniformSetID uniform_set; + RDD::ShaderID shader; + uint32_t set_index = 0; + }; + + struct ComputeListBindPipelineInstruction : ComputeListInstruction { + RDD::PipelineID pipeline; + }; + + struct ComputeListBindUniformSetInstruction : ComputeListInstruction { + RDD::UniformSetID uniform_set; + RDD::ShaderID shader; + uint32_t set_index = 0; + }; + + struct ComputeListDispatchInstruction : ComputeListInstruction { + uint32_t x_groups = 0; + uint32_t y_groups = 0; + uint32_t z_groups = 0; + }; + + struct ComputeListDispatchIndirectInstruction : ComputeListInstruction { + RDD::BufferID buffer; + uint32_t offset = 0; + }; + + struct ComputeListSetPushConstantInstruction : ComputeListInstruction { + uint32_t size = 0; + RDD::ShaderID shader; + + _FORCE_INLINE_ uint8_t *data() { + return reinterpret_cast<uint8_t *>(&this[1]); + } + + _FORCE_INLINE_ const uint8_t *data() const { + return reinterpret_cast<const uint8_t *>(&this[1]); + } + }; + + struct ComputeListUniformSetPrepareForUseInstruction : ComputeListInstruction { + RDD::UniformSetID uniform_set; + RDD::ShaderID shader; + uint32_t set_index = 0; + }; + + struct BarrierGroup { + BitField<RDD::PipelineStageBits> src_stages; + BitField<RDD::PipelineStageBits> dst_stages; + RDD::MemoryBarrier memory_barrier; + LocalVector<RDD::TextureBarrier> normalization_barriers; + LocalVector<RDD::TextureBarrier> transition_barriers; +#if USE_BUFFER_BARRIERS + LocalVector<RDD::BufferBarrier> buffer_barriers; +#endif + + void clear() { + src_stages.clear(); + dst_stages.clear(); + memory_barrier.src_access.clear(); + memory_barrier.dst_access.clear(); + normalization_barriers.clear(); + transition_barriers.clear(); +#if USE_BUFFER_BARRIERS + buffer_barriers.clear(); +#endif + } + }; + + struct SecondaryCommandBuffer { + LocalVector<uint8_t> instruction_data; + RDD::CommandBufferID command_buffer; + RDD::CommandPoolID command_pool; + RDD::RenderPassID render_pass; + RDD::FramebufferID framebuffer; + WorkerThreadPool::TaskID task; + }; + + struct Frame { + TightLocalVector<SecondaryCommandBuffer> secondary_command_buffers; + uint32_t secondary_command_buffers_used = 0; + }; + + RDD *driver = nullptr; + int64_t tracking_frame = 0; + LocalVector<uint8_t> command_data; + LocalVector<uint32_t> command_data_offsets; + LocalVector<RDD::TextureBarrier> command_normalization_barriers; + LocalVector<RDD::TextureBarrier> command_transition_barriers; + LocalVector<RDD::BufferBarrier> command_buffer_barriers; + LocalVector<char> command_label_chars; + LocalVector<Color> command_label_colors; + LocalVector<uint32_t> command_label_offsets; + int32_t command_label_index = -1; + DrawInstructionList draw_instruction_list; + ComputeInstructionList compute_instruction_list; + uint32_t command_count = 0; + uint32_t command_label_count = 0; + LocalVector<RecordedCommandListNode> command_list_nodes; + LocalVector<RecordedWriteListNode> write_list_nodes; + int32_t command_timestamp_index = -1; + int32_t command_synchronization_index = -1; + bool command_synchronization_pending = false; + BarrierGroup barrier_group; + bool driver_honors_barriers = false; + TightLocalVector<Frame> frames; + uint32_t frame = 0; + +#ifdef DEV_ENABLED + RBMap<ResourceTracker *, uint32_t> write_dependency_counters; +#endif + + static bool _is_write_usage(ResourceUsage p_usage); + static RDD::TextureLayout _usage_to_image_layout(ResourceUsage p_usage); + static RDD::BarrierAccessBits _usage_to_access_bits(ResourceUsage p_usage); + int32_t _add_to_command_list(int32_t p_command_index, int32_t p_list_index); + void _add_adjacent_command(int32_t p_previous_command_index, int32_t p_command_index, RecordedCommand *r_command); + int32_t _add_to_write_list(int32_t p_command_index, Rect2i suberesources, int32_t p_list_index); + RecordedCommand *_allocate_command(uint32_t p_command_size, int32_t &r_command_index); + DrawListInstruction *_allocate_draw_list_instruction(uint32_t p_instruction_size); + ComputeListInstruction *_allocate_compute_list_instruction(uint32_t p_instruction_size); + void _add_command_to_graph(ResourceTracker **p_resource_trackers, ResourceUsage *p_resource_usages, uint32_t p_resource_count, int32_t p_command_index, RecordedCommand *r_command); + void _add_texture_barrier_to_command(RDD::TextureID p_texture_id, BitField<RDD::BarrierAccessBits> p_src_access, BitField<RDD::BarrierAccessBits> p_dst_access, ResourceUsage p_prev_usage, ResourceUsage p_next_usage, RDD::TextureSubresourceRange p_subresources, LocalVector<RDD::TextureBarrier> &r_barrier_vector, int32_t &r_barrier_index, int32_t &r_barrier_count); +#if USE_BUFFER_BARRIERS + void _add_buffer_barrier_to_command(RDD::BufferID p_buffer_id, BitField<RDD::BarrierAccessBits> p_src_access, BitField<RDD::BarrierAccessBits> p_dst_access, int32_t &r_barrier_index, int32_t &r_barrier_count); +#endif + void _run_compute_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size); + void _run_draw_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size); + void _run_secondary_command_buffer_task(const SecondaryCommandBuffer *p_secondary); + void _wait_for_secondary_command_buffer_tasks(); + void _run_render_commands(RDD::CommandBufferID p_command_buffer, int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level); + void _run_label_command_change(RDD::CommandBufferID p_command_buffer, int32_t p_new_label_index, int32_t p_new_level, bool p_ignore_previous_value, bool p_use_label_for_empty, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level); + void _boost_priority_for_render_commands(RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, uint32_t &r_boosted_priority); + void _group_barriers_for_render_commands(RDD::CommandBufferID p_command_buffer, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, bool p_full_memory_barrier); + void _print_render_commands(const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count); + void _print_draw_list(const uint8_t *p_instruction_data, uint32_t p_instruction_data_size); + void _print_compute_list(const uint8_t *p_instruction_data, uint32_t p_instruction_data_size); + +public: + RenderingDeviceGraph(); + ~RenderingDeviceGraph(); + void initialize(RDD *p_driver, uint32_t p_frame_count, uint32_t p_secondary_command_buffers_per_frame); + void begin(); + void add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size); + void add_buffer_copy(RDD::BufferID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, RDD::BufferCopyRegion p_region); + void add_buffer_get_data(RDD::BufferID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, RDD::BufferCopyRegion p_region); + void add_buffer_update(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, VectorView<RecordedBufferCopy> p_buffer_copies); + void add_compute_list_begin(); + void add_compute_list_bind_pipeline(RDD::PipelineID p_pipeline); + void add_compute_list_bind_uniform_set(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index); + void add_compute_list_dispatch(uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups); + void add_compute_list_dispatch_indirect(RDD::BufferID p_buffer, uint32_t p_offset); + void add_compute_list_set_push_constant(RDD::ShaderID p_shader, const void *p_data, uint32_t p_data_size); + void add_compute_list_uniform_set_prepare_for_use(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index); + void add_compute_list_usage(ResourceTracker *p_tracker, ResourceUsage p_usage); + void add_compute_list_usages(VectorView<ResourceTracker *> p_trackers, VectorView<ResourceUsage> p_usages); + void add_compute_list_end(); + void add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<RDD::RenderPassClearValue> p_clear_values, bool p_uses_color, bool p_uses_depth); + void add_draw_list_bind_index_buffer(RDD::BufferID p_buffer, RDD::IndexBufferFormat p_format, uint32_t p_offset); + void add_draw_list_bind_pipeline(RDD::PipelineID p_pipeline, BitField<RDD::PipelineStageBits> p_pipeline_stage_bits); + void add_draw_list_bind_uniform_set(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index); + void add_draw_list_bind_vertex_buffers(VectorView<RDD::BufferID> p_vertex_buffers, VectorView<uint64_t> p_vertex_buffer_offsets); + void add_draw_list_clear_attachments(VectorView<RDD::AttachmentClear> p_attachments_clear, VectorView<Rect2i> p_attachments_clear_rect); + void add_draw_list_draw(uint32_t p_vertex_count, uint32_t p_instance_count); + void add_draw_list_draw_indexed(uint32_t p_index_count, uint32_t p_instance_count, uint32_t p_first_index); + void add_draw_list_execute_commands(RDD::CommandBufferID p_command_buffer); + void add_draw_list_next_subpass(RDD::CommandBufferType p_command_buffer_type); + void add_draw_list_set_blend_constants(const Color &p_color); + void add_draw_list_set_line_width(float p_width); + void add_draw_list_set_push_constant(RDD::ShaderID p_shader, const void *p_data, uint32_t p_data_size); + void add_draw_list_set_scissor(Rect2i p_rect); + void add_draw_list_set_viewport(Rect2i p_rect); + void add_draw_list_uniform_set_prepare_for_use(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index); + void add_draw_list_usage(ResourceTracker *p_tracker, ResourceUsage p_usage); + void add_draw_list_usages(VectorView<ResourceTracker *> p_trackers, VectorView<ResourceUsage> p_usages); + void add_draw_list_end(); + void add_texture_clear(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, const Color &p_color, const RDD::TextureSubresourceRange &p_range); + void add_texture_copy(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, RDD::TextureCopyRegion p_region); + void add_texture_get_data(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, VectorView<RDD::BufferTextureCopyRegion> p_buffer_texture_copy_regions); + void add_texture_resolve(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_src_layer, uint32_t p_src_mipmap, uint32_t p_dst_layer, uint32_t p_dst_mipmap); + void add_texture_update(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, VectorView<RecordedBufferToTextureCopy> p_buffer_copies); + void add_capture_timestamp(RDD::QueryPoolID p_query_pool, uint32_t p_index); + void add_synchronization(); + void begin_label(const String &p_label_name, const Color &p_color); + void end_label(); + void end(RDD::CommandBufferID p_command_buffer, bool p_reorder_commands, bool p_full_barriers); + static ResourceTracker *resource_tracker_create(); + static void resource_tracker_free(ResourceTracker *tracker); +}; + +using RDG = RenderingDeviceGraph; + +#endif // RENDERING_DEVICE_GRAPH_H diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 77fe91e4c9..bf8ab27722 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -91,10 +91,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { RSG::viewport->draw_viewports(p_swap_buffers); RSG::canvas_render->update(); - if (!OS::get_singleton()->get_current_rendering_driver_name().begins_with("opengl3")) { - // Already called for gl_compatibility renderer. - RSG::rasterizer->end_frame(p_swap_buffers); - } + RSG::rasterizer->end_frame(p_swap_buffers); XRServer *xr_server = XRServer::get_singleton(); if (xr_server != nullptr) { @@ -214,6 +211,7 @@ void RenderingServerDefault::_finish() { free(test_cube); } + RSG::canvas->finalize(); RSG::rasterizer->finalize(); } @@ -289,9 +287,11 @@ void RenderingServerDefault::set_default_clear_color(const Color &p_color) { RSG::viewport->set_default_clear_color(p_color); } +#ifndef DISABLE_DEPRECATED bool RenderingServerDefault::has_feature(Features p_feature) const { return false; } +#endif void RenderingServerDefault::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { RSG::scene->sdfgi_set_debug_probe_select(p_position, p_dir); @@ -395,15 +395,19 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) : command_queue(p_create_thread) { RenderingServer::init(); +#ifdef THREADS_ENABLED create_thread = p_create_thread; - - if (!p_create_thread) { + if (!create_thread) { server_thread = Thread::get_caller_id(); } else { server_thread = 0; } +#else + create_thread = false; + server_thread = Thread::get_main_id(); +#endif + RSG::threaded = create_thread; - RSG::threaded = p_create_thread; RSG::canvas = memnew(RendererCanvasCull); RSG::viewport = memnew(RendererViewport); RendererSceneCull *sr = memnew(RendererSceneCull); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index dac1275957..e8b20692f0 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -78,7 +78,7 @@ class RenderingServerDefault : public RenderingServer { static void _thread_callback(void *_instance); void _thread_loop(); - Thread::ID server_thread; + Thread::ID server_thread = 0; SafeFlag exit; Thread thread; SafeFlag draw_thread_up; @@ -1021,7 +1021,9 @@ public: virtual Color get_default_clear_color() override; virtual void set_default_clear_color(const Color &p_color) override; +#ifndef DISABLE_DEPRECATED virtual bool has_feature(Features p_feature) const override; +#endif virtual bool has_os_feature(const String &p_feature) const override; virtual void set_debug_generate_wireframes(bool p_generate) override; diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 1e95cdde0c..2b49d42f9e 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -543,7 +543,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene uniform_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced for (int k = 0; k < uniform_names.size(); k++) { - StringName uniform_name = uniform_names[k]; + const StringName &uniform_name = uniform_names[k]; const SL::ShaderNode::Uniform &uniform = pnode->uniforms[uniform_name]; String ucode; @@ -670,7 +670,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene varying_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced for (int k = 0; k < varying_names.size(); k++) { - StringName varying_name = varying_names[k]; + const StringName &varying_name = varying_names[k]; const SL::ShaderNode::Varying &varying = pnode->varyings[varying_name]; if (varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT || varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) { @@ -1191,6 +1191,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene // we will add logic to automatically switch between // sampler2D and sampler2D array and vec2 UV and vec3 UV. bool multiview_uv_needed = false; + bool is_normal_roughness_texture = false; for (int i = 1; i < onode->arguments.size(); i++) { if (i > 1) { @@ -1259,7 +1260,6 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene // Need to map from texture to sampler in order to sample when using Vulkan GLSL. String sampler_name; bool is_depth_texture = false; - bool is_normal_roughness_texture = false; if (actions.custom_samplers.has(texture_uniform)) { sampler_name = actions.custom_samplers[texture_uniform]; @@ -1340,6 +1340,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (is_screen_texture && !texture_func_returns_data && actions.apply_luminance_multiplier) { code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))"; } + if (is_normal_roughness_texture && !texture_func_returns_data) { + code = "normal_roughness_compatibility(" + code + ")"; + } } break; case SL::OP_INDEX: { code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index a2da26eb65..fef1a205d6 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -4665,7 +4665,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi return false; } -bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) { +bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(const StringName &p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) { for (int i = 0; i < shader->vfunctions.size(); i++) { if (shader->vfunctions[i].name == p_name) { ERR_FAIL_INDEX_V(p_argument, shader->vfunctions[i].function->arguments.size(), false); @@ -4699,7 +4699,7 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam ERR_FAIL_V(false); //bug? function not found } -bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin) { +bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(const StringName &p_name, int p_argument, const StringName &p_builtin) { for (int i = 0; i < shader->vfunctions.size(); i++) { if (shader->vfunctions[i].name == p_name) { ERR_FAIL_INDEX_V(p_argument, shader->vfunctions[i].function->arguments.size(), false); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index c707f6aad7..737545b8ca 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -1092,8 +1092,8 @@ private: bool _validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str, bool *r_is_custom_function = nullptr); bool _parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg = nullptr); - bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat); - bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin); + bool _propagate_function_call_sampler_uniform_settings(const StringName &p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat); + bool _propagate_function_call_sampler_builtin_reference(const StringName &p_name, int p_argument, const StringName &p_builtin); bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message); bool _check_node_constness(const Node *p_node) const; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index b4af27c510..27e677bce0 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -103,7 +103,7 @@ PackedInt64Array RenderingServer::_instances_cull_convex_bind(const TypedArray<P } Vector<Plane> planes; for (int i = 0; i < p_convex.size(); ++i) { - Variant v = p_convex[i]; + const Variant &v = p_convex[i]; ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, PackedInt64Array()); planes.push_back(v); } @@ -2204,6 +2204,25 @@ void RenderingServer::fix_surface_compatibility(SurfaceData &p_surface, const St } #endif +#ifdef TOOLS_ENABLED +void RenderingServer::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + String pf = p_function; + if (p_idx == 0) { + if (pf == "global_shader_parameter_set" || pf == "global_shader_parameter_set_override" || + pf == "global_shader_parameter_get" || pf == "global_shader_parameter_get_type" || pf == "global_shader_parameter_remove") { + for (StringName E : global_shader_parameter_get_list()) { + r_options->push_back(E.operator String().quote()); + } + } else if (pf == "has_os_feature") { + for (String E : { "\"rgtc\"", "\"s3tc\"", "\"bptc\"", "\"etc\"", "\"etc2\"", "\"astc\"" }) { + r_options->push_back(E); + } + } + } + Object::get_argument_options(p_function, p_idx, r_options); +} +#endif + void RenderingServer::_bind_methods() { BIND_CONSTANT(NO_INDEX_ARRAY); BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); @@ -3343,7 +3362,6 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_default_clear_color"), &RenderingServer::get_default_clear_color); ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &RenderingServer::set_default_clear_color); - ClassDB::bind_method(D_METHOD("has_feature", "feature"), &RenderingServer::has_feature); ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &RenderingServer::has_os_feature); ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &RenderingServer::set_debug_generate_wireframes); @@ -3361,9 +3379,6 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(RENDERING_INFO_BUFFER_MEM_USED); BIND_ENUM_CONSTANT(RENDERING_INFO_VIDEO_MEM_USED); - BIND_ENUM_CONSTANT(FEATURE_SHADERS); - BIND_ENUM_CONSTANT(FEATURE_MULTITHREADED); - ADD_SIGNAL(MethodInfo("frame_pre_draw")); ADD_SIGNAL(MethodInfo("frame_post_draw")); @@ -3373,6 +3388,13 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("create_local_rendering_device"), &RenderingServer::create_local_rendering_device); ClassDB::bind_method(D_METHOD("call_on_render_thread", "callable"), &RenderingServer::call_on_render_thread); + +#ifndef DISABLE_DEPRECATED + ClassDB::bind_method(D_METHOD("has_feature", "feature"), &RenderingServer::has_feature); + + BIND_ENUM_CONSTANT(FEATURE_SHADERS); + BIND_ENUM_CONSTANT(FEATURE_MULTITHREADED); +#endif } void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data) { @@ -3471,15 +3493,15 @@ void RenderingServer::init() { GLOBAL_DEF("rendering/shader_compiler/shader_cache/strip_debug", false); GLOBAL_DEF("rendering/shader_compiler/shader_cache/strip_debug.release", true); - GLOBAL_DEF_RST("rendering/reflections/sky_reflections/roughness_layers", 8); // Assumes a 256x256 cubemap + GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/reflections/sky_reflections/roughness_layers", PROPERTY_HINT_RANGE, "1,32,1"), 8); // Assumes a 256x256 cubemap GLOBAL_DEF_RST("rendering/reflections/sky_reflections/texture_array_reflections", true); GLOBAL_DEF("rendering/reflections/sky_reflections/texture_array_reflections.mobile", false); - GLOBAL_DEF_RST("rendering/reflections/sky_reflections/ggx_samples", 32); - GLOBAL_DEF("rendering/reflections/sky_reflections/ggx_samples.mobile", 16); + GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/reflections/sky_reflections/ggx_samples", PROPERTY_HINT_RANGE, "0,256,1"), 32); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/reflections/sky_reflections/ggx_samples.mobile", PROPERTY_HINT_RANGE, "0,128,1"), 16); GLOBAL_DEF("rendering/reflections/sky_reflections/fast_filter_high_quality", false); - GLOBAL_DEF("rendering/reflections/reflection_atlas/reflection_size", 256); - GLOBAL_DEF("rendering/reflections/reflection_atlas/reflection_size.mobile", 128); - GLOBAL_DEF("rendering/reflections/reflection_atlas/reflection_count", 64); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/reflections/reflection_atlas/reflection_size", PROPERTY_HINT_RANGE, "0,4096,1"), 256); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/reflections/reflection_atlas/reflection_size.mobile", PROPERTY_HINT_RANGE, "0,2048,1"), 128); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/reflections/reflection_atlas/reflection_count", PROPERTY_HINT_RANGE, "0,256,1"), 64); GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false); @@ -3526,7 +3548,7 @@ void RenderingServer::init() { GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"), DECAL_FILTER_LINEAR_MIPMAPS); GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"), LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS); - GLOBAL_DEF_RST("rendering/occlusion_culling/occlusion_rays_per_thread", 512); + GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/occlusion_culling/occlusion_rays_per_thread", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), 512); GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/environment/glow/upscale_mode", PROPERTY_HINT_ENUM, "Linear (Fast),Bicubic (Slow)"), 1); GLOBAL_DEF("rendering/environment/glow/upscale_mode.mobile", 0); @@ -3537,7 +3559,7 @@ void RenderingServer::init() { GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/environment/subsurface_scattering/subsurface_scattering_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"), 0.05); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"), 0.01); - GLOBAL_DEF("rendering/limits/global_shader_variables/buffer_size", 65536); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/limits/global_shader_variables/buffer_size", PROPERTY_HINT_RANGE, "1,1048576,1"), 65536); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/lightmapping/probe_capture/update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001"), 15); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/lightmapping/primitive_meshes/texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.2); @@ -3552,7 +3574,6 @@ void RenderingServer::init() { GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/limits/spatial_indexer/update_iterations_per_frame", PROPERTY_HINT_RANGE, "0,1024,1"), 10); GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/limits/spatial_indexer/threaded_cull_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"), 1000); - GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/limits/forward_renderer/threaded_render_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"), 500); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1"), 512); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 016801fa6e..958c21f893 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1612,13 +1612,14 @@ public: virtual Color get_default_clear_color() = 0; virtual void set_default_clear_color(const Color &p_color) = 0; +#ifndef DISABLE_DEPRECATED + // Never actually used, should be removed when we can break compatibility. enum Features { FEATURE_SHADERS, FEATURE_MULTITHREADED, }; - virtual bool has_feature(Features p_feature) const = 0; - +#endif virtual bool has_os_feature(const String &p_feature) const = 0; virtual void set_debug_generate_wireframes(bool p_generate) = 0; @@ -1639,6 +1640,10 @@ public: virtual void call_on_render_thread(const Callable &p_callable) = 0; +#ifdef TOOLS_ENABLED + virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; +#endif + RenderingServer(); virtual ~RenderingServer(); @@ -1744,10 +1749,13 @@ VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter); VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode); VARIANT_ENUM_CAST(RenderingServer::GlobalShaderParameterType); VARIANT_ENUM_CAST(RenderingServer::RenderingInfo); -VARIANT_ENUM_CAST(RenderingServer::Features); VARIANT_ENUM_CAST(RenderingServer::CanvasTextureChannel); VARIANT_ENUM_CAST(RenderingServer::BakeChannels); +#ifndef DISABLE_DEPRECATED +VARIANT_ENUM_CAST(RenderingServer::Features); +#endif + // Alias to make it easier to use. #define RS RenderingServer diff --git a/tests/core/math/test_aabb.h b/tests/core/math/test_aabb.h index d3560ff6b6..b9f84cca24 100644 --- a/tests/core/math/test_aabb.h +++ b/tests/core/math/test_aabb.h @@ -228,11 +228,20 @@ TEST_CASE("[AABB] Merging") { TEST_CASE("[AABB] Encloses") { const AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6)); + CHECK_MESSAGE( + aabb_big.encloses(aabb_big), + "encloses() with itself should return the expected result."); + AABB aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1)); CHECK_MESSAGE( aabb_big.encloses(aabb_small), "encloses() with fully contained AABB (touching the edge) should return the expected result."); + aabb_small = AABB(Vector3(1.5, 6, 2.5), Vector3(1, 1, 1)); + CHECK_MESSAGE( + aabb_big.encloses(aabb_small), + "encloses() with fully contained AABB (touching the edge) should return the expected result."); + aabb_small = AABB(Vector3(0.5, 1.5, -2), Vector3(1, 1, 1)); CHECK_MESSAGE( !aabb_big.encloses(aabb_small), diff --git a/tests/core/math/test_math_funcs.h b/tests/core/math/test_math_funcs.h index 5fbea4aece..0a9d9c97d9 100644 --- a/tests/core/math/test_math_funcs.h +++ b/tests/core/math/test_math_funcs.h @@ -110,6 +110,29 @@ TEST_CASE_TEMPLATE("[Math] round/floor/ceil", T, float, double) { CHECK(Math::ceil((T)-1.9) == (T)-1.0); } +TEST_CASE_TEMPLATE("[Math] integer division round up unsigned", T, uint32_t, uint64_t) { + CHECK(Math::division_round_up((T)0, (T)64) == 0); + CHECK(Math::division_round_up((T)1, (T)64) == 1); + CHECK(Math::division_round_up((T)63, (T)64) == 1); + CHECK(Math::division_round_up((T)64, (T)64) == 1); + CHECK(Math::division_round_up((T)65, (T)64) == 2); + CHECK(Math::division_round_up((T)65, (T)1) == 65); +} + +TEST_CASE_TEMPLATE("[Math] integer division round up signed", T, int32_t, int64_t) { + CHECK(Math::division_round_up((T)0, (T)64) == 0); + CHECK(Math::division_round_up((T)1, (T)64) == 1); + CHECK(Math::division_round_up((T)63, (T)64) == 1); + CHECK(Math::division_round_up((T)64, (T)64) == 1); + CHECK(Math::division_round_up((T)65, (T)64) == 2); + CHECK(Math::division_round_up((T)65, (T)1) == 65); + CHECK(Math::division_round_up((T)-1, (T)64) == 0); + CHECK(Math::division_round_up((T)-1, (T)-1) == 1); + CHECK(Math::division_round_up((T)-1, (T)1) == -1); + CHECK(Math::division_round_up((T)-1, (T)-2) == 1); + CHECK(Math::division_round_up((T)-4, (T)-2) == 2); +} + TEST_CASE_TEMPLATE("[Math] sin/cos/tan", T, float, double) { CHECK(Math::sin((T)-0.1) == doctest::Approx((T)-0.0998334166)); CHECK(Math::sin((T)0.1) == doctest::Approx((T)0.0998334166)); diff --git a/tests/core/math/test_vector2i.h b/tests/core/math/test_vector2i.h index 743c87f486..0f33400f7f 100644 --- a/tests/core/math/test_vector2i.h +++ b/tests/core/math/test_vector2i.h @@ -87,6 +87,12 @@ TEST_CASE("[Vector2i] Length methods") { CHECK_MESSAGE( vector2.length() == doctest::Approx(36.05551275463989293119), "Vector2i length should work as expected."); + CHECK_MESSAGE( + vector1.distance_squared_to(vector2) == 500, + "Vector2i distance_squared_to should work as expected and return exact result."); + CHECK_MESSAGE( + vector1.distance_to(vector2) == doctest::Approx(22.36067977499789696409), + "Vector2i distance_to should work as expected."); } TEST_CASE("[Vector2i] Operators") { diff --git a/tests/core/math/test_vector3i.h b/tests/core/math/test_vector3i.h index 485a500715..3914b85a75 100644 --- a/tests/core/math/test_vector3i.h +++ b/tests/core/math/test_vector3i.h @@ -90,6 +90,12 @@ TEST_CASE("[Vector3i] Length methods") { CHECK_MESSAGE( vector2.length() == doctest::Approx(53.8516480713450403125), "Vector3i length should work as expected."); + CHECK_MESSAGE( + vector1.distance_squared_to(vector2) == 1400, + "Vector3i distance_squared_to should work as expected and return exact result."); + CHECK_MESSAGE( + vector1.distance_to(vector2) == doctest::Approx(37.41657386773941385584), + "Vector3i distance_to should work as expected."); } TEST_CASE("[Vector3i] Operators") { diff --git a/tests/core/math/test_vector4i.h b/tests/core/math/test_vector4i.h index 5fda6f1778..31f68696c0 100644 --- a/tests/core/math/test_vector4i.h +++ b/tests/core/math/test_vector4i.h @@ -90,6 +90,12 @@ TEST_CASE("[Vector4i] Length methods") { CHECK_MESSAGE( vector2.length() == doctest::Approx(73.4846922835), "Vector4i length should work as expected."); + CHECK_MESSAGE( + vector1.distance_squared_to(vector2) == 3000, + "Vector4i distance_squared_to should work as expected."); + CHECK_MESSAGE( + vector1.distance_to(vector2) == doctest::Approx(54.772255750517), + "Vector4i distance_to should work as expected."); } TEST_CASE("[Vector4i] Operators") { diff --git a/tests/core/string/test_node_path.h b/tests/core/string/test_node_path.h index b0c810bb54..031a33c570 100644 --- a/tests/core/string/test_node_path.h +++ b/tests/core/string/test_node_path.h @@ -98,44 +98,44 @@ TEST_CASE("[NodePath] Relative path") { } TEST_CASE("[NodePath] Absolute path") { - const NodePath node_path_aboslute = NodePath("/root/Sprite2D"); + const NodePath node_path_absolute = NodePath("/root/Sprite2D"); CHECK_MESSAGE( - node_path_aboslute.get_as_property_path() == NodePath(":root/Sprite2D"), + node_path_absolute.get_as_property_path() == NodePath(":root/Sprite2D"), "The returned property path should match the expected value."); CHECK_MESSAGE( - node_path_aboslute.get_concatenated_subnames() == "", + node_path_absolute.get_concatenated_subnames() == "", "The returned concatenated subnames should match the expected value."); CHECK_MESSAGE( - node_path_aboslute.get_name(0) == "root", + node_path_absolute.get_name(0) == "root", "The returned name at index 0 should match the expected value."); CHECK_MESSAGE( - node_path_aboslute.get_name(1) == "Sprite2D", + node_path_absolute.get_name(1) == "Sprite2D", "The returned name at index 1 should match the expected value."); ERR_PRINT_OFF; CHECK_MESSAGE( - node_path_aboslute.get_name(2) == "", + node_path_absolute.get_name(2) == "", "The returned name at invalid index 2 should match the expected value."); CHECK_MESSAGE( - node_path_aboslute.get_name(-1) == "", + node_path_absolute.get_name(-1) == "", "The returned name at invalid index -1 should match the expected value."); ERR_PRINT_ON; CHECK_MESSAGE( - node_path_aboslute.get_name_count() == 2, + node_path_absolute.get_name_count() == 2, "The returned number of names should match the expected value."); CHECK_MESSAGE( - node_path_aboslute.get_subname_count() == 0, + node_path_absolute.get_subname_count() == 0, "The returned number of subnames should match the expected value."); CHECK_MESSAGE( - node_path_aboslute.is_absolute(), + node_path_absolute.is_absolute(), "The node path should be considered absolute."); CHECK_MESSAGE( - !node_path_aboslute.is_empty(), + !node_path_absolute.is_empty(), "The node path shouldn't be considered empty."); } diff --git a/tests/core/variant/test_array.h b/tests/core/variant/test_array.h index 228d77b3b5..ea61ae2a02 100644 --- a/tests/core/variant/test_array.h +++ b/tests/core/variant/test_array.h @@ -367,7 +367,7 @@ TEST_CASE("[Array] Duplicate recursive array") { Array a_shallow = a.duplicate(false); CHECK_EQ(a, a_shallow); - // Deep copy of recursive array endup with recursion limit and return + // Deep copy of recursive array ends up with recursion limit and return // an invalid result (multiple nested arrays), the point is we should // not end up with a segfault and an error log should be printed ERR_PRINT_OFF; diff --git a/tests/scene/test_audio_stream_wav.h b/tests/scene/test_audio_stream_wav.h index e36f049136..ed1697929e 100644 --- a/tests/scene/test_audio_stream_wav.h +++ b/tests/scene/test_audio_stream_wav.h @@ -148,7 +148,7 @@ void run_test(String file_name, AudioStreamWAV::Format data_format, bool stereo, Ref<FileAccess> wav_file = FileAccess::open(save_path, FileAccess::READ, &error); REQUIRE(error == OK); -#if TOOLS_ENABLED +#ifdef TOOLS_ENABLED // The WAV importer can be used if enabled to check that the saved file is valid. Ref<ResourceImporterWAV> wav_importer = memnew(ResourceImporterWAV); diff --git a/tests/scene/test_curve_2d.h b/tests/scene/test_curve_2d.h index fc141f3d09..099f6fefa9 100644 --- a/tests/scene/test_curve_2d.h +++ b/tests/scene/test_curve_2d.h @@ -155,17 +155,37 @@ TEST_CASE("[Curve2D] Sampling") { SUBCASE("sample_baked_with_rotation") { const real_t pi = 3.14159; - Transform2D t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 0))); - CHECK(t.get_origin() == Vector2(0, 0)); - CHECK(Math::is_equal_approx(t.get_rotation(), pi)); - - t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 25))); + const real_t half_pi = pi * 0.5; + Ref<Curve2D> rot_curve = memnew(Curve2D); + Transform2D t; + + rot_curve->clear_points(); + rot_curve->add_point(Vector2()); + rot_curve->add_point(Vector2(50, 0)); + t = rot_curve->sample_baked_with_rotation(25); + CHECK(t.get_origin() == Vector2(25, 0)); + CHECK(Math::is_equal_approx(t.get_rotation(), 0)); + + rot_curve->clear_points(); + rot_curve->add_point(Vector2()); + rot_curve->add_point(Vector2(0, 50)); + t = rot_curve->sample_baked_with_rotation(25); CHECK(t.get_origin() == Vector2(0, 25)); - CHECK(Math::is_equal_approx(t.get_rotation(), pi)); + CHECK(Math::is_equal_approx(t.get_rotation(), half_pi)); - t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 50))); - CHECK(t.get_origin() == Vector2(0, 50)); + rot_curve->clear_points(); + rot_curve->add_point(Vector2()); + rot_curve->add_point(Vector2(-50, 0)); + t = rot_curve->sample_baked_with_rotation(25); + CHECK(t.get_origin() == Vector2(-25, 0)); CHECK(Math::is_equal_approx(t.get_rotation(), pi)); + + rot_curve->clear_points(); + rot_curve->add_point(Vector2()); + rot_curve->add_point(Vector2(0, -50)); + t = rot_curve->sample_baked_with_rotation(25); + CHECK(t.get_origin() == Vector2(0, -25)); + CHECK(Math::is_equal_approx(t.get_rotation(), -half_pi)); } SUBCASE("get_closest_point") { diff --git a/tests/scene/test_packed_scene.h b/tests/scene/test_packed_scene.h index 3517aba31f..1e784c199d 100644 --- a/tests/scene/test_packed_scene.h +++ b/tests/scene/test_packed_scene.h @@ -150,6 +150,71 @@ TEST_CASE("[PackedScene] Instantiate Packed Scene With Children") { memdelete(instance); } +TEST_CASE("[PackedScene] Set Path") { + // Create a scene to pack. + Node *scene = memnew(Node); + scene->set_name("TestScene"); + + // Pack the scene. + PackedScene packed_scene; + packed_scene.pack(scene); + + // Set a new path for the packed scene. + const String new_path = "NewTestPath"; + packed_scene.set_path(new_path); + + // Check if the path has been set correctly. + Ref<SceneState> state = packed_scene.get_state(); + CHECK(state.is_valid()); + CHECK(state->get_path() == new_path); + + memdelete(scene); +} + +TEST_CASE("[PackedScene] Replace State") { + // Create a scene to pack. + Node *scene = memnew(Node); + scene->set_name("TestScene"); + + // Pack the scene. + PackedScene packed_scene; + packed_scene.pack(scene); + + // Create another scene state to replace with. + Ref<SceneState> new_state = memnew(SceneState); + new_state->set_path("NewPath"); + + // Replace the state. + packed_scene.replace_state(new_state); + + // Check if the state has been replaced. + Ref<SceneState> state = packed_scene.get_state(); + CHECK(state.is_valid()); + CHECK(state == new_state); + + memdelete(scene); +} + +TEST_CASE("[PackedScene] Recreate State") { + // Create a scene to pack. + Node *scene = memnew(Node); + scene->set_name("TestScene"); + + // Pack the scene. + PackedScene packed_scene; + packed_scene.pack(scene); + + // Recreate the state. + packed_scene.recreate_state(); + + // Check if the state has been recreated. + Ref<SceneState> state = packed_scene.get_state(); + CHECK(state.is_valid()); + CHECK(state->get_node_count() == 0); // Since the state was recreated, it should be empty. + + memdelete(scene); +} + } // namespace TestPackedScene #endif // TEST_PACKED_SCENE_H diff --git a/tests/servers/test_text_server.h b/tests/servers/test_text_server.h index 0f23929e1e..334c642d26 100644 --- a/tests/servers/test_text_server.h +++ b/tests/servers/test_text_server.h @@ -33,7 +33,7 @@ #ifdef TOOLS_ENABLED -#include "editor/builtin_fonts.gen.h" +#include "editor/themes/builtin_fonts.gen.h" #include "servers/text_server.h" #include "tests/test_macros.h" diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 5187ebd00f..7f49805274 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -30,6 +30,8 @@ #include "test_main.h" +#include "editor/editor_paths.h" +#include "editor/editor_settings.h" #include "tests/core/config/test_project_settings.h" #include "tests/core/input/test_input_event.h" #include "tests/core/input/test_input_event_key.h" @@ -94,7 +96,6 @@ #include "tests/scene/test_arraymesh.h" #include "tests/scene/test_audio_stream_wav.h" #include "tests/scene/test_bit_map.h" -#include "tests/scene/test_camera_3d.h" #include "tests/scene/test_code_edit.h" #include "tests/scene/test_color_picker.h" #include "tests/scene/test_control.h" @@ -103,16 +104,12 @@ #include "tests/scene/test_curve_3d.h" #include "tests/scene/test_gradient.h" #include "tests/scene/test_navigation_agent_2d.h" -#include "tests/scene/test_navigation_agent_3d.h" #include "tests/scene/test_navigation_obstacle_2d.h" -#include "tests/scene/test_navigation_obstacle_3d.h" #include "tests/scene/test_navigation_region_2d.h" -#include "tests/scene/test_navigation_region_3d.h" #include "tests/scene/test_node.h" #include "tests/scene/test_node_2d.h" #include "tests/scene/test_packed_scene.h" #include "tests/scene/test_path_2d.h" -#include "tests/scene/test_path_3d.h" #include "tests/scene/test_primitives.h" #include "tests/scene/test_sprite_frames.h" #include "tests/scene/test_text_edit.h" @@ -122,10 +119,18 @@ #include "tests/scene/test_window.h" #include "tests/servers/rendering/test_shader_preprocessor.h" #include "tests/servers/test_navigation_server_2d.h" -#include "tests/servers/test_navigation_server_3d.h" #include "tests/servers/test_text_server.h" #include "tests/test_validate_testing.h" +#ifndef _3D_DISABLED +#include "tests/scene/test_camera_3d.h" +#include "tests/scene/test_navigation_agent_3d.h" +#include "tests/scene/test_navigation_obstacle_3d.h" +#include "tests/scene/test_navigation_region_3d.h" +#include "tests/scene/test_path_3d.h" +#include "tests/servers/test_navigation_server_3d.h" +#endif // _3D_DISABLED + #include "modules/modules_tests.gen.h" #include "tests/display_server_mock.h" @@ -221,7 +226,7 @@ struct GodotTestCaseListener : public doctest::IReporter { String name = String(p_in.m_name); String suite_name = String(p_in.m_test_suite); - if (name.find("[SceneTree]") != -1) { + if (name.find("[SceneTree]") != -1 || name.find("[Editor]") != -1) { memnew(MessageQueue); memnew(Input); @@ -264,6 +269,13 @@ struct GodotTestCaseListener : public doctest::IReporter { if (!DisplayServer::get_singleton()->has_feature(DisplayServer::Feature::FEATURE_SUBWINDOWS)) { SceneTree::get_singleton()->get_root()->set_embedding_subwindows(true); } + + if (name.find("[Editor]") != -1) { + Engine::get_singleton()->set_editor_hint(true); + EditorPaths::create(); + EditorSettings::create(); + } + return; } @@ -286,6 +298,12 @@ struct GodotTestCaseListener : public doctest::IReporter { } void test_case_end(const doctest::CurrentTestCaseStats &) override { + if (EditorSettings::get_singleton()) { + EditorSettings::destroy(); + } + + Engine::get_singleton()->set_editor_hint(false); + if (SceneTree::get_singleton()) { SceneTree::get_singleton()->finalize(); } diff --git a/thirdparty/README.md b/thirdparty/README.md index 00d8820605..666e53375c 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -342,7 +342,7 @@ See the patches in the `patches` directory. ## glslang - Upstream: https://github.com/KhronosGroup/glslang -- Version: sdk-1.3.261.1 (76b52ebf77833908dc4c0dd6c70a9c357ac720bd, 2023) +- Version: vulkan-sdk-1.3.268.0 (36d08c0d940cf307a23928299ef52c7970d8cee6, 2023) - License: glslang Version should be kept in sync with the one of the used Vulkan SDK (see `vulkan` @@ -389,7 +389,7 @@ Files extracted from upstream source: ## icu4c - Upstream: https://github.com/unicode-org/icu -- Version: 73.2 (680f521746a3bd6a86f25f25ee50a62d88b489cf, 2023) +- Version: 74.1 (9edac7b78327a1cb58db29e2714b15f9fa14e4d7, 2023) - License: Unicode Files extracted from upstream source: @@ -401,7 +401,7 @@ Files extracted from upstream source: Files generated from upstream source: -- The `icudt73l.dat` built with the provided `godot_data.json` config file (see +- The `icudt74l.dat` built with the provided `godot_data.json` config file (see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md for instructions). @@ -411,7 +411,7 @@ Files generated from upstream source: 3. Reconfigure ICU with custom data config: `ICU_DATA_FILTER_FILE={GODOT_SOURCE}/thirdparty/icu4c/godot_data.json ./runConfigureICU {PLATFORM} --with-data-packaging=common` 4. Delete `data/out` folder and rebuild data: `cd data && rm -rf ./out && make` -5. Copy `source/data/out/icudt73l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt73l.dat` +5. Copy `source/data/out/icudt74l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt74l.dat` ## jpeg-compressor @@ -727,7 +727,7 @@ with the provided patch. ## openxr - Upstream: https://github.com/KhronosGroup/OpenXR-SDK -- Version: 1.0.31 (95fe35ffb383710a6e0567e958ead9a3b66e930c, 2023) +- Version: 1.0.33 (dc1e23937fe45eabcce80f6588cf47449edb29d1, 2024) - License: Apache 2.0 Files extracted from upstream source: @@ -811,7 +811,7 @@ proposed by these libraries and better integrate them with Godot. ## spirv-reflect - Upstream: https://github.com/KhronosGroup/SPIRV-Reflect -- Version: sdk-1.3.261.1 (d7e316e7d592d16ac58f1fe39b1df7babfe65c0d, 2023) +- Version: vulkan-sdk-1.3.268.0 (3f468129720eded0cef4077302e491036d099856, 2023) - License: Apache 2.0 Version should be kept in sync with the one of the used Vulkan SDK (see `vulkan` @@ -861,7 +861,7 @@ instead of `miniz.h` as an external dependency. ## thorvg - Upstream: https://github.com/thorvg/thorvg -- Version: 0.11.2 (b01fe9bf4461146304d3520d6dc699cf580a3744, 2023) +- Version: 0.12.1 (d761e3c5622c0ffba2e5bb40da05751e2451e495, 2024) - License: MIT Files extracted from upstream source: @@ -890,7 +890,7 @@ folder. ## volk - Upstream: https://github.com/zeux/volk -- Version: sdk-1.3.261.1 (c1fc502109e539078d53c90ee1da9f32abbb0054, 2023) +- Version: vulkan-sdk-1.3.268.0 (cdd08788bb7062031606d3da51e268f6bd491864, 2023) - License: MIT Unless there is a specific reason to package a more recent version, please stick @@ -909,7 +909,7 @@ Files extracted from upstream source: ## vulkan - Upstream: https://github.com/KhronosGroup/Vulkan-Headers -- Version: sdk-1.3.261.1 (85c2334e92e215cce34e8e0ed8b2dce4700f4a50, 2023) +- Version: vulkan-sdk-1.3.268.0 (7b3466a1f47a9251ac1113efbe022ff016e2f95b, 2023) - License: Apache 2.0 The vendored version should be kept in sync with volk, see above. @@ -919,8 +919,8 @@ Files extracted from upstream source: - `include/` - `LICENSE.md` -`vk_enum_string_helper.h` is taken from the matching `Vulkan-ValidationLayers` -SDK release: https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/layers/vulkan/generated/vk_enum_string_helper.h +`vk_enum_string_helper.h` is taken from the matching `Vulkan-Utility-Libraries` +SDK release: https://github.com/KhronosGroup/Vulkan-Utility-Libraries/blob/main/include/vulkan/vk_enum_string_helper.h `vk_mem_alloc.h` is taken from https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator Version: git (e88fff957b94f4b541ccac67a4290f07e52aa610), as advised by upstream: diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl index 65cc8b67ef..d989416eb3 100644 --- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl +++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl @@ -29,7 +29,6 @@ #define FSR2_BIND_SRV_DILATED_DEPTH 2 #define FSR2_BIND_SRV_REACTIVE_MASK 3 #define FSR2_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK 4 -#define FSR2_BIND_SRV_PREPARED_INPUT_COLOR 5 #define FSR2_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS 6 #define FSR2_BIND_SRV_INPUT_MOTION_VECTORS 7 #define FSR2_BIND_SRV_INPUT_COLOR 8 diff --git a/thirdparty/glslang/SPIRV/GLSL.ext.NV.h b/thirdparty/glslang/SPIRV/GLSL.ext.NV.h index 5b0f7eb17e..9889bc9f9b 100644 --- a/thirdparty/glslang/SPIRV/GLSL.ext.NV.h +++ b/thirdparty/glslang/SPIRV/GLSL.ext.NV.h @@ -84,4 +84,7 @@ const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; //SPV_NV_shader_execution_reorder const char* const E_SPV_NV_shader_invocation_reorder = "SPV_NV_shader_invocation_reorder"; +//SPV_NV_displacement_micromap +const char* const E_SPV_NV_displacement_micromap = "SPV_NV_displacement_micromap"; + #endif // #ifndef GLSLextNV_H diff --git a/thirdparty/glslang/SPIRV/GLSL.ext.QCOM.h b/thirdparty/glslang/SPIRV/GLSL.ext.QCOM.h new file mode 100644 index 0000000000..f13bb69359 --- /dev/null +++ b/thirdparty/glslang/SPIRV/GLSL.ext.QCOM.h @@ -0,0 +1,41 @@ +/* +** Copyright (c) 2021 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are 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 Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE 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 MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextQCOM_H +#define GLSLextQCOM_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextQCOMVersion = 100; +static const int GLSLextQCOMRevision = 1; + +//SPV_QCOM_image_processing +const char* const E_SPV_QCOM_image_processing = "SPV_QCOM_image_processing"; + +#endif // #ifndef GLSLextQCOM_H diff --git a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp index a3047cbd48..576c680f96 100755 --- a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp +++ b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp @@ -50,6 +50,7 @@ namespace spv { #include "GLSL.ext.AMD.h" #include "GLSL.ext.NV.h" #include "GLSL.ext.ARM.h" + #include "GLSL.ext.QCOM.h" #include "NonSemanticDebugPrintf.h" } @@ -132,7 +133,7 @@ public: bool visitLoop(glslang::TVisit, glslang::TIntermLoop*); bool visitBranch(glslang::TVisit visit, glslang::TIntermBranch*); - void finishSpv(); + void finishSpv(bool compileOnly); void dumpSpv(std::vector<unsigned int>& out); protected: @@ -166,6 +167,7 @@ protected: bool filterMember(const glslang::TType& member); spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, const glslang::TQualifier&); + spv::LinkageType convertGlslangLinkageToSpv(glslang::TLinkType glslangLinkType); void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, const glslang::TQualifier&, spv::Id, const std::vector<spv::Id>& spvMembers); spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim, bool allowZero = false); @@ -220,6 +222,7 @@ protected: spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId); spv::Id getSymbolId(const glslang::TIntermSymbol* node); void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier); + void addImageProcessingQCOMDecoration(spv::Id id, spv::Decoration decor); spv::Id createSpvConstant(const glslang::TIntermTyped&); spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); @@ -1006,6 +1009,22 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI builder.addExtension(spv::E_SPV_NV_ray_tracing_motion_blur); builder.addCapability(spv::CapabilityRayTracingMotionBlurNV); return spv::BuiltInCurrentRayTimeNV; + case glslang::EbvMicroTrianglePositionNV: + builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); + builder.addExtension("SPV_NV_displacement_micromap"); + return spv::BuiltInHitMicroTriangleVertexPositionsNV; + case glslang::EbvMicroTriangleBaryNV: + builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); + builder.addExtension("SPV_NV_displacement_micromap"); + return spv::BuiltInHitMicroTriangleVertexBarycentricsNV; + case glslang::EbvHitKindFrontFacingMicroTriangleNV: + builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); + builder.addExtension("SPV_NV_displacement_micromap"); + return spv::BuiltInHitKindFrontFacingMicroTriangleNV; + case glslang::EbvHitKindBackFacingMicroTriangleNV: + builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); + builder.addExtension("SPV_NV_displacement_micromap"); + return spv::BuiltInHitKindBackFacingMicroTriangleNV; // barycentrics case glslang::EbvBaryCoordNV: @@ -1586,8 +1605,12 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, builder.addCapability(spv::CapabilityVariablePointers); } - shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str()); - entryPoint = builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str()); + // If not linking, there is no entry point + if (!options.compileOnly) { + shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str()); + entryPoint = + builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str()); + } // Add the source extensions const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); @@ -1718,23 +1741,31 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, } break; - case EShLangCompute: + case EShLangCompute: { builder.addCapability(spv::CapabilityShader); - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - std::vector<spv::Id> dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) { - builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, - glslangIntermediate->getLocalSizeSpecId(dim)); + bool needSizeId = false; + for (int dim = 0; dim < 3; ++dim) { + if ((glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet)) { + needSizeId = true; + break; + } + } + if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6 && needSizeId) { + std::vector<spv::Id> dimConstId; + for (int dim = 0; dim < 3; ++dim) { + bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); + dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); + if (specConst) { + builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, + glslangIntermediate->getLocalSizeSpecId(dim)); + needSizeId = true; + } } - } - builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId); + builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId); } else { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), - glslangIntermediate->getLocalSize(1), - glslangIntermediate->getLocalSize(2)); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), + glslangIntermediate->getLocalSize(1), + glslangIntermediate->getLocalSize(2)); } if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) { builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV); @@ -1746,6 +1777,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); } break; + } case EShLangTessEvaluation: case EShLangTessControl: builder.addCapability(spv::CapabilityTessellation); @@ -1937,23 +1969,26 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, } // Finish creating SPV, after the traversal is complete. -void TGlslangToSpvTraverser::finishSpv() +void TGlslangToSpvTraverser::finishSpv(bool compileOnly) { - // Finish the entry point function - if (! entryPointTerminated) { - builder.setBuildPoint(shaderEntry->getLastBlock()); - builder.leaveFunction(); - } + // If not linking, an entry point is not expected + if (!compileOnly) { + // Finish the entry point function + if (!entryPointTerminated) { + builder.setBuildPoint(shaderEntry->getLastBlock()); + builder.leaveFunction(); + } - // finish off the entry-point SPV instruction by adding the Input/Output <id> - for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it) - entryPoint->addIdOperand(*it); + // finish off the entry-point SPV instruction by adding the Input/Output <id> + for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it) + entryPoint->addIdOperand(*it); + } // Add capabilities, extensions, remove unneeded decorations, etc., // based on the resulting SPIR-V. // Note: WebGPU code generation must have the opportunity to aggressively // prune unreachable merge blocks and continue targets. - builder.postProcess(); + builder.postProcess(compileOnly); } // Write the SPV into 'out'. @@ -2012,7 +2047,7 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) spv::StorageClass sc = builder.getStorageClass(id); // Before SPIR-V 1.4, we only want to include Input and Output. // Starting with SPIR-V 1.4, we want all globals. - if ((glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4 && builder.isGlobalStorage(id)) || + if ((glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4 && builder.isGlobalVariable(id)) || (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)) { iOSet.insert(id); } @@ -2838,9 +2873,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt // In all cases, still let the traverser visit the children for us. makeFunctions(node->getAsAggregate()->getSequence()); - // Also, we want all globals initializers to go into the beginning of the entry point, before - // anything else gets there, so visit out of order, doing them all now. - makeGlobalInitializers(node->getAsAggregate()->getSequence()); + // Global initializers is specific to the shader entry point, which does not exist in compile-only mode + if (!options.compileOnly) { + // Also, we want all globals initializers to go into the beginning of the entry point, before + // anything else gets there, so visit out of order, doing them all now. + makeGlobalInitializers(node->getAsAggregate()->getSequence()); + } //Pre process linker objects for ray tracing stages if (glslangIntermediate->isRayTracingStage()) @@ -3276,6 +3314,26 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt noReturnValue = true; break; + case glslang::EOpImageSampleWeightedQCOM: + builder.addCapability(spv::CapabilityTextureSampleWeightedQCOM); + builder.addExtension(spv::E_SPV_QCOM_image_processing); + break; + case glslang::EOpImageBoxFilterQCOM: + builder.addCapability(spv::CapabilityTextureBoxFilterQCOM); + builder.addExtension(spv::E_SPV_QCOM_image_processing); + break; + case glslang::EOpImageBlockMatchSADQCOM: + case glslang::EOpImageBlockMatchSSDQCOM: + builder.addCapability(spv::CapabilityTextureBlockMatchQCOM); + builder.addExtension(spv::E_SPV_QCOM_image_processing); + break; + + case glslang::EOpFetchMicroTriangleVertexPositionNV: + case glslang::EOpFetchMicroTriangleVertexBarycentricNV: + builder.addExtension(spv::E_SPV_NV_displacement_micromap); + builder.addCapability(spv::CapabilityDisplacementMicromapNV); + break; + case glslang::EOpDebugPrintf: noReturnValue = true; break; @@ -3640,7 +3698,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt spv::Id typeId = builder.makeArrayType(builder.makeVectorType(builder.makeFloatType(32), 3), builder.makeUintConstant(3), 0); // do the op - spv::Id result = builder.createOp(spv::OpRayQueryGetIntersectionTriangleVertexPositionsKHR, typeId, idImmOps); + + spv::Op spvOp = spv::OpRayQueryGetIntersectionTriangleVertexPositionsKHR; + + spv::Id result = builder.createOp(spvOp, typeId, idImmOps); // store the result to the pointer (out param 'm') builder.createStore(result, operands[2]); result = 0; @@ -4313,6 +4374,16 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier(), false, forwardReferenceOnly); } +spv::LinkageType TGlslangToSpvTraverser::convertGlslangLinkageToSpv(glslang::TLinkType linkType) +{ + switch (linkType) { + case glslang::ELinkExport: + return spv::LinkageTypeExport; + default: + return spv::LinkageTypeMax; + } +} + // Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id. // explicitLayout can be kept the same throughout the hierarchical recursive walk. // Mutually recursive with convertGlslangStructToSpvType(). @@ -4476,26 +4547,27 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty std::vector<spv::IdImmediate> operands; for (const auto& typeParam : spirvType.typeParams) { - if (typeParam.constant != nullptr) { + if (typeParam.getAsConstant() != nullptr) { // Constant expression - if (typeParam.constant->isLiteral()) { - if (typeParam.constant->getBasicType() == glslang::EbtFloat) { - float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst()); + auto constant = typeParam.getAsConstant(); + if (constant->isLiteral()) { + if (constant->getBasicType() == glslang::EbtFloat) { + float floatValue = static_cast<float>(constant->getConstArray()[0].getDConst()); unsigned literal; static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)"); memcpy(&literal, &floatValue, sizeof(literal)); operands.push_back({false, literal}); - } else if (typeParam.constant->getBasicType() == glslang::EbtInt) { - unsigned literal = typeParam.constant->getConstArray()[0].getIConst(); + } else if (constant->getBasicType() == glslang::EbtInt) { + unsigned literal = constant->getConstArray()[0].getIConst(); operands.push_back({false, literal}); - } else if (typeParam.constant->getBasicType() == glslang::EbtUint) { - unsigned literal = typeParam.constant->getConstArray()[0].getUConst(); + } else if (constant->getBasicType() == glslang::EbtUint) { + unsigned literal = constant->getConstArray()[0].getUConst(); operands.push_back({false, literal}); - } else if (typeParam.constant->getBasicType() == glslang::EbtBool) { - unsigned literal = typeParam.constant->getConstArray()[0].getBConst(); + } else if (constant->getBasicType() == glslang::EbtBool) { + unsigned literal = constant->getConstArray()[0].getBConst(); operands.push_back({false, literal}); - } else if (typeParam.constant->getBasicType() == glslang::EbtString) { - auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str(); + } else if (constant->getBasicType() == glslang::EbtString) { + auto str = constant->getConstArray()[0].getSConst()->c_str(); unsigned literal = 0; char* literalPtr = reinterpret_cast<char*>(&literal); unsigned charCount = 0; @@ -4520,11 +4592,11 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty } else assert(0); // Unexpected type } else - operands.push_back({true, createSpvConstant(*typeParam.constant)}); + operands.push_back({true, createSpvConstant(*constant)}); } else { // Type specifier - assert(typeParam.type != nullptr); - operands.push_back({true, convertGlslangToSpvType(*typeParam.type)}); + assert(typeParam.getAsType() != nullptr); + operands.push_back({true, convertGlslangToSpvType(*typeParam.getAsType())}); } } @@ -5379,10 +5451,10 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF } spv::Block* functionBlock; - spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()), - convertGlslangToSpvType(glslFunction->getType()), - glslFunction->getName().c_str(), paramTypes, paramNames, - paramDecorations, &functionBlock); + spv::Function* function = builder.makeFunctionEntry( + TranslatePrecisionDecoration(glslFunction->getType()), convertGlslangToSpvType(glslFunction->getType()), + glslFunction->getName().c_str(), convertGlslangLinkageToSpv(glslFunction->getLinkType()), paramTypes, + paramNames, paramDecorations, &functionBlock); if (implicitThis) function->setImplicitThis(); @@ -7161,6 +7233,14 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe unaryOp = spv::OpHitObjectGetShaderRecordBufferHandleNV; break; + case glslang::EOpFetchMicroTriangleVertexPositionNV: + unaryOp = spv::OpFetchMicroTriangleVertexPositionNV; + break; + + case glslang::EOpFetchMicroTriangleVertexBarycentricNV: + unaryOp = spv::OpFetchMicroTriangleVertexBarycentricNV; + break; + case glslang::EOpCopyObject: unaryOp = spv::OpCopyObject; break; @@ -9023,7 +9103,39 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: return 0; } + + case glslang::EOpImageSampleWeightedQCOM: + typeId = builder.makeVectorType(builder.makeFloatType(32), 4); + opCode = spv::OpImageSampleWeightedQCOM; + addImageProcessingQCOMDecoration(operands[2], spv::DecorationWeightTextureQCOM); + break; + case glslang::EOpImageBoxFilterQCOM: + typeId = builder.makeVectorType(builder.makeFloatType(32), 4); + opCode = spv::OpImageBoxFilterQCOM; + break; + case glslang::EOpImageBlockMatchSADQCOM: + typeId = builder.makeVectorType(builder.makeFloatType(32), 4); + opCode = spv::OpImageBlockMatchSADQCOM; + addImageProcessingQCOMDecoration(operands[0], spv::DecorationBlockMatchTextureQCOM); + addImageProcessingQCOMDecoration(operands[2], spv::DecorationBlockMatchTextureQCOM); + break; + case glslang::EOpImageBlockMatchSSDQCOM: + typeId = builder.makeVectorType(builder.makeFloatType(32), 4); + opCode = spv::OpImageBlockMatchSSDQCOM; + addImageProcessingQCOMDecoration(operands[0], spv::DecorationBlockMatchTextureQCOM); + addImageProcessingQCOMDecoration(operands[2], spv::DecorationBlockMatchTextureQCOM); + break; + + case glslang::EOpFetchMicroTriangleVertexBarycentricNV: + typeId = builder.makeVectorType(builder.makeFloatType(32), 2); + opCode = spv::OpFetchMicroTriangleVertexBarycentricNV; break; + + case glslang::EOpFetchMicroTriangleVertexPositionNV: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpFetchMicroTriangleVertexPositionNV; + break; + default: return 0; } @@ -9568,6 +9680,20 @@ void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const g } } +void TGlslangToSpvTraverser::addImageProcessingQCOMDecoration(spv::Id id, spv::Decoration decor) +{ + spv::Op opc = builder.getOpCode(id); + if (opc == spv::OpSampledImage) { + id = builder.getIdOperand(id, 0); + opc = builder.getOpCode(id); + } + + if (opc == spv::OpLoad) { + spv::Id texid = builder.getIdOperand(id, 0); + builder.addDecoration(texid, decor); + } +} + // Make a full tree of instructions to build a SPIR-V specialization constant, // or regular constant if possible. // @@ -10050,7 +10176,7 @@ void GlslangToSpv(const TIntermediate& intermediate, std::vector<unsigned int>& TGlslangToSpvTraverser it(intermediate.getSpv().spv, &intermediate, logger, *options); root->traverse(&it); - it.finishSpv(); + it.finishSpv(options->compileOnly); it.dumpSpv(spirv); #if ENABLE_OPT diff --git a/thirdparty/glslang/SPIRV/SpvBuilder.cpp b/thirdparty/glslang/SPIRV/SpvBuilder.cpp index 57e03d5d6b..d42f728816 100644 --- a/thirdparty/glslang/SPIRV/SpvBuilder.cpp +++ b/thirdparty/glslang/SPIRV/SpvBuilder.cpp @@ -859,11 +859,19 @@ Id Builder::makeBoolDebugType(int const size) Id Builder::makeIntegerDebugType(int const width, bool const hasSign) { + const char* typeName = nullptr; + switch (width) { + case 8: typeName = hasSign ? "int8_t" : "uint8_t"; break; + case 16: typeName = hasSign ? "int16_t" : "uint16_t"; break; + case 64: typeName = hasSign ? "int64_t" : "uint64_t"; break; + default: typeName = hasSign ? "int" : "uint"; + } + auto nameId = getStringId(typeName); // try to find it Instruction* type; for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; - if (type->getIdOperand(0) == (hasSign ? getStringId("int") : getStringId("uint")) && + if (type->getIdOperand(0) == nameId && type->getIdOperand(1) == static_cast<unsigned int>(width) && type->getIdOperand(2) == (hasSign ? NonSemanticShaderDebugInfo100Signed : NonSemanticShaderDebugInfo100Unsigned)) return type->getResultId(); @@ -873,11 +881,7 @@ Id Builder::makeIntegerDebugType(int const width, bool const hasSign) type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); type->addIdOperand(nonSemanticShaderDebugInfo); type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); - if(hasSign == true) { - type->addIdOperand(getStringId("int")); // name id - } else { - type->addIdOperand(getStringId("uint")); // name id - } + type->addIdOperand(nameId); // name id type->addIdOperand(makeUintConstant(width)); // size id if(hasSign == true) { type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Signed)); // encoding id @@ -895,11 +899,18 @@ Id Builder::makeIntegerDebugType(int const width, bool const hasSign) Id Builder::makeFloatDebugType(int const width) { + const char* typeName = nullptr; + switch (width) { + case 16: typeName = "float16_t"; break; + case 64: typeName = "double"; break; + default: typeName = "float"; break; + } + auto nameId = getStringId(typeName); // try to find it Instruction* type; for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; - if (type->getIdOperand(0) == getStringId("float") && + if (type->getIdOperand(0) == nameId && type->getIdOperand(1) == static_cast<unsigned int>(width) && type->getIdOperand(2) == NonSemanticShaderDebugInfo100Float) return type->getResultId(); @@ -909,7 +920,7 @@ Id Builder::makeFloatDebugType(int const width) type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); type->addIdOperand(nonSemanticShaderDebugInfo); type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); - type->addIdOperand(getStringId("float")); // name id + type->addIdOperand(nameId); // name id type->addIdOperand(makeUintConstant(width)); // size id type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Float)); // encoding id type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id @@ -1018,7 +1029,10 @@ Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char cons for(auto const memberType : memberTypes) { assert(debugTypeLocs.find(memberType) != debugTypeLocs.end()); - memberDebugTypes.emplace_back(makeMemberDebugType(memberType, debugTypeLocs[memberType])); + // There _should_ be debug types for all the member types but currently buffer references + // do not have member debug info generated. + if (debugId[memberType]) + memberDebugTypes.emplace_back(makeMemberDebugType(memberType, debugTypeLocs[memberType])); // TODO: Need to rethink this method of passing location information. // debugTypeLocs.erase(memberType); @@ -1824,6 +1838,10 @@ Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, co // Currently relying on the fact that all 'value' of interest are small non-negative values. void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3) { + // entryPoint can be null if we are in compile-only mode + if (!entryPoint) + return; + Instruction* instr = new Instruction(OpExecutionMode); instr->addIdOperand(entryPoint->getId()); instr->addImmediateOperand(mode); @@ -1839,6 +1857,10 @@ void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int val void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector<unsigned>& literals) { + // entryPoint can be null if we are in compile-only mode + if (!entryPoint) + return; + Instruction* instr = new Instruction(OpExecutionMode); instr->addIdOperand(entryPoint->getId()); instr->addImmediateOperand(mode); @@ -1850,6 +1872,10 @@ void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const s void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector<Id>& operandIds) { + // entryPoint can be null if we are in compile-only mode + if (!entryPoint) + return; + Instruction* instr = new Instruction(OpExecutionModeId); instr->addIdOperand(entryPoint->getId()); instr->addImmediateOperand(mode); @@ -1933,6 +1959,16 @@ void Builder::addDecoration(Id id, Decoration decoration, const std::vector<cons decorations.push_back(std::unique_ptr<Instruction>(dec)); } +void Builder::addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType) { + Instruction* dec = new Instruction(OpDecorate); + dec->addIdOperand(id); + dec->addImmediateOperand(spv::DecorationLinkageAttributes); + dec->addStringOperand(name); + dec->addImmediateOperand(linkType); + + decorations.push_back(std::unique_ptr<Instruction>(dec)); +} + void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration) { if (decoration == spv::DecorationMax) @@ -2037,7 +2073,7 @@ Function* Builder::makeEntryPoint(const char* entryPoint) emitNonSemanticShaderDebugInfo = false; } - entryPointFunction = makeFunctionEntry(NoPrecision, returnType, entryPoint, paramsTypes, paramNames, decorations, &entry); + entryPointFunction = makeFunctionEntry(NoPrecision, returnType, entryPoint, LinkageTypeMax, paramsTypes, paramNames, decorations, &entry); emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo; @@ -2045,7 +2081,7 @@ Function* Builder::makeEntryPoint(const char* entryPoint) } // Comments in header -Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, +Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType, const std::vector<Id>& paramTypes, const std::vector<char const*>& paramNames, const std::vector<std::vector<Decoration>>& decorations, Block **entry) { @@ -2053,7 +2089,7 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const Id typeId = makeFunctionType(returnType, paramTypes); Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size()); Id funcId = getUniqueId(); - Function* function = new Function(funcId, returnType, typeId, firstParamId, module); + Function* function = new Function(funcId, returnType, typeId, firstParamId, linkType, name, module); // Set up the precisions setPrecision(function->getId(), precision); @@ -2223,6 +2259,12 @@ void Builder::enterFunction(Function const* function) defInst->addIdOperand(funcId); buildPoint->addInstruction(std::unique_ptr<Instruction>(defInst)); } + + if (auto linkType = function->getLinkType(); linkType != LinkageTypeMax) { + Id funcId = function->getFuncId(); + addCapability(CapabilityLinkage); + addLinkageDecoration(funcId, function->getExportName(), linkType); + } } // Comments in header diff --git a/thirdparty/glslang/SPIRV/SpvBuilder.h b/thirdparty/glslang/SPIRV/SpvBuilder.h index 1f38e7899d..2e1c07d49d 100644 --- a/thirdparty/glslang/SPIRV/SpvBuilder.h +++ b/thirdparty/glslang/SPIRV/SpvBuilder.h @@ -261,6 +261,7 @@ public: ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } Id getResultingAccessChainType() const; + Id getIdOperand(Id resultId, int idx) { return module.getInstruction(resultId)->getIdOperand(idx); } bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } @@ -392,6 +393,7 @@ public: void addDecoration(Id, Decoration, const char*); void addDecoration(Id, Decoration, const std::vector<unsigned>& literals); void addDecoration(Id, Decoration, const std::vector<const char*>& strings); + void addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType); void addDecorationId(Id id, Decoration, Id idDecoration); void addDecorationId(Id id, Decoration, const std::vector<Id>& operandIds); void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); @@ -416,7 +418,8 @@ public: // Return the function, pass back the entry. // The returned pointer is only valid for the lifetime of this builder. Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, - const std::vector<Id>& paramTypes, const std::vector<char const*>& paramNames, + LinkageType linkType, const std::vector<Id>& paramTypes, + const std::vector<char const*>& paramNames, const std::vector<std::vector<Decoration>>& precisions, Block **entry = nullptr); // Create a return. An 'implicit' return is one not appearing in the source @@ -827,7 +830,7 @@ public: // Add capabilities, extensions, remove unneeded decorations, etc., // based on the resulting SPIR-V. - void postProcess(); + void postProcess(bool compileOnly); // Prune unreachable blocks in the CFG and remove unneeded decorations. void postProcessCFG(); diff --git a/thirdparty/glslang/SPIRV/SpvPostProcess.cpp b/thirdparty/glslang/SPIRV/SpvPostProcess.cpp index c4be365527..13001a67a1 100644 --- a/thirdparty/glslang/SPIRV/SpvPostProcess.cpp +++ b/thirdparty/glslang/SPIRV/SpvPostProcess.cpp @@ -53,6 +53,7 @@ namespace spv { #include "GLSL.ext.AMD.h" #include "GLSL.ext.NV.h" #include "GLSL.ext.ARM.h" + #include "GLSL.ext.QCOM.h" } namespace spv { @@ -482,9 +483,13 @@ void Builder::postProcessFeatures() { } // comment in header -void Builder::postProcess() { - postProcessCFG(); - postProcessFeatures(); +void Builder::postProcess(bool compileOnly) +{ + // postProcessCFG needs an entrypoint to determine what is reachable, but if we are not creating an "executable" shader, we don't have an entrypoint + if (!compileOnly) + postProcessCFG(); + + postProcessFeatures(); } }; // end spv namespace diff --git a/thirdparty/glslang/SPIRV/SpvTools.h b/thirdparty/glslang/SPIRV/SpvTools.h index 6fc4e40b02..a4ce11b887 100644 --- a/thirdparty/glslang/SPIRV/SpvTools.h +++ b/thirdparty/glslang/SPIRV/SpvTools.h @@ -61,6 +61,7 @@ struct SpvOptions { bool validate {false}; bool emitNonSemanticShaderDebugInfo {false}; bool emitNonSemanticShaderDebugSource{ false }; + bool compileOnly{false}; }; #if ENABLE_OPT diff --git a/thirdparty/glslang/SPIRV/disassemble.cpp b/thirdparty/glslang/SPIRV/disassemble.cpp index 479f4a64eb..c5e961cf02 100644 --- a/thirdparty/glslang/SPIRV/disassemble.cpp +++ b/thirdparty/glslang/SPIRV/disassemble.cpp @@ -56,6 +56,7 @@ namespace spv { #include "GLSL.ext.NV.h" #include "GLSL.ext.ARM.h" #include "NonSemanticShaderDebugInfo100.h" + #include "GLSL.ext.QCOM.h" } } const char* GlslStd450DebugNames[spv::GLSLstd450Count]; diff --git a/thirdparty/glslang/SPIRV/doc.cpp b/thirdparty/glslang/SPIRV/doc.cpp index b7f0053dd6..53ce9e152b 100755 --- a/thirdparty/glslang/SPIRV/doc.cpp +++ b/thirdparty/glslang/SPIRV/doc.cpp @@ -55,6 +55,7 @@ namespace spv { #include "GLSL.ext.AMD.h" #include "GLSL.ext.NV.h" #include "GLSL.ext.ARM.h" + #include "GLSL.ext.QCOM.h" } } @@ -311,7 +312,9 @@ const char* DecorationString(int decoration) case DecorationCeiling: default: return "Bad"; - case DecorationExplicitInterpAMD: return "ExplicitInterpAMD"; + case DecorationWeightTextureQCOM: return "DecorationWeightTextureQCOM"; + case DecorationBlockMatchTextureQCOM: return "DecorationBlockMatchTextureQCOM"; + case DecorationExplicitInterpAMD: return "ExplicitInterpAMD"; case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; case DecorationPassthroughNV: return "PassthroughNV"; case DecorationViewportRelativeNV: return "ViewportRelativeNV"; @@ -411,6 +414,10 @@ const char* BuiltInString(int builtIn) case BuiltInRayTmaxKHR: return "RayTmaxKHR"; case BuiltInCullMaskKHR: return "CullMaskKHR"; case BuiltInHitTriangleVertexPositionsKHR: return "HitTriangleVertexPositionsKHR"; + case BuiltInHitMicroTriangleVertexPositionsNV: return "HitMicroTriangleVertexPositionsNV"; + case BuiltInHitMicroTriangleVertexBarycentricsNV: return "HitMicroTriangleVertexBarycentricsNV"; + case BuiltInHitKindFrontFacingMicroTriangleNV: return "HitKindFrontFacingMicroTriangleNV"; + case BuiltInHitKindBackFacingMicroTriangleNV: return "HitKindBackFacingMicroTriangleNV"; case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR"; case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR"; case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR"; @@ -974,6 +981,8 @@ const char* CapabilityString(int info) case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR"; case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR"; case CapabilityRayTracingPositionFetchKHR: return "RayTracingPositionFetchKHR"; + case CapabilityDisplacementMicromapNV: return "DisplacementMicromapNV"; + case CapabilityRayTracingDisplacementMicromapNV: return "CapabilityRayTracingDisplacementMicromapNV"; case CapabilityRayQueryPositionFetchKHR: return "RayQueryPositionFetchKHR"; case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV"; case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV"; @@ -1040,6 +1049,11 @@ const char* CapabilityString(int info) case CapabilityCoreBuiltinsARM: return "CoreBuiltinsARM"; case CapabilityShaderInvocationReorderNV: return "ShaderInvocationReorderNV"; + + case CapabilityTextureSampleWeightedQCOM: return "TextureSampleWeightedQCOM"; + case CapabilityTextureBoxFilterQCOM: return "TextureBoxFilterQCOM"; + case CapabilityTextureBlockMatchQCOM: return "TextureBlockMatchQCOM"; + default: return "Bad"; } } @@ -1534,10 +1548,18 @@ const char* OpcodeString(int op) case OpHitObjectGetShaderBindingTableRecordIndexNV: return "OpHitObjectGetShaderBindingTableRecordIndexNV"; case OpHitObjectGetShaderRecordBufferHandleNV: return "OpHitObjectGetShaderRecordBufferHandleNV"; + case OpFetchMicroTriangleVertexBarycentricNV: return "OpFetchMicroTriangleVertexBarycentricNV"; + case OpFetchMicroTriangleVertexPositionNV: return "OpFetchMicroTriangleVertexPositionNV"; + case OpColorAttachmentReadEXT: return "OpColorAttachmentReadEXT"; case OpDepthAttachmentReadEXT: return "OpDepthAttachmentReadEXT"; case OpStencilAttachmentReadEXT: return "OpStencilAttachmentReadEXT"; + case OpImageSampleWeightedQCOM: return "OpImageSampleWeightedQCOM"; + case OpImageBoxFilterQCOM: return "OpImageBoxFilterQCOM"; + case OpImageBlockMatchSADQCOM: return "OpImageBlockMatchSADQCOM"; + case OpImageBlockMatchSSDQCOM: return "OpImageBlockMatchSSDQCOM"; + default: return "Bad"; } @@ -3069,7 +3091,7 @@ void Parameterize() InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].operands.push(OperandId, "'RayQuery'"); InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true); + InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].setResultAndType(true, true); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'"); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'"); @@ -3335,10 +3357,52 @@ void Parameterize() InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Payload'"); InstructionDesc[OpHitObjectTraceRayMotionNV].setResultAndType(false, false); + InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Acceleration Structure'"); + InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Instance ID'"); + InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Geometry Index'"); + InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Primitive Index'"); + InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Barycentrics'"); + InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].setResultAndType(true, true); + + InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Acceleration Structure'"); + InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Instance ID'"); + InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Geometry Index'"); + InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Primitive Index'"); + InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Barycentrics'"); + InstructionDesc[OpFetchMicroTriangleVertexPositionNV].setResultAndType(true, true); + InstructionDesc[OpColorAttachmentReadEXT].operands.push(OperandId, "'Attachment'"); InstructionDesc[OpColorAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); InstructionDesc[OpStencilAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); InstructionDesc[OpDepthAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); + + InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'source texture'"); + InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'texture coordinates'"); + InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'weights texture'"); + InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandImageOperands, "", true); + InstructionDesc[OpImageSampleWeightedQCOM].setResultAndType(true, true); + + InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'source texture'"); + InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'texture coordinates'"); + InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'box size'"); + InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandImageOperands, "", true); + InstructionDesc[OpImageBoxFilterQCOM].setResultAndType(true, true); + + InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'target texture'"); + InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'target coordinates'"); + InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'reference texture'"); + InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'reference coordinates'"); + InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'block size'"); + InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandImageOperands, "", true); + InstructionDesc[OpImageBlockMatchSADQCOM].setResultAndType(true, true); + + InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'target texture'"); + InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'target coordinates'"); + InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'reference texture'"); + InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'reference coordinates'"); + InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'block size'"); + InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandImageOperands, "", true); + InstructionDesc[OpImageBlockMatchSSDQCOM].setResultAndType(true, true); }); } diff --git a/thirdparty/glslang/SPIRV/spirv.hpp b/thirdparty/glslang/SPIRV/spirv.hpp index 4fb721ef18..02c1eded73 100644 --- a/thirdparty/glslang/SPIRV/spirv.hpp +++ b/thirdparty/glslang/SPIRV/spirv.hpp @@ -513,6 +513,8 @@ enum Decoration { DecorationMaxByteOffsetId = 47, DecorationNoSignedWrap = 4469, DecorationNoUnsignedWrap = 4470, + DecorationWeightTextureQCOM = 4487, + DecorationBlockMatchTextureQCOM = 4488, DecorationExplicitInterpAMD = 4999, DecorationOverrideCoverageNV = 5248, DecorationPassthroughNV = 5250, @@ -718,6 +720,10 @@ enum BuiltIn { BuiltInHitKindNV = 5333, BuiltInCurrentRayTimeNV = 5334, BuiltInHitTriangleVertexPositionsKHR = 5335, + BuiltInHitMicroTriangleVertexPositionsNV = 5337, + BuiltInHitMicroTriangleVertexBarycentricsNV = 5344, + BuiltInHitKindFrontFacingMicroTriangleNV = 5405, + BuiltInHitKindBackFacingMicroTriangleNV = 5406, BuiltInIncomingRayFlagsKHR = 5351, BuiltInIncomingRayFlagsNV = 5351, BuiltInRayGeometryIndexKHR = 5352, @@ -1023,6 +1029,9 @@ enum Capability { CapabilityRayQueryKHR = 4472, CapabilityRayTraversalPrimitiveCullingKHR = 4478, CapabilityRayTracingKHR = 4479, + CapabilityTextureSampleWeightedQCOM = 4484, + CapabilityTextureBoxFilterQCOM = 4485, + CapabilityTextureBlockMatchQCOM = 4486, CapabilityFloat16ImageAMD = 5008, CapabilityImageGatherBiasLodAMD = 5009, CapabilityFragmentMaskAMD = 5010, @@ -1089,6 +1098,8 @@ enum Capability { CapabilityFragmentShaderPixelInterlockEXT = 5378, CapabilityDemoteToHelperInvocation = 5379, CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilityDisplacementMicromapNV = 5380, + CapabilityRayTracingDisplacementMicromapNV = 5409, CapabilityRayTracingOpacityMicromapEXT = 5381, CapabilityShaderInvocationReorderNV = 5383, CapabilityBindlessTextureNV = 5390, @@ -1678,6 +1689,10 @@ enum Op { OpRayQueryConfirmIntersectionKHR = 4476, OpRayQueryProceedKHR = 4477, OpRayQueryGetIntersectionTypeKHR = 4479, + OpImageSampleWeightedQCOM = 4480, + OpImageBoxFilterQCOM = 4481, + OpImageBlockMatchSSDQCOM = 4482, + OpImageBlockMatchSADQCOM = 4483, OpGroupIAddNonUniformAMD = 5000, OpGroupFAddNonUniformAMD = 5001, OpGroupFMinNonUniformAMD = 5002, @@ -1727,6 +1742,8 @@ enum Op { OpSetMeshOutputsEXT = 5295, OpGroupNonUniformPartitionNV = 5296, OpWritePackedPrimitiveIndices4x8NV = 5299, + OpFetchMicroTriangleVertexPositionNV = 5300, + OpFetchMicroTriangleVertexBarycentricNV = 5301, OpReportIntersectionKHR = 5334, OpReportIntersectionNV = 5334, OpIgnoreIntersectionNV = 5335, @@ -2395,6 +2412,10 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleWeightedQCOM: *hasResult = true; *hasResultType = true; break; + case OpImageBoxFilterQCOM: *hasResult = true; *hasResultType = true; break; + case OpImageBlockMatchSSDQCOM: *hasResult = true; *hasResultType = true; break; + case OpImageBlockMatchSADQCOM: *hasResult = true; *hasResultType = true; break; case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; diff --git a/thirdparty/glslang/SPIRV/spvIR.h b/thirdparty/glslang/SPIRV/spvIR.h index 5cbffec25f..1f8e28ff46 100644 --- a/thirdparty/glslang/SPIRV/spvIR.h +++ b/thirdparty/glslang/SPIRV/spvIR.h @@ -323,7 +323,7 @@ void inReadableOrder(Block* root, std::function<void(Block*, ReachReason, Block* class Function { public: - Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + Function(Id id, Id resultType, Id functionType, Id firstParam, LinkageType linkage, const std::string& name, Module& parent); virtual ~Function() { for (int i = 0; i < (int)parameterInstructions.size(); ++i) @@ -402,6 +402,9 @@ public: end.dump(out); } + LinkageType getLinkType() const { return linkType; } + const char* getExportName() const { return exportName.c_str(); } + protected: Function(const Function&); Function& operator=(Function&); @@ -414,6 +417,8 @@ protected: bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument bool reducedPrecisionReturn; std::set<int> reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg + LinkageType linkType; + std::string exportName; }; // @@ -473,10 +478,11 @@ protected: // Add both // - the OpFunction instruction // - all the OpFunctionParameter instructions -__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, LinkageType linkage, const std::string& name, Module& parent) : parent(parent), lineInstruction(nullptr), functionInstruction(id, resultType, OpFunction), implicitThis(false), - reducedPrecisionReturn(false) + reducedPrecisionReturn(false), + linkType(linkage) { // OpFunction functionInstruction.addImmediateOperand(FunctionControlMaskNone); @@ -492,6 +498,11 @@ __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParam parent.mapInstruction(param); parameterInstructions.push_back(param); } + + // If importing/exporting, save the function name (without the mangled parameters) for the linkage decoration + if (linkType != LinkageTypeMax) { + exportName = name.substr(0, name.find_first_of('(')); + } } __inline void Function::addLocalVariable(std::unique_ptr<Instruction> inst) diff --git a/thirdparty/glslang/glslang/Include/BaseTypes.h b/thirdparty/glslang/glslang/Include/BaseTypes.h index ae49a936a1..64bffa8926 100755 --- a/thirdparty/glslang/glslang/Include/BaseTypes.h +++ b/thirdparty/glslang/glslang/Include/BaseTypes.h @@ -290,6 +290,12 @@ enum TBuiltInVariable { EbvLayerPerViewNV, EbvMeshViewCountNV, EbvMeshViewIndicesNV, + + EbvMicroTrianglePositionNV, + EbvMicroTriangleBaryNV, + EbvHitKindFrontFacingMicroTriangleNV, + EbvHitKindBackFacingMicroTriangleNV, + //GL_EXT_mesh_shader EbvPrimitivePointIndicesEXT, EbvPrimitiveLineIndicesEXT, @@ -523,6 +529,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v) case EbvShadingRateKHR: return "ShadingRateKHR"; case EbvPrimitiveShadingRateKHR: return "PrimitiveShadingRateKHR"; + case EbvHitKindFrontFacingMicroTriangleNV: return "HitKindFrontFacingMicroTriangleNV"; + case EbvHitKindBackFacingMicroTriangleNV: return "HitKindBackFacingMicroTriangleNV"; + default: return "unknown built-in variable"; } } diff --git a/thirdparty/glslang/glslang/Include/PoolAlloc.h b/thirdparty/glslang/glslang/Include/PoolAlloc.h index 3e67d6edff..e84ac52cd2 100644 --- a/thirdparty/glslang/glslang/Include/PoolAlloc.h +++ b/thirdparty/glslang/glslang/Include/PoolAlloc.h @@ -118,11 +118,16 @@ private: unsigned char* mem; // beginning of our allocation (pts to header) TAllocation* prevAlloc; // prior allocation in the chain - const static unsigned char guardBlockBeginVal; - const static unsigned char guardBlockEndVal; - const static unsigned char userDataFill; + static inline constexpr unsigned char guardBlockBeginVal = 0xfb; + static inline constexpr unsigned char guardBlockEndVal = 0xfe; + static inline constexpr unsigned char userDataFill = 0xcd; + +# ifdef GUARD_BLOCKS + static inline constexpr size_t guardBlockSize = 16; +# else + static inline constexpr size_t guardBlockSize = 0; +# endif - const static size_t guardBlockSize; # ifdef GUARD_BLOCKS inline static size_t headerSize() { return sizeof(TAllocation); } # else diff --git a/thirdparty/glslang/glslang/Include/SpirvIntrinsics.h b/thirdparty/glslang/glslang/Include/SpirvIntrinsics.h index bfb551e445..0082a4d4eb 100644 --- a/thirdparty/glslang/glslang/Include/SpirvIntrinsics.h +++ b/thirdparty/glslang/glslang/Include/SpirvIntrinsics.h @@ -39,6 +39,7 @@ // GL_EXT_spirv_intrinsics // #include "Common.h" +#include <variant> namespace glslang { @@ -96,23 +97,27 @@ struct TSpirvInstruction { struct TSpirvTypeParameter { POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - TSpirvTypeParameter(const TIntermConstantUnion* arg) + TSpirvTypeParameter(const TIntermConstantUnion* arg) { value = arg; } + TSpirvTypeParameter(const TType* arg) { value = arg; } + + const TIntermConstantUnion* getAsConstant() const { - constant = arg; - type = nullptr; + if (value.index() == 0) + return std::get<const TIntermConstantUnion*>(value); + return nullptr; } - - TSpirvTypeParameter(const TType *arg) + const TType* getAsType() const { - constant = nullptr; - type = arg; + if (value.index() == 1) + return std::get<const TType*>(value); + return nullptr; } bool operator==(const TSpirvTypeParameter& rhs) const; bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); } - const TIntermConstantUnion* constant; // Constant expression - const TType* type; // Type specifier + // Parameter value: constant expression or type specifier + std::variant<const TIntermConstantUnion*, const TType*> value; }; typedef TVector<TSpirvTypeParameter> TSpirvTypeParameters; diff --git a/thirdparty/glslang/glslang/Include/intermediate.h b/thirdparty/glslang/glslang/Include/intermediate.h index b002ce889d..9d311d60b5 100644 --- a/thirdparty/glslang/glslang/Include/intermediate.h +++ b/thirdparty/glslang/glslang/Include/intermediate.h @@ -1006,6 +1006,8 @@ enum TOperator { EOpHitObjectGetAttributesNV, EOpHitObjectGetCurrentTimeNV, EOpReorderThreadNV, + EOpFetchMicroTriangleVertexPositionNV, + EOpFetchMicroTriangleVertexBarycentricNV, // HLSL operations // @@ -1100,6 +1102,17 @@ enum TOperator { // Shader tile image ops EOpStencilAttachmentReadEXT, // Fragment only EOpDepthAttachmentReadEXT, // Fragment only + + // Image processing + EOpImageSampleWeightedQCOM, + EOpImageBoxFilterQCOM, + EOpImageBlockMatchSADQCOM, + EOpImageBlockMatchSSDQCOM, +}; + +enum TLinkType { + ELinkNone, + ELinkExport, }; class TIntermTraverser; @@ -1319,9 +1332,11 @@ public: virtual const TString& getMethodName() const { return method; } virtual TIntermTyped* getObject() const { return object; } virtual void traverse(TIntermTraverser*); + void setExport() { linkType = ELinkExport; } protected: TIntermTyped* object; TString method; + TLinkType linkType; }; // @@ -1694,6 +1709,9 @@ public: const TPragmaTable& getPragmaTable() const { return *pragmaTable; } void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; } const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; } + + void setLinkType(TLinkType l) { linkType = l; } + TLinkType getLinkType() const { return linkType; } protected: TIntermAggregate(const TIntermAggregate&); // disallow copy constructor TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator @@ -1705,6 +1723,7 @@ protected: bool debug; TPragmaTable* pragmaTable; TSpirvInstruction spirvInst; + TLinkType linkType = ELinkNone; }; // diff --git a/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp b/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp index 3c7aaea3ff..8d5ce9af8c 100755 --- a/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp @@ -51,7 +51,6 @@ // including identifying what extensions are needed if a version does not allow a symbol // -#include "../Include/intermediate.h" #include "Initialize.h" namespace glslang { @@ -61,10 +60,6 @@ const bool ARBCompatibility = true; const bool ForwardCompatibility = false; -// change this back to false if depending on textual spellings of texturing calls when consuming the AST -// Using PureOperatorBuiltins=false is deprecated. -bool PureOperatorBuiltins = true; - namespace { // @@ -4113,6 +4108,19 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } + // Builtins for GL_EXT_texture_shadow_lod + if ((profile == EEsProfile && version >= 300) || ((profile != EEsProfile && version >= 130))) { + commonBuiltins.append( + "float texture(sampler2DArrayShadow, vec4, float);" + "float texture(samplerCubeArrayShadow, vec4, float, float);" + "float textureLod(sampler2DArrayShadow, vec4, float);" + "float textureLod(samplerCubeShadow, vec4, float);" + "float textureLod(samplerCubeArrayShadow, vec4, float, float);" + "float textureLodOffset(sampler2DArrayShadow, vec4, float, ivec2);" + "float textureOffset(sampler2DArrayShadow, vec4 , ivec2, float);" + "\n"); + } + if (profile != EEsProfile && version >= 450) { stageBuiltins[EShLangFragment].append(derivativesAndControl64bits); stageBuiltins[EShLangFragment].append( @@ -4135,6 +4143,18 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } + // QCOM_image_processing + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 140)) { + commonBuiltins.append( + "vec4 textureWeightedQCOM(sampler2D, vec2, sampler2DArray);" + "vec4 textureWeightedQCOM(sampler2D, vec2, sampler1DArray);" + "vec4 textureBoxFilterQCOM(sampler2D, vec2, vec2);" + "vec4 textureBlockMatchSADQCOM(sampler2D, uvec2, sampler2D, uvec2, uvec2);" + "vec4 textureBlockMatchSSDQCOM(sampler2D, uvec2, sampler2D, uvec2, uvec2);" + "\n"); + } + //============================================================================ // // Prototypes for built-in functions seen by vertex shaders only. @@ -4624,7 +4644,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "uvec4 fragmentFetchAMD(usubpassInputMS, uint);" "\n"); - } + } // Builtins for GL_NV_ray_tracing/GL_NV_ray_tracing_motion_blur/GL_EXT_ray_tracing/GL_EXT_ray_query/ // GL_NV_shader_invocation_reorder/GL_KHR_ray_tracing_position_Fetch @@ -4694,6 +4714,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "void reorderThreadNV(uint, uint);" "void reorderThreadNV(hitObjectNV);" "void reorderThreadNV(hitObjectNV, uint, uint);" + "vec3 fetchMicroTriangleVertexPositionNV(accelerationStructureEXT, int, int, int, ivec2);" + "vec2 fetchMicroTriangleVertexBarycentricNV(accelerationStructureEXT, int, int, int, ivec2);" "\n"); stageBuiltins[EShLangIntersect].append( "bool reportIntersectionNV(float, uint);" @@ -4811,6 +4833,20 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "void SetMeshOutputsEXT(uint, uint);" "\n"); } + // Builtins for GL_NV_displacement_micromap + if ((profile != EEsProfile && version >= 460) || (profile == EEsProfile && version >= 320)) { + stageBuiltins[EShLangMesh].append( + "vec3 fetchMicroTriangleVertexPositionNV(accelerationStructureEXT, int, int, int, ivec2);" + "vec2 fetchMicroTriangleVertexBarycentricNV(accelerationStructureEXT, int, int, int, ivec2);" + "\n"); + + stageBuiltins[EShLangCompute].append( + "vec3 fetchMicroTriangleVertexPositionNV(accelerationStructureEXT, int, int, int, ivec2);" + "vec2 fetchMicroTriangleVertexBarycentricNV(accelerationStructureEXT, int, int, int, ivec2);" + "\n"); + + } + //============================================================================ // @@ -5993,6 +6029,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "const uint gl_RayFlagsForceOpacityMicromap2StateEXT = 1024U;" "const uint gl_HitKindFrontFacingTriangleEXT = 254U;" "const uint gl_HitKindBackFacingTriangleEXT = 255U;" + "in uint gl_HitKindFrontFacingMicroTriangleNV;" + "in uint gl_HitKindBackFacingMicroTriangleNV;" "\n"; const char *constRayQueryIntersection = @@ -6081,7 +6119,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "in float gl_CurrentRayTimeNV;" "in uint gl_CullMaskEXT;" "in vec3 gl_HitTriangleVertexPositionsEXT[3];" + "in vec3 gl_HitMicroTriangleVertexPositionsNV[3];" + "in vec2 gl_HitMicroTriangleVertexBarycentricsNV[3];" "\n"; + const char *missDecls = "in uvec3 gl_LaunchIDNV;" "in uvec3 gl_LaunchIDEXT;" @@ -8095,7 +8136,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable); } - if (profile != EEsProfile) { + if (profile != EEsProfile) { BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); @@ -8725,6 +8766,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setFunctionExtensions("stencilAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); symbolTable.setFunctionExtensions("depthAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); symbolTable.setFunctionExtensions("colorAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); + + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 140)) { + symbolTable.setFunctionExtensions("textureWeightedQCOM", 1, &E_GL_QCOM_image_processing); + symbolTable.setFunctionExtensions("textureBoxFilterQCOM", 1, &E_GL_QCOM_image_processing); + symbolTable.setFunctionExtensions("textureBlockMatchSADQCOM", 1, &E_GL_QCOM_image_processing); + symbolTable.setFunctionExtensions("textureBlockMatchSSDQCOM", 1, &E_GL_QCOM_image_processing); + } break; case EShLangCompute: @@ -8885,6 +8934,11 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); } + + if ((profile != EEsProfile && version >= 460)) { + symbolTable.setFunctionExtensions("fetchMicroTriangleVertexPositionNV", 1, &E_GL_NV_displacement_micromap); + symbolTable.setFunctionExtensions("fetchMicroTriangleVertexBarycentricNV", 1, &E_GL_NV_displacement_micromap); + } break; case EShLangRayGen: @@ -8931,6 +8985,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setVariableExtensions("gl_IncomingRayFlagsEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_CurrentRayTimeNV", 1, &E_GL_NV_ray_tracing_motion_blur); symbolTable.setVariableExtensions("gl_HitTriangleVertexPositionsEXT", 1, &E_GL_EXT_ray_tracing_position_fetch); + symbolTable.setVariableExtensions("gl_HitMicroTriangleVertexPositionsNV", 1, &E_GL_NV_displacement_micromap); + symbolTable.setVariableExtensions("gl_HitMicroTriangleVertexBarycentricsNV", 1, &E_GL_NV_displacement_micromap); symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); @@ -8976,6 +9032,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setFunctionExtensions("hitObjectGetShaderBindingTableRecordIndexNV", 1, &E_GL_NV_shader_invocation_reorder); symbolTable.setFunctionExtensions("hitObjectGetShaderRecordBufferHandleNV", 1, &E_GL_NV_shader_invocation_reorder); symbolTable.setFunctionExtensions("reorderThreadNV", 1, &E_GL_NV_shader_invocation_reorder); + symbolTable.setFunctionExtensions("fetchMicroTriangleVertexPositionNV", 1, &E_GL_NV_displacement_micromap); + symbolTable.setFunctionExtensions("fetchMicroTriangleVertexBarycentricNV", 1, &E_GL_NV_displacement_micromap); BuiltInVariable("gl_LaunchIDNV", EbvLaunchId, symbolTable); @@ -9015,6 +9073,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); BuiltInVariable("gl_CurrentRayTimeNV", EbvCurrentRayTimeNV, symbolTable); BuiltInVariable("gl_HitTriangleVertexPositionsEXT", EbvPositionFetch, symbolTable); + BuiltInVariable("gl_HitMicroTriangleVertexPositionsNV", EbvMicroTrianglePositionNV, symbolTable); + BuiltInVariable("gl_HitMicroTriangleVertexBarycentricsNV", EbvMicroTriangleBaryNV, symbolTable); + BuiltInVariable("gl_HitKindFrontFacingMicroTriangleNV", EbvHitKindFrontFacingMicroTriangleNV, symbolTable); + BuiltInVariable("gl_HitKindBackFacingMicroTriangleNV", EbvHitKindBackFacingMicroTriangleNV, symbolTable); // GL_ARB_shader_ballot symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); @@ -9316,6 +9378,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); } + + // Builtins for GL_NV_displacment_micromap + if ((profile != EEsProfile && version >= 460)) { + symbolTable.setFunctionExtensions("fetchMicroTriangleVertexPositionNV", 1, &E_GL_NV_displacement_micromap); + symbolTable.setFunctionExtensions("fetchMicroTriangleVertexBarycentricNV", 1, &E_GL_NV_displacement_micromap); + } + break; case EShLangTask: @@ -9890,6 +9959,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("shadow2DEXT", EOpTexture); symbolTable.relateToOperator("shadow2DProjEXT", EOpTextureProj); } + + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 140)) { + symbolTable.relateToOperator("textureWeightedQCOM", EOpImageSampleWeightedQCOM); + symbolTable.relateToOperator("textureBoxFilterQCOM", EOpImageBoxFilterQCOM); + symbolTable.relateToOperator("textureBlockMatchSADQCOM", EOpImageBlockMatchSADQCOM); + symbolTable.relateToOperator("textureBlockMatchSSDQCOM", EOpImageBlockMatchSSDQCOM); + } } switch(language) { @@ -9981,9 +10058,18 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("coopMatLoad", EOpCooperativeMatrixLoad); symbolTable.relateToOperator("coopMatStore", EOpCooperativeMatrixStore); symbolTable.relateToOperator("coopMatMulAdd", EOpCooperativeMatrixMulAdd); + + if (profile != EEsProfile && version >= 460) { + symbolTable.relateToOperator("fetchMicroTriangleVertexPositionNV", EOpFetchMicroTriangleVertexPositionNV); + symbolTable.relateToOperator("fetchMicroTriangleVertexBarycentricNV", EOpFetchMicroTriangleVertexBarycentricNV); + } break; case EShLangRayGen: + if (profile != EEsProfile && version >= 460) { + symbolTable.relateToOperator("fetchMicroTriangleVertexPositionNV", EOpFetchMicroTriangleVertexPositionNV); + symbolTable.relateToOperator("fetchMicroTriangleVertexBarycentricNV", EOpFetchMicroTriangleVertexBarycentricNV); + } // fallthrough case EShLangClosestHit: case EShLangMiss: if (profile != EEsProfile && version >= 460) { @@ -10030,7 +10116,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion if (profile != EEsProfile && version >= 460) { symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersection); symbolTable.relateToOperator("reportIntersectionEXT", EOpReportIntersection); - } + } break; case EShLangAnyHit: if (profile != EEsProfile && version >= 460) { @@ -10055,6 +10141,12 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion if (profile != EEsProfile && version >= 450) { symbolTable.relateToOperator("SetMeshOutputsEXT", EOpSetMeshOutputsEXT); } + + if (profile != EEsProfile && version >= 460) { + // Builtins for GL_NV_displacement_micromap. + symbolTable.relateToOperator("fetchMicroTriangleVertexPositionNV", EOpFetchMicroTriangleVertexPositionNV); + symbolTable.relateToOperator("fetchMicroTriangleVertexBarycentricNV", EOpFetchMicroTriangleVertexBarycentricNV); + } break; case EShLangTask: if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { diff --git a/thirdparty/glslang/glslang/MachineIndependent/Initialize.h b/thirdparty/glslang/glslang/MachineIndependent/Initialize.h index ac8ec33e99..42c32ddbb7 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/Initialize.h +++ b/thirdparty/glslang/glslang/MachineIndependent/Initialize.h @@ -107,6 +107,9 @@ protected: int dimMap[EsdNumDims]; }; +// change this back to false if depending on textual spellings of texturing calls when consuming the AST +// Using PureOperatorBuiltins=false is deprecated. +constexpr bool PureOperatorBuiltins = true; } // end namespace glslang #endif // _INITIALIZE_INCLUDED_ diff --git a/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp index b8c64e0985..592e9aa8ad 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp @@ -38,6 +38,7 @@ // #include "ParseHelper.h" +#include "Initialize.h" #include "Scan.h" #include "../OSDependent/osinclude.h" @@ -1242,6 +1243,8 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, error(loc, "function cannot take any parameter(s)", function.getName().c_str(), ""); if (function.getType().getBasicType() != EbtVoid) error(loc, "", function.getType().getBasicTypeString().c_str(), "entry point cannot return a value"); + if (function.getLinkType() != ELinkNone) + error(loc, "main function cannot be exported", "", ""); } // @@ -1278,6 +1281,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, } else paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); } + paramNodes->setLinkType(function.getLinkType()); intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); loopNestingLevel = 0; statementNestingLevel = 0; @@ -2168,6 +2172,37 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan } break; } + + case EOpTexture: + case EOpTextureLod: + { + if ((fnCandidate.getParamCount() > 2) && ((*argp)[1]->getAsTyped()->getType().getBasicType() == EbtFloat) && + ((*argp)[1]->getAsTyped()->getType().getVectorSize() == 4) && fnCandidate[0].type->getSampler().shadow) { + featureString = fnCandidate.getName(); + if (callNode.getOp() == EOpTexture) + featureString += "(..., float bias)"; + else + featureString += "(..., float lod)"; + feature = featureString.c_str(); + + if ((fnCandidate[0].type->getSampler().dim == Esd2D && fnCandidate[0].type->getSampler().arrayed) || //2D Array Shadow + (fnCandidate[0].type->getSampler().dim == EsdCube && fnCandidate[0].type->getSampler().arrayed && fnCandidate.getParamCount() > 3) || // Cube Array Shadow + (fnCandidate[0].type->getSampler().dim == EsdCube && callNode.getOp() == EOpTextureLod)) { // Cube Shadow + requireExtensions(loc, 1, &E_GL_EXT_texture_shadow_lod, feature); + if (isEsProfile()) { + if (version < 320 && + !extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) + error(loc, "GL_EXT_texture_shadow_lod not supported for this ES version", feature, ""); + else + profileRequires(loc, EEsProfile, 320, nullptr, feature); + } else { // Desktop + profileRequires(loc, ~EEsProfile, 130, nullptr, feature); + } + } + } + break; + } + case EOpSparseTextureGather: case EOpSparseTextureGatherOffset: case EOpSparseTextureGatherOffsets: @@ -2282,12 +2317,36 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan if (callNode.getOp() == EOpTextureOffset) { TSampler s = arg0->getType().getSampler(); if (s.is2D() && s.isArrayed() && s.isShadow()) { - if (isEsProfile()) + if ( + ((*argp)[1]->getAsTyped()->getType().getBasicType() == EbtFloat) && + ((*argp)[1]->getAsTyped()->getType().getVectorSize() == 4) && + (fnCandidate.getParamCount() == 4)) { + featureString = fnCandidate.getName() + " for sampler2DArrayShadow"; + feature = featureString.c_str(); + requireExtensions(loc, 1, &E_GL_EXT_texture_shadow_lod, feature); + profileRequires(loc, EEsProfile, 300, nullptr, feature); + profileRequires(loc, ~EEsProfile, 130, nullptr, feature); + } + else if (isEsProfile()) error(loc, "TextureOffset does not support sampler2DArrayShadow : ", "sampler", "ES Profile"); else if (version <= 420) error(loc, "TextureOffset does not support sampler2DArrayShadow : ", "sampler", "version <= 420"); } } + + if (callNode.getOp() == EOpTextureLodOffset) { + TSampler s = arg0->getType().getSampler(); + if (s.is2D() && s.isArrayed() && s.isShadow() && + ((*argp)[1]->getAsTyped()->getType().getBasicType() == EbtFloat) && + ((*argp)[1]->getAsTyped()->getType().getVectorSize() == 4) && + (fnCandidate.getParamCount() == 4)) { + featureString = fnCandidate.getName() + " for sampler2DArrayShadow"; + feature = featureString.c_str(); + profileRequires(loc, EEsProfile, 300, nullptr, feature); + profileRequires(loc, ~EEsProfile, 130, nullptr, feature); + requireExtensions(loc, 1, &E_GL_EXT_texture_shadow_lod, feature); + } + } } break; @@ -2513,11 +2572,18 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan } const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true , true); - const TType* refType = (base->getType().isReference()) ? base->getType().getReferentType() : nullptr; - const TQualifier& qualifier = (refType != nullptr) ? refType->getQualifier() : base->getType().getQualifier(); - if (qualifier.storage != EvqShared && qualifier.storage != EvqBuffer && qualifier.storage != EvqtaskPayloadSharedEXT) - error(loc,"Atomic memory function can only be used for shader storage block member or shared variable.", - fnCandidate.getName().c_str(), ""); + const char* errMsg = "Only l-values corresponding to shader block storage or shared variables can be used with " + "atomic memory functions."; + if (base) { + const TType* refType = (base->getType().isReference()) ? base->getType().getReferentType() : nullptr; + const TQualifier& qualifier = + (refType != nullptr) ? refType->getQualifier() : base->getType().getQualifier(); + if (qualifier.storage != EvqShared && qualifier.storage != EvqBuffer && + qualifier.storage != EvqtaskPayloadSharedEXT) + error(loc, errMsg, fnCandidate.getName().c_str(), ""); + } else { + error(loc, errMsg, fnCandidate.getName().c_str(), ""); + } break; } @@ -2685,7 +2751,6 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan } } -extern bool PureOperatorBuiltins; // Deprecated! Use PureOperatorBuiltins == true instead, in which case this // functionality is handled in builtInOpCheck() instead of here. @@ -6324,9 +6389,6 @@ void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool m // Do layout error checking with respect to a type. void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) { - if (extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) - return; // Skip any check if GL_EXT_spirv_intrinsics is turned on - const TQualifier& qualifier = type.getQualifier(); // first, intra-layout qualifier-only error checking @@ -6380,6 +6442,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) case EvqCallableData: case EvqCallableDataIn: case EvqHitObjectAttrNV: + case EvqSpirvStorageClass: break; case EvqTileImageEXT: break; @@ -6436,7 +6499,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) // an array of size N, all elements of the array from binding through binding + N - 1 must be within this // range." // - if (! type.isOpaque() && type.getBasicType() != EbtBlock) + if (!type.isOpaque() && type.getBasicType() != EbtBlock && type.getBasicType() != EbtSpirvType) error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", ""); if (type.getBasicType() == EbtSampler) { int lastBinding = qualifier.layoutBinding; diff --git a/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.h b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.h index d74662939f..05ebca275d 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.h +++ b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.h @@ -196,6 +196,7 @@ public: struct TPragma contextPragma; int beginInvocationInterlockCount; int endInvocationInterlockCount; + bool compileOnly = false; protected: TParseContextBase(TParseContextBase&); diff --git a/thirdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp b/thirdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp index 471a980409..5d7173c9db 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp @@ -131,16 +131,6 @@ TPoolAllocator::~TPoolAllocator() } } -const unsigned char TAllocation::guardBlockBeginVal = 0xfb; -const unsigned char TAllocation::guardBlockEndVal = 0xfe; -const unsigned char TAllocation::userDataFill = 0xcd; - -# ifdef GUARD_BLOCKS - const size_t TAllocation::guardBlockSize = 16; -# else - const size_t TAllocation::guardBlockSize = 0; -# endif - // // Check a single guard block for damage // diff --git a/thirdparty/glslang/glslang/MachineIndependent/Scan.cpp b/thirdparty/glslang/glslang/MachineIndependent/Scan.cpp index 99c9ecbbba..5c7e2e662e 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/Scan.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/Scan.cpp @@ -1073,12 +1073,18 @@ int TScanContext::tokenizeIdentifier() parseContext.extensionTurnedOn(E_GL_NV_ray_tracing)) return keyword; return identifierOrType(); + case ACCSTRUCTEXT: + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) || + parseContext.extensionTurnedOn(E_GL_EXT_ray_query) || + parseContext.extensionTurnedOn(E_GL_NV_displacement_micromap)) + return keyword; + return identifierOrType(); case PAYLOADEXT: case PAYLOADINEXT: case HITATTREXT: case CALLDATAEXT: case CALLDATAINEXT: - case ACCSTRUCTEXT: if (parseContext.symbolTable.atBuiltInLevel() || parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) || parseContext.extensionTurnedOn(E_GL_EXT_ray_query)) diff --git a/thirdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp b/thirdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp index 51c524bbec..9a42acae91 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp @@ -796,7 +796,8 @@ bool ProcessDeferred( bool requireNonempty, TShader::Includer& includer, const std::string sourceEntryPointName = "", - const TEnvironment* environment = nullptr) // optional way of fully setting all versions, overriding the above + const TEnvironment* environment = nullptr, // optional way of fully setting all versions, overriding the above + bool compileOnly = false) { // This must be undone (.pop()) by the caller, after it finishes consuming the created tree. GetThreadPoolAllocator().push(); @@ -942,6 +943,7 @@ bool ProcessDeferred( std::unique_ptr<TParseContextBase> parseContext(CreateParseContext(*symbolTable, intermediate, version, profile, source, stage, compiler->infoSink, spvVersion, forwardCompatible, messages, false, sourceEntryPointName)); + parseContext->compileOnly = compileOnly; TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer); // only GLSL (bison triggered, really) needs an externally set scan context @@ -1066,8 +1068,8 @@ struct DoPreprocessing { EShOptimizationLevel, EShMessages) { // This is a list of tokens that do not require a space before or after. - static const std::string unNeededSpaceTokens = ";()[]"; - static const std::string noSpaceBeforeTokens = ","; + static const std::string noNeededSpaceBeforeTokens = ";)[].,"; + static const std::string noNeededSpaceAfterTokens = ".(["; glslang::TPpToken ppToken; parseContext.setScanner(&input); @@ -1140,6 +1142,7 @@ struct DoPreprocessing { }); int lastToken = EndOfInput; // lastToken records the last token processed. + std::string lastTokenName; do { int token = ppContext.tokenize(ppToken); if (token == EndOfInput) @@ -1158,12 +1161,23 @@ struct DoPreprocessing { // Output a space in between tokens, but not at the start of a line, // and also not around special tokens. This helps with readability // and consistency. - if (!isNewString && !isNewLine && lastToken != EndOfInput && - (unNeededSpaceTokens.find((char)token) == std::string::npos) && - (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) && - (noSpaceBeforeTokens.find((char)token) == std::string::npos)) { - outputBuffer += ' '; + if (!isNewString && !isNewLine && lastToken != EndOfInput) { + // left parenthesis need a leading space, except it is in a function-call-like context. + // examples: `for (xxx)`, `a * (b + c)`, `vec(2.0)`, `foo(x, y, z)` + if (token == '(') { + if (lastToken != PpAtomIdentifier || + lastTokenName == "if" || + lastTokenName == "for" || + lastTokenName == "while" || + lastTokenName == "switch") + outputBuffer += ' '; + } else if ((noNeededSpaceBeforeTokens.find((char)token) == std::string::npos) && + (noNeededSpaceAfterTokens.find((char)lastToken) == std::string::npos)) { + outputBuffer += ' '; + } } + if (token == PpAtomIdentifier) + lastTokenName = ppToken.name; lastToken = token; if (token == PpAtomConstString) outputBuffer += "\""; @@ -1279,14 +1293,15 @@ bool CompileDeferred( TIntermediate& intermediate,// returned tree, etc. TShader::Includer& includer, const std::string sourceEntryPointName = "", - TEnvironment* environment = nullptr) + TEnvironment* environment = nullptr, + bool compileOnly = false) { DoFullParse parser; return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, preamble, optLevel, resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, overrideVersion, forwardCompatible, messages, intermediate, parser, - true, includer, sourceEntryPointName, environment); + true, includer, sourceEntryPointName, environment, compileOnly); } } // end anonymous namespace for local functions @@ -1867,7 +1882,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion preamble, EShOptNone, builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, overrideVersion, forwardCompatible, messages, *intermediate, includer, sourceEntryPointName, - &environment); + &environment, compileOnly); } // Fill in a string with the result of preprocessing ShaderStrings diff --git a/thirdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp b/thirdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp index 4e130c31be..1d08797ac2 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp @@ -45,11 +45,11 @@ namespace glslang { bool TSpirvTypeParameter::operator==(const TSpirvTypeParameter& rhs) const { - if (constant != nullptr) - return constant->getConstArray() == rhs.constant->getConstArray(); + if (getAsConstant() != nullptr) + return getAsConstant()->getConstArray() == rhs.getAsConstant()->getConstArray(); - assert(type != nullptr); - return *type == *rhs.type; + assert(getAsType() != nullptr); + return *getAsType() == *rhs.getAsType(); } // diff --git a/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp b/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp index 1e007a7120..dae5a8b918 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp @@ -318,6 +318,16 @@ void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const c } } +// Make a single function require an extension(s). i.e., this will only set the extensions for the symbol that matches 'name' exactly. +// This is different from setFunctionExtensions, which uses std::map::lower_bound to effectively set all symbols that start with 'name'. +// Should only be used for a version/profile that actually needs the extension(s). +void TSymbolTableLevel::setSingleFunctionExtensions(const char* name, int num, const char* const extensions[]) +{ + if (auto candidate = level.find(name); candidate != level.end()) { + candidate->second->setExtensions(num, extensions); + } +} + // // Make all symbols in this table level read only. // diff --git a/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.h b/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.h index fc86ad6229..94c3929da2 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.h +++ b/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.h @@ -246,7 +246,8 @@ public: TSymbol(name), mangledName(*name + '('), op(tOp), - defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0), + linkType(ELinkNone) { returnType.shallowCopy(retType); declaredBuiltIn = retType.getQualifier().builtIn; @@ -326,6 +327,9 @@ public: virtual void dump(TInfoSink& infoSink, bool complete = false) const override; + void setExport() { linkType = ELinkExport; } + TLinkType getLinkType() const { return linkType; } + protected: explicit TFunction(const TFunction&); TFunction& operator=(const TFunction&); @@ -347,6 +351,7 @@ protected: int defaultParamCount; TSpirvInstruction spirvInst; // SPIR-V instruction qualifiers + TLinkType linkType; }; // @@ -571,6 +576,7 @@ public: void relateToOperator(const char* name, TOperator op); void setFunctionExtensions(const char* name, int num, const char* const extensions[]); + void setSingleFunctionExtensions(const char* name, int num, const char* const extensions[]); void dump(TInfoSink& infoSink, bool complete = false) const; TSymbolTableLevel* clone() const; void readOnly(); @@ -872,6 +878,12 @@ public: table[level]->setFunctionExtensions(name, num, extensions); } + void setSingleFunctionExtensions(const char* name, int num, const char* const extensions[]) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->setSingleFunctionExtensions(name, num, extensions); + } + void setVariableExtensions(const char* name, int numExts, const char* const extensions[]) { TSymbol* symbol = find(TString(name)); diff --git a/thirdparty/glslang/glslang/MachineIndependent/Versions.cpp b/thirdparty/glslang/glslang/MachineIndependent/Versions.cpp index 40cf3ed81e..bede71604e 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/Versions.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/Versions.cpp @@ -297,16 +297,18 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_NV_compute_shader_derivatives] = EBhDisable; extensionBehavior[E_GL_NV_shader_texture_footprint] = EBhDisable; extensionBehavior[E_GL_NV_mesh_shader] = EBhDisable; - extensionBehavior[E_GL_NV_cooperative_matrix] = EBhDisable; extensionBehavior[E_GL_NV_shader_sm_builtins] = EBhDisable; extensionBehavior[E_GL_NV_integer_cooperative_matrix] = EBhDisable; - extensionBehavior[E_GL_NV_shader_invocation_reorder] = EBhDisable; + extensionBehavior[E_GL_NV_displacement_micromap] = EBhDisable; // ARM extensionBehavior[E_GL_ARM_shader_core_builtins] = EBhDisable; + // QCOM + extensionBehavior[E_GL_QCOM_image_processing] = EBhDisable; + // AEP extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisable; extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisable; @@ -356,6 +358,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_opacity_micromap] = EBhDisable; extensionBehavior[E_GL_EXT_ray_tracing_position_fetch] = EBhDisable; extensionBehavior[E_GL_EXT_shader_tile_image] = EBhDisable; + extensionBehavior[E_GL_EXT_texture_shadow_lod] = EBhDisable; // OVR extensions extensionBehavior[E_GL_OVR_multiview] = EBhDisable; @@ -431,6 +434,8 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_OES_texture_buffer 1\n" "#define GL_OES_texture_cube_map_array 1\n" "#define GL_EXT_shader_non_constant_global_initializers 1\n" + + "#define GL_QCOM_image_processing 1\n" ; if (version >= 300) { @@ -555,6 +560,8 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_NV_integer_cooperative_matrix 1\n" "#define GL_NV_shader_invocation_reorder 1\n" + "#define GL_QCOM_image_processing 1\n" + "#define GL_EXT_shader_explicit_arithmetic_types 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_int8 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_int16 1\n" diff --git a/thirdparty/glslang/glslang/MachineIndependent/Versions.h b/thirdparty/glslang/glslang/MachineIndependent/Versions.h index 29ebed248e..0ebace9bb2 100755 --- a/thirdparty/glslang/glslang/MachineIndependent/Versions.h +++ b/thirdparty/glslang/glslang/MachineIndependent/Versions.h @@ -266,7 +266,12 @@ const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragmen const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives"; const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint"; const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader"; +const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix"; +const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins"; +const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix"; +const char* const E_GL_NV_shader_invocation_reorder = "GL_NV_shader_invocation_reorder"; const char* const E_GL_EXT_ray_tracing_position_fetch = "GL_EXT_ray_tracing_position_fetch"; +const char* const E_GL_NV_displacement_micromap = "GL_NV_displacement_micromap"; // ARM const char* const E_GL_ARM_shader_core_builtins = "GL_ARM_shader_core_builtins"; @@ -276,10 +281,8 @@ const char* const E_GL_ARM_shader_core_builtins = "GL_ARM_shader const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 }; const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]); -const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix"; -const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins"; -const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix"; -const char* const E_GL_NV_shader_invocation_reorder = "GL_NV_shader_invocation_reorder"; + +const char* const E_GL_QCOM_image_processing = "GL_QCOM_image_processing"; // AEP const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a"; @@ -331,6 +334,8 @@ const char* const E_GL_EXT_shader_atomic_float2 = "GL_EXT_shader_atomic_float2"; const char* const E_GL_EXT_shader_tile_image = "GL_EXT_shader_tile_image"; +const char* const E_GL_EXT_texture_shadow_lod = "GL_EXT_texture_shadow_lod"; + // Arrays of extensions for the above AEP duplications const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader }; diff --git a/thirdparty/glslang/glslang/MachineIndependent/attribute.cpp b/thirdparty/glslang/glslang/MachineIndependent/attribute.cpp index 21ef736870..a167c494fb 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/attribute.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/attribute.cpp @@ -123,6 +123,8 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const return EatPartialCount; else if (name == "subgroup_uniform_control_flow") return EatSubgroupUniformControlFlow; + else if (name == "export") + return EatExport; else return EatNone; } @@ -355,6 +357,7 @@ void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttri switch (it->name) { case EatSubgroupUniformControlFlow: + requireExtensions(loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); intermediate.setSubgroupUniformControlFlow(); break; default: diff --git a/thirdparty/glslang/glslang/MachineIndependent/attribute.h b/thirdparty/glslang/glslang/MachineIndependent/attribute.h index c5b29176c4..a0c4c43d45 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/attribute.h +++ b/thirdparty/glslang/glslang/MachineIndependent/attribute.h @@ -120,6 +120,7 @@ namespace glslang { EatNonWritable, EatNonReadable, EatSubgroupUniformControlFlow, + EatExport, }; class TIntermAggregate; diff --git a/thirdparty/glslang/glslang/MachineIndependent/glslang.y b/thirdparty/glslang/glslang/MachineIndependent/glslang.y index d47f29259a..99f0d388bc 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/glslang.y +++ b/thirdparty/glslang/glslang/MachineIndependent/glslang.y @@ -941,24 +941,25 @@ identifier_list function_prototype : function_declarator RIGHT_PAREN { $$.function = $1; + if (parseContext.compileOnly) $$.function->setExport(); $$.loc = $2.loc; } | function_declarator RIGHT_PAREN attribute { $$.function = $1; + if (parseContext.compileOnly) $$.function->setExport(); $$.loc = $2.loc; - parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.handleFunctionAttributes($2.loc, *$3); } | attribute function_declarator RIGHT_PAREN { $$.function = $2; + if (parseContext.compileOnly) $$.function->setExport(); $$.loc = $3.loc; - parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.handleFunctionAttributes($3.loc, *$1); } | attribute function_declarator RIGHT_PAREN attribute { $$.function = $2; + if (parseContext.compileOnly) $$.function->setExport(); $$.loc = $3.loc; - parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.handleFunctionAttributes($3.loc, *$1); parseContext.handleFunctionAttributes($3.loc, *$4); } @@ -4088,6 +4089,7 @@ function_definition parseContext.error($1.loc, "function does not return a value:", "", $1.function->getName().c_str()); parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); $$ = parseContext.intermediate.growAggregate($1.intermNode, $3); + $$->getAsAggregate()->setLinkType($1.function->getLinkType()); parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getType(), $1.loc); $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); diff --git a/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp b/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp index a265abc802..534bee13cb 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp @@ -67,7 +67,7 @@ /* First part of user prologue. */ -#line 69 "MachineIndependent/glslang.y" +#line 44 "MachineIndependent/glslang.y" /* Based on: @@ -723,7 +723,7 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; /* Second part of user prologue. */ -#line 136 "MachineIndependent/glslang.y" +#line 111 "MachineIndependent/glslang.y" /* windows only pragma */ @@ -1167,77 +1167,77 @@ static const yytype_int16 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 395, 395, 401, 404, 409, 412, 415, 419, 423, - 426, 430, 434, 438, 442, 446, 450, 456, 464, 467, - 470, 473, 476, 481, 489, 496, 503, 509, 513, 520, - 523, 529, 536, 546, 554, 559, 587, 596, 602, 606, - 610, 630, 631, 632, 633, 639, 640, 645, 650, 659, - 660, 665, 673, 674, 680, 689, 690, 695, 700, 705, - 713, 714, 723, 735, 736, 745, 746, 755, 756, 765, - 766, 774, 775, 783, 784, 792, 793, 793, 811, 812, - 828, 832, 836, 840, 845, 849, 853, 857, 861, 865, - 869, 876, 879, 890, 897, 903, 910, 916, 921, 928, - 932, 936, 940, 945, 950, 959, 959, 970, 974, 981, - 985, 991, 997, 1007, 1010, 1017, 1025, 1045, 1068, 1083, - 1108, 1119, 1129, 1139, 1149, 1158, 1161, 1165, 1169, 1174, - 1182, 1189, 1194, 1199, 1204, 1213, 1223, 1250, 1259, 1266, - 1274, 1281, 1288, 1296, 1304, 1314, 1324, 1331, 1342, 1348, - 1351, 1358, 1362, 1366, 1375, 1385, 1388, 1399, 1402, 1405, - 1409, 1413, 1418, 1422, 1425, 1430, 1434, 1439, 1448, 1452, - 1457, 1463, 1469, 1476, 1481, 1486, 1494, 1500, 1512, 1526, - 1532, 1537, 1545, 1553, 1561, 1569, 1577, 1585, 1593, 1601, - 1609, 1616, 1623, 1627, 1632, 1637, 1642, 1647, 1652, 1657, - 1661, 1665, 1669, 1673, 1679, 1685, 1697, 1704, 1707, 1716, - 1723, 1734, 1739, 1747, 1751, 1761, 1764, 1770, 1776, 1781, - 1789, 1799, 1803, 1807, 1811, 1816, 1820, 1825, 1830, 1835, - 1840, 1845, 1850, 1855, 1860, 1865, 1871, 1877, 1883, 1888, - 1893, 1898, 1903, 1908, 1913, 1918, 1923, 1928, 1933, 1938, - 1944, 1951, 1956, 1961, 1966, 1971, 1976, 1981, 1986, 1991, - 1996, 2001, 2006, 2014, 2022, 2030, 2036, 2042, 2048, 2054, - 2060, 2066, 2072, 2078, 2084, 2090, 2096, 2102, 2108, 2114, - 2120, 2126, 2132, 2138, 2144, 2150, 2156, 2162, 2168, 2174, - 2180, 2186, 2192, 2198, 2204, 2210, 2216, 2222, 2228, 2236, - 2244, 2252, 2260, 2268, 2276, 2284, 2292, 2300, 2308, 2316, - 2324, 2330, 2336, 2342, 2348, 2354, 2360, 2366, 2372, 2378, - 2384, 2390, 2396, 2402, 2408, 2414, 2420, 2426, 2432, 2438, - 2444, 2450, 2456, 2462, 2468, 2474, 2480, 2486, 2492, 2498, - 2504, 2510, 2516, 2522, 2528, 2534, 2540, 2544, 2548, 2552, - 2557, 2563, 2568, 2573, 2578, 2583, 2588, 2593, 2599, 2604, - 2609, 2614, 2619, 2624, 2630, 2636, 2642, 2648, 2654, 2660, - 2666, 2672, 2678, 2684, 2690, 2696, 2702, 2708, 2713, 2718, - 2723, 2728, 2733, 2738, 2744, 2749, 2754, 2759, 2764, 2769, - 2774, 2779, 2785, 2790, 2795, 2800, 2805, 2810, 2815, 2820, - 2825, 2830, 2835, 2840, 2845, 2850, 2855, 2861, 2866, 2871, - 2877, 2883, 2888, 2893, 2898, 2904, 2909, 2914, 2919, 2925, - 2930, 2935, 2940, 2946, 2951, 2956, 2961, 2967, 2973, 2979, - 2985, 2990, 2996, 3002, 3008, 3013, 3018, 3023, 3028, 3033, - 3039, 3044, 3049, 3054, 3060, 3065, 3070, 3075, 3081, 3086, - 3091, 3096, 3102, 3107, 3112, 3117, 3123, 3128, 3133, 3138, - 3144, 3149, 3154, 3159, 3165, 3170, 3175, 3180, 3186, 3191, - 3196, 3201, 3207, 3212, 3217, 3222, 3228, 3233, 3238, 3243, - 3249, 3254, 3259, 3264, 3270, 3275, 3280, 3285, 3291, 3296, - 3301, 3306, 3312, 3317, 3322, 3327, 3333, 3338, 3343, 3348, - 3353, 3358, 3363, 3368, 3373, 3378, 3383, 3388, 3393, 3398, - 3403, 3408, 3413, 3418, 3423, 3428, 3433, 3438, 3443, 3448, - 3453, 3459, 3465, 3471, 3477, 3483, 3489, 3495, 3502, 3509, - 3515, 3521, 3527, 3533, 3540, 3547, 3554, 3561, 3565, 3570, - 3575, 3591, 3596, 3601, 3609, 3609, 3620, 3620, 3630, 3633, - 3646, 3668, 3695, 3699, 3705, 3710, 3721, 3725, 3731, 3737, - 3748, 3751, 3758, 3762, 3763, 3769, 3770, 3771, 3772, 3773, - 3774, 3775, 3777, 3783, 3792, 3793, 3797, 3793, 3809, 3810, - 3814, 3814, 3821, 3821, 3835, 3838, 3846, 3854, 3865, 3866, - 3870, 3874, 3882, 3889, 3893, 3901, 3905, 3918, 3922, 3930, - 3930, 3950, 3953, 3959, 3971, 3983, 3987, 3995, 3995, 4010, - 4010, 4028, 4028, 4049, 4052, 4058, 4061, 4067, 4071, 4078, - 4083, 4088, 4095, 4098, 4102, 4107, 4111, 4121, 4125, 4134, - 4137, 4141, 4150, 4150, 4192, 4197, 4200, 4205, 4208, 4215, - 4218, 4223, 4226, 4231, 4234, 4239, 4242, 4247, 4251, 4256, - 4260, 4265, 4269, 4276, 4279, 4284, 4287, 4290, 4293, 4296, - 4301, 4310, 4321, 4326, 4334, 4338, 4343, 4347, 4352, 4356, - 4361, 4365, 4372, 4375, 4380, 4383, 4386, 4389, 4394, 4397, - 4402, 4408, 4411, 4414, 4417, 4422, 4426, 4431, 4435, 4440, - 4444, 4451, 4454, 4459, 4462, 4467, 4470, 4476, 4479, 4484, - 4487 + 0, 362, 362, 368, 371, 376, 379, 382, 386, 389, + 392, 396, 400, 404, 408, 412, 416, 422, 429, 432, + 435, 438, 441, 446, 454, 461, 468, 474, 478, 485, + 488, 494, 501, 511, 519, 524, 551, 559, 565, 569, + 573, 593, 594, 595, 596, 602, 603, 608, 613, 622, + 623, 628, 636, 637, 643, 652, 653, 658, 663, 668, + 676, 677, 686, 698, 699, 708, 709, 718, 719, 728, + 729, 737, 738, 746, 747, 755, 756, 756, 774, 775, + 791, 795, 799, 803, 808, 812, 816, 820, 824, 828, + 832, 839, 842, 853, 860, 865, 872, 877, 882, 889, + 893, 897, 901, 906, 911, 920, 920, 931, 935, 942, + 947, 953, 959, 969, 972, 979, 987, 1007, 1030, 1045, + 1070, 1081, 1091, 1101, 1111, 1120, 1123, 1127, 1131, 1136, + 1144, 1149, 1154, 1159, 1164, 1173, 1183, 1210, 1219, 1226, + 1233, 1240, 1247, 1255, 1263, 1273, 1283, 1290, 1300, 1306, + 1309, 1316, 1320, 1324, 1332, 1341, 1344, 1355, 1358, 1361, + 1365, 1369, 1373, 1377, 1380, 1385, 1389, 1394, 1402, 1406, + 1411, 1417, 1423, 1430, 1435, 1440, 1448, 1453, 1465, 1479, + 1485, 1490, 1498, 1506, 1514, 1522, 1530, 1538, 1546, 1554, + 1562, 1569, 1576, 1580, 1585, 1590, 1595, 1600, 1605, 1610, + 1614, 1618, 1622, 1626, 1632, 1638, 1648, 1655, 1658, 1666, + 1673, 1684, 1689, 1697, 1701, 1711, 1714, 1720, 1726, 1731, + 1739, 1749, 1753, 1757, 1761, 1766, 1770, 1775, 1780, 1785, + 1790, 1795, 1800, 1805, 1810, 1815, 1821, 1827, 1833, 1838, + 1843, 1848, 1853, 1858, 1863, 1868, 1873, 1878, 1883, 1888, + 1893, 1900, 1905, 1910, 1915, 1920, 1925, 1930, 1935, 1940, + 1945, 1950, 1955, 1963, 1971, 1979, 1985, 1991, 1997, 2003, + 2009, 2015, 2021, 2027, 2033, 2039, 2045, 2051, 2057, 2063, + 2069, 2075, 2081, 2087, 2093, 2099, 2105, 2111, 2117, 2123, + 2129, 2135, 2141, 2147, 2153, 2159, 2165, 2171, 2177, 2185, + 2193, 2201, 2209, 2217, 2225, 2233, 2241, 2249, 2257, 2265, + 2273, 2279, 2285, 2291, 2297, 2303, 2309, 2315, 2321, 2327, + 2333, 2339, 2345, 2351, 2357, 2363, 2369, 2375, 2381, 2387, + 2393, 2399, 2405, 2411, 2417, 2423, 2429, 2435, 2441, 2447, + 2453, 2459, 2465, 2471, 2477, 2483, 2489, 2493, 2497, 2501, + 2506, 2511, 2516, 2521, 2526, 2531, 2536, 2541, 2546, 2551, + 2556, 2561, 2566, 2571, 2577, 2583, 2589, 2595, 2601, 2607, + 2613, 2619, 2625, 2631, 2637, 2643, 2649, 2654, 2659, 2664, + 2669, 2674, 2679, 2684, 2689, 2694, 2699, 2704, 2709, 2714, + 2719, 2724, 2729, 2734, 2739, 2744, 2749, 2754, 2759, 2764, + 2769, 2774, 2779, 2784, 2789, 2794, 2799, 2804, 2809, 2814, + 2820, 2826, 2831, 2836, 2841, 2847, 2852, 2857, 2862, 2868, + 2873, 2878, 2883, 2889, 2894, 2899, 2904, 2910, 2916, 2922, + 2928, 2933, 2939, 2945, 2951, 2956, 2961, 2966, 2971, 2976, + 2982, 2987, 2992, 2997, 3003, 3008, 3013, 3018, 3024, 3029, + 3034, 3039, 3045, 3050, 3055, 3060, 3066, 3071, 3076, 3081, + 3087, 3092, 3097, 3102, 3108, 3113, 3118, 3123, 3129, 3134, + 3139, 3144, 3150, 3155, 3160, 3165, 3171, 3176, 3181, 3186, + 3192, 3197, 3202, 3207, 3213, 3218, 3223, 3228, 3234, 3239, + 3244, 3249, 3255, 3260, 3265, 3270, 3276, 3281, 3286, 3291, + 3296, 3301, 3306, 3311, 3316, 3321, 3326, 3331, 3336, 3341, + 3346, 3351, 3356, 3361, 3366, 3371, 3376, 3381, 3386, 3391, + 3396, 3402, 3408, 3414, 3420, 3426, 3432, 3438, 3445, 3452, + 3458, 3464, 3470, 3476, 3483, 3490, 3497, 3504, 3508, 3512, + 3517, 3533, 3538, 3543, 3551, 3551, 3562, 3562, 3572, 3575, + 3588, 3610, 3637, 3641, 3647, 3652, 3663, 3666, 3672, 3678, + 3687, 3690, 3696, 3700, 3701, 3707, 3708, 3709, 3710, 3711, + 3712, 3713, 3714, 3718, 3726, 3727, 3731, 3727, 3743, 3744, + 3748, 3748, 3755, 3755, 3769, 3772, 3780, 3788, 3799, 3800, + 3804, 3807, 3814, 3821, 3825, 3833, 3837, 3850, 3853, 3860, + 3860, 3880, 3883, 3889, 3901, 3913, 3916, 3923, 3923, 3938, + 3938, 3956, 3956, 3977, 3980, 3986, 3989, 3995, 3999, 4006, + 4011, 4016, 4023, 4026, 4030, 4034, 4038, 4047, 4051, 4060, + 4063, 4066, 4074, 4074, 4116, 4121, 4124, 4129, 4132, 4137, + 4140, 4145, 4148, 4153, 4156, 4161, 4164, 4169, 4173, 4178, + 4182, 4187, 4191, 4198, 4201, 4206, 4209, 4212, 4215, 4218, + 4223, 4232, 4243, 4248, 4256, 4260, 4265, 4269, 4274, 4278, + 4283, 4287, 4294, 4297, 4302, 4305, 4308, 4311, 4316, 4319, + 4324, 4330, 4333, 4336, 4339, 4344, 4348, 4353, 4357, 4362, + 4366, 4373, 4376, 4381, 4384, 4389, 4392, 4398, 4401, 4406, + 4409 }; #endif @@ -5210,7 +5210,7 @@ yyreduce: switch (yyn) { case 2: /* variable_identifier: IDENTIFIER */ -#line 395 "MachineIndependent/glslang.y" +#line 362 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string); } @@ -5218,7 +5218,7 @@ yyreduce: break; case 3: /* primary_expression: variable_identifier */ -#line 401 "MachineIndependent/glslang.y" +#line 368 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } @@ -5226,7 +5226,7 @@ yyreduce: break; case 4: /* primary_expression: LEFT_PAREN expression RIGHT_PAREN */ -#line 404 "MachineIndependent/glslang.y" +#line 371 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) @@ -5236,7 +5236,7 @@ yyreduce: break; case 5: /* primary_expression: FLOATCONSTANT */ -#line 409 "MachineIndependent/glslang.y" +#line 376 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); } @@ -5244,7 +5244,7 @@ yyreduce: break; case 6: /* primary_expression: INTCONSTANT */ -#line 412 "MachineIndependent/glslang.y" +#line 379 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); } @@ -5252,7 +5252,7 @@ yyreduce: break; case 7: /* primary_expression: UINTCONSTANT */ -#line 415 "MachineIndependent/glslang.y" +#line 382 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); @@ -5261,7 +5261,7 @@ yyreduce: break; case 8: /* primary_expression: BOOLCONSTANT */ -#line 419 "MachineIndependent/glslang.y" +#line 386 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); } @@ -5269,7 +5269,7 @@ yyreduce: break; case 9: /* primary_expression: STRING_LITERAL */ -#line 423 "MachineIndependent/glslang.y" +#line 389 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true); } @@ -5277,7 +5277,7 @@ yyreduce: break; case 10: /* primary_expression: INT32CONSTANT */ -#line 426 "MachineIndependent/glslang.y" +#line 392 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); @@ -5286,7 +5286,7 @@ yyreduce: break; case 11: /* primary_expression: UINT32CONSTANT */ -#line 430 "MachineIndependent/glslang.y" +#line 396 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); @@ -5295,7 +5295,7 @@ yyreduce: break; case 12: /* primary_expression: INT64CONSTANT */ -#line 434 "MachineIndependent/glslang.y" +#line 400 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true); @@ -5304,7 +5304,7 @@ yyreduce: break; case 13: /* primary_expression: UINT64CONSTANT */ -#line 438 "MachineIndependent/glslang.y" +#line 404 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true); @@ -5313,7 +5313,7 @@ yyreduce: break; case 14: /* primary_expression: INT16CONSTANT */ -#line 442 "MachineIndependent/glslang.y" +#line 408 "MachineIndependent/glslang.y" { parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit integer literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((short)(yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); @@ -5322,7 +5322,7 @@ yyreduce: break; case 15: /* primary_expression: UINT16CONSTANT */ -#line 446 "MachineIndependent/glslang.y" +#line 412 "MachineIndependent/glslang.y" { parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((unsigned short)(yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); @@ -5331,7 +5331,7 @@ yyreduce: break; case 16: /* primary_expression: DOUBLECONSTANT */ -#line 450 "MachineIndependent/glslang.y" +#line 416 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double literal"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -5342,7 +5342,7 @@ yyreduce: break; case 17: /* primary_expression: FLOAT16CONSTANT */ -#line 456 "MachineIndependent/glslang.y" +#line 422 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat16, (yyvsp[0].lex).loc, true); @@ -5351,7 +5351,7 @@ yyreduce: break; case 18: /* postfix_expression: primary_expression */ -#line 464 "MachineIndependent/glslang.y" +#line 429 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } @@ -5359,7 +5359,7 @@ yyreduce: break; case 19: /* postfix_expression: postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET */ -#line 467 "MachineIndependent/glslang.y" +#line 432 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode)); } @@ -5367,7 +5367,7 @@ yyreduce: break; case 20: /* postfix_expression: function_call */ -#line 470 "MachineIndependent/glslang.y" +#line 435 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } @@ -5375,7 +5375,7 @@ yyreduce: break; case 21: /* postfix_expression: postfix_expression DOT IDENTIFIER */ -#line 473 "MachineIndependent/glslang.y" +#line 438 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string); } @@ -5383,7 +5383,7 @@ yyreduce: break; case 22: /* postfix_expression: postfix_expression INC_OP */ -#line 476 "MachineIndependent/glslang.y" +#line 441 "MachineIndependent/glslang.y" { parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode)); @@ -5393,7 +5393,7 @@ yyreduce: break; case 23: /* postfix_expression: postfix_expression DEC_OP */ -#line 481 "MachineIndependent/glslang.y" +#line 446 "MachineIndependent/glslang.y" { parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode)); @@ -5403,7 +5403,7 @@ yyreduce: break; case 24: /* integer_expression: expression */ -#line 489 "MachineIndependent/glslang.y" +#line 454 "MachineIndependent/glslang.y" { parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]"); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); @@ -5412,7 +5412,7 @@ yyreduce: break; case 25: /* function_call: function_call_or_method */ -#line 496 "MachineIndependent/glslang.y" +#line 461 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode); delete (yyvsp[0].interm).function; @@ -5421,7 +5421,7 @@ yyreduce: break; case 26: /* function_call_or_method: function_call_generic */ -#line 503 "MachineIndependent/glslang.y" +#line 468 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[0].interm); } @@ -5429,7 +5429,7 @@ yyreduce: break; case 27: /* function_call_generic: function_call_header_with_parameters RIGHT_PAREN */ -#line 509 "MachineIndependent/glslang.y" +#line 474 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[-1].interm); (yyval.interm).loc = (yyvsp[0].lex).loc; @@ -5438,7 +5438,7 @@ yyreduce: break; case 28: /* function_call_generic: function_call_header_no_parameters RIGHT_PAREN */ -#line 513 "MachineIndependent/glslang.y" +#line 478 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[-1].interm); (yyval.interm).loc = (yyvsp[0].lex).loc; @@ -5447,7 +5447,7 @@ yyreduce: break; case 29: /* function_call_header_no_parameters: function_call_header VOID */ -#line 520 "MachineIndependent/glslang.y" +#line 485 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[-1].interm); } @@ -5455,7 +5455,7 @@ yyreduce: break; case 30: /* function_call_header_no_parameters: function_call_header */ -#line 523 "MachineIndependent/glslang.y" +#line 488 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[0].interm); } @@ -5463,7 +5463,7 @@ yyreduce: break; case 31: /* function_call_header_with_parameters: function_call_header assignment_expression */ -#line 529 "MachineIndependent/glslang.y" +#line 494 "MachineIndependent/glslang.y" { TParameter param = { 0, new TType }; param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); @@ -5475,7 +5475,7 @@ yyreduce: break; case 32: /* function_call_header_with_parameters: function_call_header_with_parameters COMMA assignment_expression */ -#line 536 "MachineIndependent/glslang.y" +#line 501 "MachineIndependent/glslang.y" { TParameter param = { 0, new TType }; param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); @@ -5487,7 +5487,7 @@ yyreduce: break; case 33: /* function_call_header: function_identifier LEFT_PAREN */ -#line 546 "MachineIndependent/glslang.y" +#line 511 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[-1].interm); } @@ -5495,7 +5495,7 @@ yyreduce: break; case 34: /* function_identifier: type_specifier */ -#line 554 "MachineIndependent/glslang.y" +#line 519 "MachineIndependent/glslang.y" { // Constructor (yyval.interm).intermNode = 0; @@ -5505,7 +5505,7 @@ yyreduce: break; case 35: /* function_identifier: postfix_expression */ -#line 559 "MachineIndependent/glslang.y" +#line 524 "MachineIndependent/glslang.y" { // // Should be a method or subroutine call, but we haven't recognized the arguments yet. @@ -5537,7 +5537,7 @@ yyreduce: break; case 36: /* function_identifier: non_uniform_qualifier */ -#line 587 "MachineIndependent/glslang.y" +#line 551 "MachineIndependent/glslang.y" { // Constructor (yyval.interm).intermNode = 0; @@ -5547,7 +5547,7 @@ yyreduce: break; case 37: /* unary_expression: postfix_expression */ -#line 596 "MachineIndependent/glslang.y" +#line 559 "MachineIndependent/glslang.y" { parseContext.variableCheck((yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); @@ -5558,7 +5558,7 @@ yyreduce: break; case 38: /* unary_expression: INC_OP unary_expression */ -#line 602 "MachineIndependent/glslang.y" +#line 565 "MachineIndependent/glslang.y" { parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode)); @@ -5567,7 +5567,7 @@ yyreduce: break; case 39: /* unary_expression: DEC_OP unary_expression */ -#line 606 "MachineIndependent/glslang.y" +#line 569 "MachineIndependent/glslang.y" { parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode)); @@ -5576,7 +5576,7 @@ yyreduce: break; case 40: /* unary_expression: unary_operator unary_expression */ -#line 610 "MachineIndependent/glslang.y" +#line 573 "MachineIndependent/glslang.y" { if ((yyvsp[-1].interm).op != EOpNull) { char errorOp[2] = {0, 0}; @@ -5597,38 +5597,38 @@ yyreduce: break; case 41: /* unary_operator: PLUS */ -#line 630 "MachineIndependent/glslang.y" +#line 593 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; } #line 5603 "MachineIndependent/glslang_tab.cpp" break; case 42: /* unary_operator: DASH */ -#line 631 "MachineIndependent/glslang.y" +#line 594 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; } #line 5609 "MachineIndependent/glslang_tab.cpp" break; case 43: /* unary_operator: BANG */ -#line 632 "MachineIndependent/glslang.y" +#line 595 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; } #line 5615 "MachineIndependent/glslang_tab.cpp" break; case 44: /* unary_operator: TILDE */ -#line 633 "MachineIndependent/glslang.y" +#line 596 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot; parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); } #line 5622 "MachineIndependent/glslang_tab.cpp" break; case 45: /* multiplicative_expression: unary_expression */ -#line 639 "MachineIndependent/glslang.y" +#line 602 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5628 "MachineIndependent/glslang_tab.cpp" break; case 46: /* multiplicative_expression: multiplicative_expression STAR unary_expression */ -#line 640 "MachineIndependent/glslang.y" +#line 603 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5638,7 +5638,7 @@ yyreduce: break; case 47: /* multiplicative_expression: multiplicative_expression SLASH unary_expression */ -#line 645 "MachineIndependent/glslang.y" +#line 608 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5648,7 +5648,7 @@ yyreduce: break; case 48: /* multiplicative_expression: multiplicative_expression PERCENT unary_expression */ -#line 650 "MachineIndependent/glslang.y" +#line 613 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); @@ -5659,13 +5659,13 @@ yyreduce: break; case 49: /* additive_expression: multiplicative_expression */ -#line 659 "MachineIndependent/glslang.y" +#line 622 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5665 "MachineIndependent/glslang_tab.cpp" break; case 50: /* additive_expression: additive_expression PLUS multiplicative_expression */ -#line 660 "MachineIndependent/glslang.y" +#line 623 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5675,7 +5675,7 @@ yyreduce: break; case 51: /* additive_expression: additive_expression DASH multiplicative_expression */ -#line 665 "MachineIndependent/glslang.y" +#line 628 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5685,13 +5685,13 @@ yyreduce: break; case 52: /* shift_expression: additive_expression */ -#line 673 "MachineIndependent/glslang.y" +#line 636 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5691 "MachineIndependent/glslang_tab.cpp" break; case 53: /* shift_expression: shift_expression LEFT_OP additive_expression */ -#line 674 "MachineIndependent/glslang.y" +#line 637 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); @@ -5702,7 +5702,7 @@ yyreduce: break; case 54: /* shift_expression: shift_expression RIGHT_OP additive_expression */ -#line 680 "MachineIndependent/glslang.y" +#line 643 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); @@ -5713,13 +5713,13 @@ yyreduce: break; case 55: /* relational_expression: shift_expression */ -#line 689 "MachineIndependent/glslang.y" +#line 652 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5719 "MachineIndependent/glslang_tab.cpp" break; case 56: /* relational_expression: relational_expression LEFT_ANGLE shift_expression */ -#line 690 "MachineIndependent/glslang.y" +#line 653 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5729,7 +5729,7 @@ yyreduce: break; case 57: /* relational_expression: relational_expression RIGHT_ANGLE shift_expression */ -#line 695 "MachineIndependent/glslang.y" +#line 658 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5739,7 +5739,7 @@ yyreduce: break; case 58: /* relational_expression: relational_expression LE_OP shift_expression */ -#line 700 "MachineIndependent/glslang.y" +#line 663 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5749,7 +5749,7 @@ yyreduce: break; case 59: /* relational_expression: relational_expression GE_OP shift_expression */ -#line 705 "MachineIndependent/glslang.y" +#line 668 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5759,13 +5759,13 @@ yyreduce: break; case 60: /* equality_expression: relational_expression */ -#line 713 "MachineIndependent/glslang.y" +#line 676 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5765 "MachineIndependent/glslang_tab.cpp" break; case 61: /* equality_expression: equality_expression EQ_OP relational_expression */ -#line 714 "MachineIndependent/glslang.y" +#line 677 "MachineIndependent/glslang.y" { parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); @@ -5779,7 +5779,7 @@ yyreduce: break; case 62: /* equality_expression: equality_expression NE_OP relational_expression */ -#line 723 "MachineIndependent/glslang.y" +#line 686 "MachineIndependent/glslang.y" { parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); @@ -5793,13 +5793,13 @@ yyreduce: break; case 63: /* and_expression: equality_expression */ -#line 735 "MachineIndependent/glslang.y" +#line 698 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5799 "MachineIndependent/glslang_tab.cpp" break; case 64: /* and_expression: and_expression AMPERSAND equality_expression */ -#line 736 "MachineIndependent/glslang.y" +#line 699 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); @@ -5810,13 +5810,13 @@ yyreduce: break; case 65: /* exclusive_or_expression: and_expression */ -#line 745 "MachineIndependent/glslang.y" +#line 708 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5816 "MachineIndependent/glslang_tab.cpp" break; case 66: /* exclusive_or_expression: exclusive_or_expression CARET and_expression */ -#line 746 "MachineIndependent/glslang.y" +#line 709 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); @@ -5827,13 +5827,13 @@ yyreduce: break; case 67: /* inclusive_or_expression: exclusive_or_expression */ -#line 755 "MachineIndependent/glslang.y" +#line 718 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5833 "MachineIndependent/glslang_tab.cpp" break; case 68: /* inclusive_or_expression: inclusive_or_expression VERTICAL_BAR exclusive_or_expression */ -#line 756 "MachineIndependent/glslang.y" +#line 719 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); @@ -5844,13 +5844,13 @@ yyreduce: break; case 69: /* logical_and_expression: inclusive_or_expression */ -#line 765 "MachineIndependent/glslang.y" +#line 728 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5850 "MachineIndependent/glslang_tab.cpp" break; case 70: /* logical_and_expression: logical_and_expression AND_OP inclusive_or_expression */ -#line 766 "MachineIndependent/glslang.y" +#line 729 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5860,13 +5860,13 @@ yyreduce: break; case 71: /* logical_xor_expression: logical_and_expression */ -#line 774 "MachineIndependent/glslang.y" +#line 737 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5866 "MachineIndependent/glslang_tab.cpp" break; case 72: /* logical_xor_expression: logical_xor_expression XOR_OP logical_and_expression */ -#line 775 "MachineIndependent/glslang.y" +#line 738 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5876,13 +5876,13 @@ yyreduce: break; case 73: /* logical_or_expression: logical_xor_expression */ -#line 783 "MachineIndependent/glslang.y" +#line 746 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5882 "MachineIndependent/glslang_tab.cpp" break; case 74: /* logical_or_expression: logical_or_expression OR_OP logical_xor_expression */ -#line 784 "MachineIndependent/glslang.y" +#line 747 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) @@ -5892,13 +5892,13 @@ yyreduce: break; case 75: /* conditional_expression: logical_or_expression */ -#line 792 "MachineIndependent/glslang.y" +#line 755 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5898 "MachineIndependent/glslang_tab.cpp" break; case 76: /* $@1: %empty */ -#line 793 "MachineIndependent/glslang.y" +#line 756 "MachineIndependent/glslang.y" { ++parseContext.controlFlowNestingLevel; } @@ -5906,7 +5906,7 @@ yyreduce: break; case 77: /* conditional_expression: logical_or_expression QUESTION $@1 expression COLON assignment_expression */ -#line 796 "MachineIndependent/glslang.y" +#line 759 "MachineIndependent/glslang.y" { --parseContext.controlFlowNestingLevel; parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode)); @@ -5923,13 +5923,13 @@ yyreduce: break; case 78: /* assignment_expression: conditional_expression */ -#line 811 "MachineIndependent/glslang.y" +#line 774 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } #line 5929 "MachineIndependent/glslang_tab.cpp" break; case 79: /* assignment_expression: unary_expression assignment_operator assignment_expression */ -#line 812 "MachineIndependent/glslang.y" +#line 775 "MachineIndependent/glslang.y" { parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment"); parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); @@ -5947,7 +5947,7 @@ yyreduce: break; case 80: /* assignment_operator: EQUAL */ -#line 828 "MachineIndependent/glslang.y" +#line 791 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAssign; @@ -5956,7 +5956,7 @@ yyreduce: break; case 81: /* assignment_operator: MUL_ASSIGN */ -#line 832 "MachineIndependent/glslang.y" +#line 795 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpMulAssign; @@ -5965,7 +5965,7 @@ yyreduce: break; case 82: /* assignment_operator: DIV_ASSIGN */ -#line 836 "MachineIndependent/glslang.y" +#line 799 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpDivAssign; @@ -5974,7 +5974,7 @@ yyreduce: break; case 83: /* assignment_operator: MOD_ASSIGN */ -#line 840 "MachineIndependent/glslang.y" +#line 803 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%="); (yyval.interm).loc = (yyvsp[0].lex).loc; @@ -5984,7 +5984,7 @@ yyreduce: break; case 84: /* assignment_operator: ADD_ASSIGN */ -#line 845 "MachineIndependent/glslang.y" +#line 808 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAddAssign; @@ -5993,7 +5993,7 @@ yyreduce: break; case 85: /* assignment_operator: SUB_ASSIGN */ -#line 849 "MachineIndependent/glslang.y" +#line 812 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpSubAssign; @@ -6002,7 +6002,7 @@ yyreduce: break; case 86: /* assignment_operator: LEFT_ASSIGN */ -#line 853 "MachineIndependent/glslang.y" +#line 816 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign; @@ -6011,7 +6011,7 @@ yyreduce: break; case 87: /* assignment_operator: RIGHT_ASSIGN */ -#line 857 "MachineIndependent/glslang.y" +#line 820 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign; @@ -6020,7 +6020,7 @@ yyreduce: break; case 88: /* assignment_operator: AND_ASSIGN */ -#line 861 "MachineIndependent/glslang.y" +#line 824 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign; @@ -6029,7 +6029,7 @@ yyreduce: break; case 89: /* assignment_operator: XOR_ASSIGN */ -#line 865 "MachineIndependent/glslang.y" +#line 828 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign; @@ -6038,7 +6038,7 @@ yyreduce: break; case 90: /* assignment_operator: OR_ASSIGN */ -#line 869 "MachineIndependent/glslang.y" +#line 832 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign; @@ -6047,7 +6047,7 @@ yyreduce: break; case 91: /* expression: assignment_expression */ -#line 876 "MachineIndependent/glslang.y" +#line 839 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } @@ -6055,7 +6055,7 @@ yyreduce: break; case 92: /* expression: expression COMMA assignment_expression */ -#line 879 "MachineIndependent/glslang.y" +#line 842 "MachineIndependent/glslang.y" { parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); @@ -6068,7 +6068,7 @@ yyreduce: break; case 93: /* constant_expression: conditional_expression */ -#line 890 "MachineIndependent/glslang.y" +#line 853 "MachineIndependent/glslang.y" { parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), ""); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); @@ -6077,7 +6077,7 @@ yyreduce: break; case 94: /* declaration: function_prototype SEMICOLON */ -#line 897 "MachineIndependent/glslang.y" +#line 860 "MachineIndependent/glslang.y" { parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */); (yyval.interm.intermNode) = 0; @@ -6087,7 +6087,7 @@ yyreduce: break; case 95: /* declaration: spirv_instruction_qualifier function_prototype SEMICOLON */ -#line 903 "MachineIndependent/glslang.y" +#line 865 "MachineIndependent/glslang.y" { parseContext.requireExtensions((yyvsp[-1].interm).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V instruction qualifier"); (yyvsp[-1].interm).function->setSpirvInstruction(*(yyvsp[-2].interm.spirvInst)); // Attach SPIR-V intruction qualifier @@ -6099,7 +6099,7 @@ yyreduce: break; case 96: /* declaration: spirv_execution_mode_qualifier SEMICOLON */ -#line 910 "MachineIndependent/glslang.y" +#line 872 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "SPIR-V execution mode qualifier"); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V execution mode qualifier"); @@ -6109,7 +6109,7 @@ yyreduce: break; case 97: /* declaration: init_declarator_list SEMICOLON */ -#line 916 "MachineIndependent/glslang.y" +#line 877 "MachineIndependent/glslang.y" { if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate()) (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence); @@ -6119,7 +6119,7 @@ yyreduce: break; case 98: /* declaration: PRECISION precision_qualifier type_specifier SEMICOLON */ -#line 921 "MachineIndependent/glslang.y" +#line 882 "MachineIndependent/glslang.y" { parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement"); // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope @@ -6131,7 +6131,7 @@ yyreduce: break; case 99: /* declaration: block_structure SEMICOLON */ -#line 928 "MachineIndependent/glslang.y" +#line 889 "MachineIndependent/glslang.y" { parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList); (yyval.interm.intermNode) = 0; @@ -6140,7 +6140,7 @@ yyreduce: break; case 100: /* declaration: block_structure IDENTIFIER SEMICOLON */ -#line 932 "MachineIndependent/glslang.y" +#line 893 "MachineIndependent/glslang.y" { parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string); (yyval.interm.intermNode) = 0; @@ -6149,7 +6149,7 @@ yyreduce: break; case 101: /* declaration: block_structure IDENTIFIER array_specifier SEMICOLON */ -#line 936 "MachineIndependent/glslang.y" +#line 897 "MachineIndependent/glslang.y" { parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes); (yyval.interm.intermNode) = 0; @@ -6158,7 +6158,7 @@ yyreduce: break; case 102: /* declaration: type_qualifier SEMICOLON */ -#line 940 "MachineIndependent/glslang.y" +#line 901 "MachineIndependent/glslang.y" { parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type)); @@ -6168,7 +6168,7 @@ yyreduce: break; case 103: /* declaration: type_qualifier IDENTIFIER SEMICOLON */ -#line 945 "MachineIndependent/glslang.y" +#line 906 "MachineIndependent/glslang.y" { parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers); parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string); @@ -6178,7 +6178,7 @@ yyreduce: break; case 104: /* declaration: type_qualifier IDENTIFIER identifier_list SEMICOLON */ -#line 950 "MachineIndependent/glslang.y" +#line 911 "MachineIndependent/glslang.y" { parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers); (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string); @@ -6189,13 +6189,13 @@ yyreduce: break; case 105: /* $@2: %empty */ -#line 959 "MachineIndependent/glslang.y" +#line 920 "MachineIndependent/glslang.y" { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); } #line 6195 "MachineIndependent/glslang_tab.cpp" break; case 106: /* block_structure: type_qualifier IDENTIFIER LEFT_BRACE $@2 struct_declaration_list RIGHT_BRACE */ -#line 959 "MachineIndependent/glslang.y" +#line 920 "MachineIndependent/glslang.y" { --parseContext.blockNestingLevel; parseContext.blockName = (yyvsp[-4].lex).string; @@ -6209,7 +6209,7 @@ yyreduce: break; case 107: /* identifier_list: COMMA IDENTIFIER */ -#line 970 "MachineIndependent/glslang.y" +#line 931 "MachineIndependent/glslang.y" { (yyval.interm.identifierList) = new TIdentifierList; (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); @@ -6218,7 +6218,7 @@ yyreduce: break; case 108: /* identifier_list: identifier_list COMMA IDENTIFIER */ -#line 974 "MachineIndependent/glslang.y" +#line 935 "MachineIndependent/glslang.y" { (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList); (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); @@ -6227,66 +6227,67 @@ yyreduce: break; case 109: /* function_prototype: function_declarator RIGHT_PAREN */ -#line 981 "MachineIndependent/glslang.y" +#line 942 "MachineIndependent/glslang.y" { (yyval.interm).function = (yyvsp[-1].interm.function); + if (parseContext.compileOnly) (yyval.interm).function->setExport(); (yyval.interm).loc = (yyvsp[0].lex).loc; } -#line 6236 "MachineIndependent/glslang_tab.cpp" +#line 6237 "MachineIndependent/glslang_tab.cpp" break; case 110: /* function_prototype: function_declarator RIGHT_PAREN attribute */ -#line 985 "MachineIndependent/glslang.y" +#line 947 "MachineIndependent/glslang.y" { (yyval.interm).function = (yyvsp[-2].interm.function); + if (parseContext.compileOnly) (yyval.interm).function->setExport(); (yyval.interm).loc = (yyvsp[-1].lex).loc; - parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[0].interm.attributes)); } -#line 6247 "MachineIndependent/glslang_tab.cpp" +#line 6248 "MachineIndependent/glslang_tab.cpp" break; case 111: /* function_prototype: attribute function_declarator RIGHT_PAREN */ -#line 991 "MachineIndependent/glslang.y" +#line 953 "MachineIndependent/glslang.y" { (yyval.interm).function = (yyvsp[-1].interm.function); + if (parseContext.compileOnly) (yyval.interm).function->setExport(); (yyval.interm).loc = (yyvsp[0].lex).loc; - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.handleFunctionAttributes((yyvsp[0].lex).loc, *(yyvsp[-2].interm.attributes)); } -#line 6258 "MachineIndependent/glslang_tab.cpp" +#line 6259 "MachineIndependent/glslang_tab.cpp" break; case 112: /* function_prototype: attribute function_declarator RIGHT_PAREN attribute */ -#line 997 "MachineIndependent/glslang.y" +#line 959 "MachineIndependent/glslang.y" { (yyval.interm).function = (yyvsp[-2].interm.function); + if (parseContext.compileOnly) (yyval.interm).function->setExport(); (yyval.interm).loc = (yyvsp[-1].lex).loc; - parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[-3].interm.attributes)); parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[0].interm.attributes)); } -#line 6270 "MachineIndependent/glslang_tab.cpp" +#line 6271 "MachineIndependent/glslang_tab.cpp" break; case 113: /* function_declarator: function_header */ -#line 1007 "MachineIndependent/glslang.y" +#line 969 "MachineIndependent/glslang.y" { (yyval.interm.function) = (yyvsp[0].interm.function); } -#line 6278 "MachineIndependent/glslang_tab.cpp" +#line 6279 "MachineIndependent/glslang_tab.cpp" break; case 114: /* function_declarator: function_header_with_parameters */ -#line 1010 "MachineIndependent/glslang.y" +#line 972 "MachineIndependent/glslang.y" { (yyval.interm.function) = (yyvsp[0].interm.function); } -#line 6286 "MachineIndependent/glslang_tab.cpp" +#line 6287 "MachineIndependent/glslang_tab.cpp" break; case 115: /* function_header_with_parameters: function_header parameter_declaration */ -#line 1017 "MachineIndependent/glslang.y" +#line 979 "MachineIndependent/glslang.y" { // Add the parameter (yyval.interm.function) = (yyvsp[-1].interm.function); @@ -6295,11 +6296,11 @@ yyreduce: else delete (yyvsp[0].interm).param.type; } -#line 6299 "MachineIndependent/glslang_tab.cpp" +#line 6300 "MachineIndependent/glslang_tab.cpp" break; case 116: /* function_header_with_parameters: function_header_with_parameters COMMA parameter_declaration */ -#line 1025 "MachineIndependent/glslang.y" +#line 987 "MachineIndependent/glslang.y" { // // Only first parameter of one-parameter functions can be void @@ -6317,11 +6318,11 @@ yyreduce: (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param); } } -#line 6321 "MachineIndependent/glslang_tab.cpp" +#line 6322 "MachineIndependent/glslang_tab.cpp" break; case 117: /* function_header: fully_specified_type IDENTIFIER LEFT_PAREN */ -#line 1045 "MachineIndependent/glslang.y" +#line 1007 "MachineIndependent/glslang.y" { if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) { parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return", @@ -6341,11 +6342,11 @@ yyreduce: function = new TFunction((yyvsp[-1].lex).string, type); (yyval.interm.function) = function; } -#line 6345 "MachineIndependent/glslang_tab.cpp" +#line 6346 "MachineIndependent/glslang_tab.cpp" break; case 118: /* parameter_declarator: type_specifier IDENTIFIER */ -#line 1068 "MachineIndependent/glslang.y" +#line 1030 "MachineIndependent/glslang.y" { if ((yyvsp[-1].interm.type).arraySizes) { parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); @@ -6361,11 +6362,11 @@ yyreduce: (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).param = param; } -#line 6365 "MachineIndependent/glslang_tab.cpp" +#line 6366 "MachineIndependent/glslang_tab.cpp" break; case 119: /* parameter_declarator: type_specifier IDENTIFIER array_specifier */ -#line 1083 "MachineIndependent/glslang.y" +#line 1045 "MachineIndependent/glslang.y" { if ((yyvsp[-2].interm.type).arraySizes) { parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); @@ -6385,11 +6386,11 @@ yyreduce: (yyval.interm).loc = (yyvsp[-1].lex).loc; (yyval.interm).param = param; } -#line 6389 "MachineIndependent/glslang_tab.cpp" +#line 6390 "MachineIndependent/glslang_tab.cpp" break; case 120: /* parameter_declaration: type_qualifier parameter_declarator */ -#line 1108 "MachineIndependent/glslang.y" +#line 1070 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[0].interm); if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) @@ -6401,11 +6402,11 @@ yyreduce: parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); } -#line 6405 "MachineIndependent/glslang_tab.cpp" +#line 6406 "MachineIndependent/glslang_tab.cpp" break; case 121: /* parameter_declaration: parameter_declarator */ -#line 1119 "MachineIndependent/glslang.y" +#line 1081 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[0].interm); @@ -6413,11 +6414,11 @@ yyreduce: parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier(), (yyval.interm).param.type->isCoopMat()); } -#line 6417 "MachineIndependent/glslang_tab.cpp" +#line 6418 "MachineIndependent/glslang_tab.cpp" break; case 122: /* parameter_declaration: type_qualifier parameter_type_specifier */ -#line 1129 "MachineIndependent/glslang.y" +#line 1091 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[0].interm); if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) @@ -6428,11 +6429,11 @@ yyreduce: parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); } -#line 6432 "MachineIndependent/glslang_tab.cpp" +#line 6433 "MachineIndependent/glslang_tab.cpp" break; case 123: /* parameter_declaration: parameter_type_specifier */ -#line 1139 "MachineIndependent/glslang.y" +#line 1101 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[0].interm); @@ -6440,120 +6441,118 @@ yyreduce: parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier(), (yyval.interm).param.type->isCoopMat()); } -#line 6444 "MachineIndependent/glslang_tab.cpp" +#line 6445 "MachineIndependent/glslang_tab.cpp" break; case 124: /* parameter_type_specifier: type_specifier */ -#line 1149 "MachineIndependent/glslang.y" +#line 1111 "MachineIndependent/glslang.y" { TParameter param = { 0, new TType((yyvsp[0].interm.type)) }; (yyval.interm).param = param; if ((yyvsp[0].interm.type).arraySizes) parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes); } -#line 6455 "MachineIndependent/glslang_tab.cpp" +#line 6456 "MachineIndependent/glslang_tab.cpp" break; case 125: /* init_declarator_list: single_declaration */ -#line 1158 "MachineIndependent/glslang.y" +#line 1120 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[0].interm); } -#line 6463 "MachineIndependent/glslang_tab.cpp" +#line 6464 "MachineIndependent/glslang_tab.cpp" break; case 126: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER */ -#line 1161 "MachineIndependent/glslang.y" +#line 1123 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[-2].interm); parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type); } -#line 6472 "MachineIndependent/glslang_tab.cpp" +#line 6473 "MachineIndependent/glslang_tab.cpp" break; case 127: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER array_specifier */ -#line 1165 "MachineIndependent/glslang.y" +#line 1127 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[-3].interm); parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes); } -#line 6481 "MachineIndependent/glslang_tab.cpp" +#line 6482 "MachineIndependent/glslang_tab.cpp" break; case 128: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer */ -#line 1169 "MachineIndependent/glslang.y" +#line 1131 "MachineIndependent/glslang.y" { (yyval.interm).type = (yyvsp[-5].interm).type; TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc); } -#line 6491 "MachineIndependent/glslang_tab.cpp" +#line 6492 "MachineIndependent/glslang_tab.cpp" break; case 129: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER EQUAL initializer */ -#line 1174 "MachineIndependent/glslang.y" +#line 1136 "MachineIndependent/glslang.y" { (yyval.interm).type = (yyvsp[-4].interm).type; TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode)); (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc); } -#line 6501 "MachineIndependent/glslang_tab.cpp" +#line 6502 "MachineIndependent/glslang_tab.cpp" break; case 130: /* single_declaration: fully_specified_type */ -#line 1182 "MachineIndependent/glslang.y" +#line 1144 "MachineIndependent/glslang.y" { (yyval.interm).type = (yyvsp[0].interm.type); (yyval.interm).intermNode = 0; - parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type); - } -#line 6513 "MachineIndependent/glslang_tab.cpp" +#line 6512 "MachineIndependent/glslang_tab.cpp" break; case 131: /* single_declaration: fully_specified_type IDENTIFIER */ -#line 1189 "MachineIndependent/glslang.y" +#line 1149 "MachineIndependent/glslang.y" { (yyval.interm).type = (yyvsp[-1].interm.type); (yyval.interm).intermNode = 0; parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type)); } -#line 6523 "MachineIndependent/glslang_tab.cpp" +#line 6522 "MachineIndependent/glslang_tab.cpp" break; case 132: /* single_declaration: fully_specified_type IDENTIFIER array_specifier */ -#line 1194 "MachineIndependent/glslang.y" +#line 1154 "MachineIndependent/glslang.y" { (yyval.interm).type = (yyvsp[-2].interm.type); (yyval.interm).intermNode = 0; parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes); } -#line 6533 "MachineIndependent/glslang_tab.cpp" +#line 6532 "MachineIndependent/glslang_tab.cpp" break; case 133: /* single_declaration: fully_specified_type IDENTIFIER array_specifier EQUAL initializer */ -#line 1199 "MachineIndependent/glslang.y" +#line 1159 "MachineIndependent/glslang.y" { (yyval.interm).type = (yyvsp[-4].interm.type); TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); } -#line 6543 "MachineIndependent/glslang_tab.cpp" +#line 6542 "MachineIndependent/glslang_tab.cpp" break; case 134: /* single_declaration: fully_specified_type IDENTIFIER EQUAL initializer */ -#line 1204 "MachineIndependent/glslang.y" +#line 1164 "MachineIndependent/glslang.y" { (yyval.interm).type = (yyvsp[-3].interm.type); TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); } -#line 6553 "MachineIndependent/glslang_tab.cpp" +#line 6552 "MachineIndependent/glslang_tab.cpp" break; case 135: /* fully_specified_type: type_specifier */ -#line 1213 "MachineIndependent/glslang.y" +#line 1173 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[0].interm.type); @@ -6564,11 +6563,11 @@ yyreduce: } parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier, (yyval.interm.type).isCoopmat()); } -#line 6568 "MachineIndependent/glslang_tab.cpp" +#line 6567 "MachineIndependent/glslang_tab.cpp" break; case 136: /* fully_specified_type: type_qualifier type_specifier */ -#line 1223 "MachineIndependent/glslang.y" +#line 1183 "MachineIndependent/glslang.y" { parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, false, &(yyvsp[0].interm.type)); parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type)); @@ -6593,22 +6592,22 @@ yyreduce: (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn))) (yyval.interm.type).qualifier.smooth = true; } -#line 6597 "MachineIndependent/glslang_tab.cpp" +#line 6596 "MachineIndependent/glslang_tab.cpp" break; case 137: /* invariant_qualifier: INVARIANT */ -#line 1250 "MachineIndependent/glslang.y" +#line 1210 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "invariant"); parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.invariant = true; } -#line 6608 "MachineIndependent/glslang_tab.cpp" +#line 6607 "MachineIndependent/glslang_tab.cpp" break; case 138: /* interpolation_qualifier: SMOOTH */ -#line 1259 "MachineIndependent/glslang.y" +#line 1219 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "smooth"); parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth"); @@ -6616,11 +6615,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.smooth = true; } -#line 6620 "MachineIndependent/glslang_tab.cpp" +#line 6619 "MachineIndependent/glslang_tab.cpp" break; case 139: /* interpolation_qualifier: FLAT */ -#line 1266 "MachineIndependent/glslang.y" +#line 1226 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "flat"); parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat"); @@ -6628,11 +6627,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.flat = true; } -#line 6632 "MachineIndependent/glslang_tab.cpp" +#line 6631 "MachineIndependent/glslang_tab.cpp" break; case 140: /* interpolation_qualifier: NOPERSPECTIVE */ -#line 1274 "MachineIndependent/glslang.y" +#line 1233 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective"); parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective"); @@ -6640,11 +6639,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.nopersp = true; } -#line 6644 "MachineIndependent/glslang_tab.cpp" +#line 6643 "MachineIndependent/glslang_tab.cpp" break; case 141: /* interpolation_qualifier: EXPLICITINTERPAMD */ -#line 1281 "MachineIndependent/glslang.y" +#line 1240 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "__explicitInterpAMD"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); @@ -6652,11 +6651,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.explicitInterp = true; } -#line 6656 "MachineIndependent/glslang_tab.cpp" +#line 6655 "MachineIndependent/glslang_tab.cpp" break; case 142: /* interpolation_qualifier: PERVERTEXNV */ -#line 1288 "MachineIndependent/glslang.y" +#line 1247 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexNV"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); @@ -6665,11 +6664,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.pervertexNV = true; } -#line 6669 "MachineIndependent/glslang_tab.cpp" +#line 6668 "MachineIndependent/glslang_tab.cpp" break; case 143: /* interpolation_qualifier: PERVERTEXEXT */ -#line 1296 "MachineIndependent/glslang.y" +#line 1255 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexEXT"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric"); @@ -6678,11 +6677,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.pervertexEXT = true; } -#line 6682 "MachineIndependent/glslang_tab.cpp" +#line 6681 "MachineIndependent/glslang_tab.cpp" break; case 144: /* interpolation_qualifier: PERPRIMITIVENV */ -#line 1304 "MachineIndependent/glslang.y" +#line 1263 "MachineIndependent/glslang.y" { // No need for profile version or extension check. Shader stage already checks both. parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveNV"); @@ -6693,11 +6692,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.perPrimitiveNV = true; } -#line 6697 "MachineIndependent/glslang_tab.cpp" +#line 6696 "MachineIndependent/glslang_tab.cpp" break; case 145: /* interpolation_qualifier: PERPRIMITIVEEXT */ -#line 1314 "MachineIndependent/glslang.y" +#line 1273 "MachineIndependent/glslang.y" { // No need for profile version or extension check. Shader stage already checks both. parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveEXT"); @@ -6708,11 +6707,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.perPrimitiveNV = true; } -#line 6712 "MachineIndependent/glslang_tab.cpp" +#line 6711 "MachineIndependent/glslang_tab.cpp" break; case 146: /* interpolation_qualifier: PERVIEWNV */ -#line 1324 "MachineIndependent/glslang.y" +#line 1283 "MachineIndependent/glslang.y" { // No need for profile version or extension check. Shader stage already checks both. parseContext.globalCheck((yyvsp[0].lex).loc, "perviewNV"); @@ -6720,11 +6719,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.perViewNV = true; } -#line 6724 "MachineIndependent/glslang_tab.cpp" +#line 6723 "MachineIndependent/glslang_tab.cpp" break; case 147: /* interpolation_qualifier: PERTASKNV */ -#line 1331 "MachineIndependent/glslang.y" +#line 1290 "MachineIndependent/glslang.y" { // No need for profile version or extension check. Shader stage already checks both. parseContext.globalCheck((yyvsp[0].lex).loc, "taskNV"); @@ -6732,84 +6731,84 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.perTaskNV = true; } -#line 6736 "MachineIndependent/glslang_tab.cpp" +#line 6735 "MachineIndependent/glslang_tab.cpp" break; case 148: /* layout_qualifier: LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN */ -#line 1342 "MachineIndependent/glslang.y" +#line 1300 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[-1].interm.type); } -#line 6744 "MachineIndependent/glslang_tab.cpp" +#line 6743 "MachineIndependent/glslang_tab.cpp" break; case 149: /* layout_qualifier_id_list: layout_qualifier_id */ -#line 1348 "MachineIndependent/glslang.y" +#line 1306 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6752 "MachineIndependent/glslang_tab.cpp" +#line 6751 "MachineIndependent/glslang_tab.cpp" break; case 150: /* layout_qualifier_id_list: layout_qualifier_id_list COMMA layout_qualifier_id */ -#line 1351 "MachineIndependent/glslang.y" +#line 1309 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[-2].interm.type); (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); } -#line 6762 "MachineIndependent/glslang_tab.cpp" +#line 6761 "MachineIndependent/glslang_tab.cpp" break; case 151: /* layout_qualifier_id: IDENTIFIER */ -#line 1358 "MachineIndependent/glslang.y" +#line 1316 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string); } -#line 6771 "MachineIndependent/glslang_tab.cpp" +#line 6770 "MachineIndependent/glslang_tab.cpp" break; case 152: /* layout_qualifier_id: IDENTIFIER EQUAL constant_expression */ -#line 1362 "MachineIndependent/glslang.y" +#line 1320 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-2].lex).loc); parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode)); } -#line 6780 "MachineIndependent/glslang_tab.cpp" +#line 6779 "MachineIndependent/glslang_tab.cpp" break; case 153: /* layout_qualifier_id: SHARED */ -#line 1366 "MachineIndependent/glslang.y" +#line 1324 "MachineIndependent/glslang.y" { // because "shared" is both an identifier and a keyword (yyval.interm.type).init((yyvsp[0].lex).loc); TString strShared("shared"); parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared); } -#line 6790 "MachineIndependent/glslang_tab.cpp" +#line 6789 "MachineIndependent/glslang_tab.cpp" break; case 154: /* precise_qualifier: PRECISE */ -#line 1375 "MachineIndependent/glslang.y" +#line 1332 "MachineIndependent/glslang.y" { parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise"); parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.noContraction = true; } -#line 6801 "MachineIndependent/glslang_tab.cpp" +#line 6800 "MachineIndependent/glslang_tab.cpp" break; case 155: /* type_qualifier: single_type_qualifier */ -#line 1385 "MachineIndependent/glslang.y" +#line 1341 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6809 "MachineIndependent/glslang_tab.cpp" +#line 6808 "MachineIndependent/glslang_tab.cpp" break; case 156: /* type_qualifier: type_qualifier single_type_qualifier */ -#line 1388 "MachineIndependent/glslang.y" +#line 1344 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[-1].interm.type); if ((yyval.interm.type).basicType == EbtVoid) @@ -6818,151 +6817,151 @@ yyreduce: (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); } -#line 6822 "MachineIndependent/glslang_tab.cpp" +#line 6821 "MachineIndependent/glslang_tab.cpp" break; case 157: /* single_type_qualifier: storage_qualifier */ -#line 1399 "MachineIndependent/glslang.y" +#line 1355 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6830 "MachineIndependent/glslang_tab.cpp" +#line 6829 "MachineIndependent/glslang_tab.cpp" break; case 158: /* single_type_qualifier: layout_qualifier */ -#line 1402 "MachineIndependent/glslang.y" +#line 1358 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6838 "MachineIndependent/glslang_tab.cpp" +#line 6837 "MachineIndependent/glslang_tab.cpp" break; case 159: /* single_type_qualifier: precision_qualifier */ -#line 1405 "MachineIndependent/glslang.y" +#line 1361 "MachineIndependent/glslang.y" { parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision); (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6847 "MachineIndependent/glslang_tab.cpp" +#line 6846 "MachineIndependent/glslang_tab.cpp" break; case 160: /* single_type_qualifier: interpolation_qualifier */ -#line 1409 "MachineIndependent/glslang.y" +#line 1365 "MachineIndependent/glslang.y" { // allow inheritance of storage qualifier from block declaration (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6856 "MachineIndependent/glslang_tab.cpp" +#line 6855 "MachineIndependent/glslang_tab.cpp" break; case 161: /* single_type_qualifier: invariant_qualifier */ -#line 1413 "MachineIndependent/glslang.y" +#line 1369 "MachineIndependent/glslang.y" { // allow inheritance of storage qualifier from block declaration (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6865 "MachineIndependent/glslang_tab.cpp" +#line 6864 "MachineIndependent/glslang_tab.cpp" break; case 162: /* single_type_qualifier: precise_qualifier */ -#line 1418 "MachineIndependent/glslang.y" +#line 1373 "MachineIndependent/glslang.y" { // allow inheritance of storage qualifier from block declaration (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6874 "MachineIndependent/glslang_tab.cpp" +#line 6873 "MachineIndependent/glslang_tab.cpp" break; case 163: /* single_type_qualifier: non_uniform_qualifier */ -#line 1422 "MachineIndependent/glslang.y" +#line 1377 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6882 "MachineIndependent/glslang_tab.cpp" +#line 6881 "MachineIndependent/glslang_tab.cpp" break; case 164: /* single_type_qualifier: spirv_storage_class_qualifier */ -#line 1425 "MachineIndependent/glslang.y" +#line 1380 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].interm.type).loc, "spirv_storage_class"); parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V storage class qualifier"); (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6892 "MachineIndependent/glslang_tab.cpp" +#line 6891 "MachineIndependent/glslang_tab.cpp" break; case 165: /* single_type_qualifier: spirv_decorate_qualifier */ -#line 1430 "MachineIndependent/glslang.y" +#line 1385 "MachineIndependent/glslang.y" { parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V decorate qualifier"); (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 6901 "MachineIndependent/glslang_tab.cpp" +#line 6900 "MachineIndependent/glslang_tab.cpp" break; case 166: /* single_type_qualifier: SPIRV_BY_REFERENCE */ -#line 1434 "MachineIndependent/glslang.y" +#line 1389 "MachineIndependent/glslang.y" { parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_reference"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.setSpirvByReference(); } -#line 6911 "MachineIndependent/glslang_tab.cpp" +#line 6910 "MachineIndependent/glslang_tab.cpp" break; case 167: /* single_type_qualifier: SPIRV_LITERAL */ -#line 1439 "MachineIndependent/glslang.y" +#line 1394 "MachineIndependent/glslang.y" { parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_literal"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.setSpirvLiteral(); } -#line 6921 "MachineIndependent/glslang_tab.cpp" +#line 6920 "MachineIndependent/glslang_tab.cpp" break; case 168: /* storage_qualifier: CONST */ -#line 1448 "MachineIndependent/glslang.y" +#line 1402 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant } -#line 6930 "MachineIndependent/glslang_tab.cpp" +#line 6929 "MachineIndependent/glslang_tab.cpp" break; case 169: /* storage_qualifier: INOUT */ -#line 1452 "MachineIndependent/glslang.y" +#line 1406 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "inout"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqInOut; } -#line 6940 "MachineIndependent/glslang_tab.cpp" +#line 6939 "MachineIndependent/glslang_tab.cpp" break; case 170: /* storage_qualifier: IN */ -#line 1457 "MachineIndependent/glslang.y" +#line 1411 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "in"); (yyval.interm.type).init((yyvsp[0].lex).loc); // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later (yyval.interm.type).qualifier.storage = EvqIn; } -#line 6951 "MachineIndependent/glslang_tab.cpp" +#line 6950 "MachineIndependent/glslang_tab.cpp" break; case 171: /* storage_qualifier: OUT */ -#line 1463 "MachineIndependent/glslang.y" +#line 1417 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "out"); (yyval.interm.type).init((yyvsp[0].lex).loc); // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later (yyval.interm.type).qualifier.storage = EvqOut; } -#line 6962 "MachineIndependent/glslang_tab.cpp" +#line 6961 "MachineIndependent/glslang_tab.cpp" break; case 172: /* storage_qualifier: CENTROID */ -#line 1469 "MachineIndependent/glslang.y" +#line 1423 "MachineIndependent/glslang.y" { parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid"); parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid"); @@ -6970,31 +6969,31 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.centroid = true; } -#line 6974 "MachineIndependent/glslang_tab.cpp" +#line 6973 "MachineIndependent/glslang_tab.cpp" break; case 173: /* storage_qualifier: UNIFORM */ -#line 1476 "MachineIndependent/glslang.y" +#line 1430 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "uniform"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqUniform; } -#line 6984 "MachineIndependent/glslang_tab.cpp" +#line 6983 "MachineIndependent/glslang_tab.cpp" break; case 174: /* storage_qualifier: TILEIMAGEEXT */ -#line 1481 "MachineIndependent/glslang.y" +#line 1435 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "tileImageEXT"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqTileImageEXT; } -#line 6994 "MachineIndependent/glslang_tab.cpp" +#line 6993 "MachineIndependent/glslang_tab.cpp" break; case 175: /* storage_qualifier: SHARED */ -#line 1486 "MachineIndependent/glslang.y" +#line 1440 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "shared"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); @@ -7003,21 +7002,21 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqShared; } -#line 7007 "MachineIndependent/glslang_tab.cpp" +#line 7006 "MachineIndependent/glslang_tab.cpp" break; case 176: /* storage_qualifier: BUFFER */ -#line 1494 "MachineIndependent/glslang.y" +#line 1448 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "buffer"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqBuffer; } -#line 7017 "MachineIndependent/glslang_tab.cpp" +#line 7016 "MachineIndependent/glslang_tab.cpp" break; case 177: /* storage_qualifier: ATTRIBUTE */ -#line 1500 "MachineIndependent/glslang.y" +#line 1453 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute"); parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute"); @@ -7030,11 +7029,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqVaryingIn; } -#line 7034 "MachineIndependent/glslang_tab.cpp" +#line 7033 "MachineIndependent/glslang_tab.cpp" break; case 178: /* storage_qualifier: VARYING */ -#line 1512 "MachineIndependent/glslang.y" +#line 1465 "MachineIndependent/glslang.y" { parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying"); parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying"); @@ -7049,32 +7048,32 @@ yyreduce: else (yyval.interm.type).qualifier.storage = EvqVaryingIn; } -#line 7053 "MachineIndependent/glslang_tab.cpp" +#line 7052 "MachineIndependent/glslang_tab.cpp" break; case 179: /* storage_qualifier: PATCH */ -#line 1526 "MachineIndependent/glslang.y" +#line 1479 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "patch"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.patch = true; } -#line 7064 "MachineIndependent/glslang_tab.cpp" +#line 7063 "MachineIndependent/glslang_tab.cpp" break; case 180: /* storage_qualifier: SAMPLE */ -#line 1532 "MachineIndependent/glslang.y" +#line 1485 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "sample"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.sample = true; } -#line 7074 "MachineIndependent/glslang_tab.cpp" +#line 7073 "MachineIndependent/glslang_tab.cpp" break; case 181: /* storage_qualifier: HITATTRNV */ -#line 1537 "MachineIndependent/glslang.y" +#line 1490 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask @@ -7083,11 +7082,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqHitAttr; } -#line 7087 "MachineIndependent/glslang_tab.cpp" +#line 7086 "MachineIndependent/glslang_tab.cpp" break; case 182: /* storage_qualifier: HITOBJECTATTRNV */ -#line 1545 "MachineIndependent/glslang.y" +#line 1498 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask @@ -7096,11 +7095,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqHitObjectAttrNV; } -#line 7100 "MachineIndependent/glslang_tab.cpp" +#line 7099 "MachineIndependent/glslang_tab.cpp" break; case 183: /* storage_qualifier: HITATTREXT */ -#line 1553 "MachineIndependent/glslang.y" +#line 1506 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeEXT"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask @@ -7109,11 +7108,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqHitAttr; } -#line 7113 "MachineIndependent/glslang_tab.cpp" +#line 7112 "MachineIndependent/glslang_tab.cpp" break; case 184: /* storage_qualifier: PAYLOADNV */ -#line 1561 "MachineIndependent/glslang.y" +#line 1514 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadNV"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | @@ -7122,11 +7121,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqPayload; } -#line 7126 "MachineIndependent/glslang_tab.cpp" +#line 7125 "MachineIndependent/glslang_tab.cpp" break; case 185: /* storage_qualifier: PAYLOADEXT */ -#line 1569 "MachineIndependent/glslang.y" +#line 1522 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadEXT"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | @@ -7135,11 +7134,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqPayload; } -#line 7139 "MachineIndependent/glslang_tab.cpp" +#line 7138 "MachineIndependent/glslang_tab.cpp" break; case 186: /* storage_qualifier: PAYLOADINNV */ -#line 1577 "MachineIndependent/glslang.y" +#line 1530 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInNV"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask | @@ -7148,11 +7147,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqPayloadIn; } -#line 7152 "MachineIndependent/glslang_tab.cpp" +#line 7151 "MachineIndependent/glslang_tab.cpp" break; case 187: /* storage_qualifier: PAYLOADINEXT */ -#line 1585 "MachineIndependent/glslang.y" +#line 1538 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInEXT"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask | @@ -7161,11 +7160,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqPayloadIn; } -#line 7165 "MachineIndependent/glslang_tab.cpp" +#line 7164 "MachineIndependent/glslang_tab.cpp" break; case 188: /* storage_qualifier: CALLDATANV */ -#line 1593 "MachineIndependent/glslang.y" +#line 1546 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataNV"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | @@ -7174,11 +7173,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqCallableData; } -#line 7178 "MachineIndependent/glslang_tab.cpp" +#line 7177 "MachineIndependent/glslang_tab.cpp" break; case 189: /* storage_qualifier: CALLDATAEXT */ -#line 1601 "MachineIndependent/glslang.y" +#line 1554 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataEXT"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | @@ -7187,11 +7186,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqCallableData; } -#line 7191 "MachineIndependent/glslang_tab.cpp" +#line 7190 "MachineIndependent/glslang_tab.cpp" break; case 190: /* storage_qualifier: CALLDATAINNV */ -#line 1609 "MachineIndependent/glslang.y" +#line 1562 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInNV"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); @@ -7199,11 +7198,11 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqCallableDataIn; } -#line 7203 "MachineIndependent/glslang_tab.cpp" +#line 7202 "MachineIndependent/glslang_tab.cpp" break; case 191: /* storage_qualifier: CALLDATAINEXT */ -#line 1616 "MachineIndependent/glslang.y" +#line 1569 "MachineIndependent/glslang.y" { parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInEXT"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); @@ -7211,138 +7210,138 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqCallableDataIn; } -#line 7215 "MachineIndependent/glslang_tab.cpp" +#line 7214 "MachineIndependent/glslang_tab.cpp" break; case 192: /* storage_qualifier: COHERENT */ -#line 1623 "MachineIndependent/glslang.y" +#line 1576 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.coherent = true; } -#line 7224 "MachineIndependent/glslang_tab.cpp" +#line 7223 "MachineIndependent/glslang_tab.cpp" break; case 193: /* storage_qualifier: DEVICECOHERENT */ -#line 1627 "MachineIndependent/glslang.y" +#line 1580 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent"); (yyval.interm.type).qualifier.devicecoherent = true; } -#line 7234 "MachineIndependent/glslang_tab.cpp" +#line 7233 "MachineIndependent/glslang_tab.cpp" break; case 194: /* storage_qualifier: QUEUEFAMILYCOHERENT */ -#line 1632 "MachineIndependent/glslang.y" +#line 1585 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent"); (yyval.interm.type).qualifier.queuefamilycoherent = true; } -#line 7244 "MachineIndependent/glslang_tab.cpp" +#line 7243 "MachineIndependent/glslang_tab.cpp" break; case 195: /* storage_qualifier: WORKGROUPCOHERENT */ -#line 1637 "MachineIndependent/glslang.y" +#line 1590 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent"); (yyval.interm.type).qualifier.workgroupcoherent = true; } -#line 7254 "MachineIndependent/glslang_tab.cpp" +#line 7253 "MachineIndependent/glslang_tab.cpp" break; case 196: /* storage_qualifier: SUBGROUPCOHERENT */ -#line 1642 "MachineIndependent/glslang.y" +#line 1595 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent"); (yyval.interm.type).qualifier.subgroupcoherent = true; } -#line 7264 "MachineIndependent/glslang_tab.cpp" +#line 7263 "MachineIndependent/glslang_tab.cpp" break; case 197: /* storage_qualifier: NONPRIVATE */ -#line 1647 "MachineIndependent/glslang.y" +#line 1600 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); (yyval.interm.type).qualifier.nonprivate = true; } -#line 7274 "MachineIndependent/glslang_tab.cpp" +#line 7273 "MachineIndependent/glslang_tab.cpp" break; case 198: /* storage_qualifier: SHADERCALLCOHERENT */ -#line 1652 "MachineIndependent/glslang.y" +#line 1605 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); (yyval.interm.type).qualifier.shadercallcoherent = true; } -#line 7284 "MachineIndependent/glslang_tab.cpp" +#line 7283 "MachineIndependent/glslang_tab.cpp" break; case 199: /* storage_qualifier: VOLATILE */ -#line 1657 "MachineIndependent/glslang.y" +#line 1610 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.volatil = true; } -#line 7293 "MachineIndependent/glslang_tab.cpp" +#line 7292 "MachineIndependent/glslang_tab.cpp" break; case 200: /* storage_qualifier: RESTRICT */ -#line 1661 "MachineIndependent/glslang.y" +#line 1614 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.restrict = true; } -#line 7302 "MachineIndependent/glslang_tab.cpp" +#line 7301 "MachineIndependent/glslang_tab.cpp" break; case 201: /* storage_qualifier: READONLY */ -#line 1665 "MachineIndependent/glslang.y" +#line 1618 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.readonly = true; } -#line 7311 "MachineIndependent/glslang_tab.cpp" +#line 7310 "MachineIndependent/glslang_tab.cpp" break; case 202: /* storage_qualifier: WRITEONLY */ -#line 1669 "MachineIndependent/glslang.y" +#line 1622 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.writeonly = true; } -#line 7320 "MachineIndependent/glslang_tab.cpp" +#line 7319 "MachineIndependent/glslang_tab.cpp" break; case 203: /* storage_qualifier: SUBROUTINE */ -#line 1673 "MachineIndependent/glslang.y" +#line 1626 "MachineIndependent/glslang.y" { parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine"); parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine"); parseContext.unimplemented((yyvsp[0].lex).loc, "subroutine"); (yyval.interm.type).init((yyvsp[0].lex).loc); } -#line 7331 "MachineIndependent/glslang_tab.cpp" +#line 7330 "MachineIndependent/glslang_tab.cpp" break; case 204: /* storage_qualifier: SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN */ -#line 1679 "MachineIndependent/glslang.y" +#line 1632 "MachineIndependent/glslang.y" { parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine"); parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine"); parseContext.unimplemented((yyvsp[-3].lex).loc, "subroutine"); (yyval.interm.type).init((yyvsp[-3].lex).loc); } -#line 7342 "MachineIndependent/glslang_tab.cpp" +#line 7341 "MachineIndependent/glslang_tab.cpp" break; case 205: /* storage_qualifier: TASKPAYLOADWORKGROUPEXT */ -#line 1685 "MachineIndependent/glslang.y" +#line 1638 "MachineIndependent/glslang.y" { // No need for profile version or extension check. Shader stage already checks both. parseContext.globalCheck((yyvsp[0].lex).loc, "taskPayloadSharedEXT"); @@ -7350,38 +7349,38 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqtaskPayloadSharedEXT; } -#line 7354 "MachineIndependent/glslang_tab.cpp" +#line 7353 "MachineIndependent/glslang_tab.cpp" break; case 206: /* non_uniform_qualifier: NONUNIFORM */ -#line 1697 "MachineIndependent/glslang.y" +#line 1648 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.nonUniform = true; } -#line 7363 "MachineIndependent/glslang_tab.cpp" +#line 7362 "MachineIndependent/glslang_tab.cpp" break; case 207: /* type_name_list: IDENTIFIER */ -#line 1704 "MachineIndependent/glslang.y" +#line 1655 "MachineIndependent/glslang.y" { // TODO } -#line 7371 "MachineIndependent/glslang_tab.cpp" +#line 7370 "MachineIndependent/glslang_tab.cpp" break; case 208: /* type_name_list: type_name_list COMMA IDENTIFIER */ -#line 1707 "MachineIndependent/glslang.y" +#line 1658 "MachineIndependent/glslang.y" { // TODO: 4.0 semantics: subroutines // 1) make sure each identifier is a type declared earlier with SUBROUTINE // 2) save all of the identifiers for future comparison with the declared function } -#line 7381 "MachineIndependent/glslang_tab.cpp" +#line 7380 "MachineIndependent/glslang_tab.cpp" break; case 209: /* type_specifier: type_specifier_nonarray type_parameter_specifier_opt */ -#line 1716 "MachineIndependent/glslang.y" +#line 1666 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[-1].interm.type); (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); @@ -7389,11 +7388,11 @@ yyreduce: parseContext.coopMatTypeParametersCheck((yyvsp[-1].interm.type).loc, (yyval.interm.type)); } -#line 7393 "MachineIndependent/glslang_tab.cpp" +#line 7392 "MachineIndependent/glslang_tab.cpp" break; case 210: /* type_specifier: type_specifier_nonarray type_parameter_specifier_opt array_specifier */ -#line 1723 "MachineIndependent/glslang.y" +#line 1673 "MachineIndependent/glslang.y" { parseContext.arrayOfArrayVersionCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes); (yyval.interm.type) = (yyvsp[-2].interm.type); @@ -7402,21 +7401,21 @@ yyreduce: (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes; parseContext.coopMatTypeParametersCheck((yyvsp[-2].interm.type).loc, (yyval.interm.type)); } -#line 7406 "MachineIndependent/glslang_tab.cpp" +#line 7405 "MachineIndependent/glslang_tab.cpp" break; case 211: /* array_specifier: LEFT_BRACKET RIGHT_BRACKET */ -#line 1734 "MachineIndependent/glslang.y" +#line 1684 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[-1].lex).loc; (yyval.interm).arraySizes = new TArraySizes; (yyval.interm).arraySizes->addInnerSize(); } -#line 7416 "MachineIndependent/glslang_tab.cpp" +#line 7415 "MachineIndependent/glslang_tab.cpp" break; case 212: /* array_specifier: LEFT_BRACKET conditional_expression RIGHT_BRACKET */ -#line 1739 "MachineIndependent/glslang.y" +#line 1689 "MachineIndependent/glslang.y" { (yyval.interm).loc = (yyvsp[-2].lex).loc; (yyval.interm).arraySizes = new TArraySizes; @@ -7425,20 +7424,20 @@ yyreduce: parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); (yyval.interm).arraySizes->addInnerSize(size); } -#line 7429 "MachineIndependent/glslang_tab.cpp" +#line 7428 "MachineIndependent/glslang_tab.cpp" break; case 213: /* array_specifier: array_specifier LEFT_BRACKET RIGHT_BRACKET */ -#line 1747 "MachineIndependent/glslang.y" +#line 1697 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[-2].interm); (yyval.interm).arraySizes->addInnerSize(); } -#line 7438 "MachineIndependent/glslang_tab.cpp" +#line 7437 "MachineIndependent/glslang_tab.cpp" break; case 214: /* array_specifier: array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET */ -#line 1751 "MachineIndependent/glslang.y" +#line 1701 "MachineIndependent/glslang.y" { (yyval.interm) = (yyvsp[-3].interm); @@ -7446,45 +7445,45 @@ yyreduce: parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); (yyval.interm).arraySizes->addInnerSize(size); } -#line 7450 "MachineIndependent/glslang_tab.cpp" +#line 7449 "MachineIndependent/glslang_tab.cpp" break; case 215: /* type_parameter_specifier_opt: type_parameter_specifier */ -#line 1761 "MachineIndependent/glslang.y" +#line 1711 "MachineIndependent/glslang.y" { (yyval.interm.typeParameters) = (yyvsp[0].interm.typeParameters); } -#line 7458 "MachineIndependent/glslang_tab.cpp" +#line 7457 "MachineIndependent/glslang_tab.cpp" break; case 216: /* type_parameter_specifier_opt: %empty */ -#line 1764 "MachineIndependent/glslang.y" +#line 1714 "MachineIndependent/glslang.y" { (yyval.interm.typeParameters) = 0; } -#line 7466 "MachineIndependent/glslang_tab.cpp" +#line 7465 "MachineIndependent/glslang_tab.cpp" break; case 217: /* type_parameter_specifier: LEFT_ANGLE type_parameter_specifier_list RIGHT_ANGLE */ -#line 1770 "MachineIndependent/glslang.y" +#line 1720 "MachineIndependent/glslang.y" { (yyval.interm.typeParameters) = (yyvsp[-1].interm.typeParameters); } -#line 7474 "MachineIndependent/glslang_tab.cpp" +#line 7473 "MachineIndependent/glslang_tab.cpp" break; case 218: /* type_parameter_specifier_list: type_specifier */ -#line 1776 "MachineIndependent/glslang.y" +#line 1726 "MachineIndependent/glslang.y" { (yyval.interm.typeParameters) = new TTypeParameters; (yyval.interm.typeParameters)->arraySizes = new TArraySizes; (yyval.interm.typeParameters)->basicType = (yyvsp[0].interm.type).basicType; } -#line 7484 "MachineIndependent/glslang_tab.cpp" +#line 7483 "MachineIndependent/glslang_tab.cpp" break; case 219: /* type_parameter_specifier_list: unary_expression */ -#line 1781 "MachineIndependent/glslang.y" +#line 1731 "MachineIndependent/glslang.y" { (yyval.interm.typeParameters) = new TTypeParameters; (yyval.interm.typeParameters)->arraySizes = new TArraySizes; @@ -7493,11 +7492,11 @@ yyreduce: parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter", true); (yyval.interm.typeParameters)->arraySizes->addInnerSize(size); } -#line 7497 "MachineIndependent/glslang_tab.cpp" +#line 7496 "MachineIndependent/glslang_tab.cpp" break; case 220: /* type_parameter_specifier_list: type_parameter_specifier_list COMMA unary_expression */ -#line 1789 "MachineIndependent/glslang.y" +#line 1739 "MachineIndependent/glslang.y" { (yyval.interm.typeParameters) = (yyvsp[-2].interm.typeParameters); @@ -7505,300 +7504,300 @@ yyreduce: parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter", true); (yyval.interm.typeParameters)->arraySizes->addInnerSize(size); } -#line 7509 "MachineIndependent/glslang_tab.cpp" +#line 7508 "MachineIndependent/glslang_tab.cpp" break; case 221: /* type_specifier_nonarray: VOID */ -#line 1799 "MachineIndependent/glslang.y" +#line 1749 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtVoid; } -#line 7518 "MachineIndependent/glslang_tab.cpp" +#line 7517 "MachineIndependent/glslang_tab.cpp" break; case 222: /* type_specifier_nonarray: FLOAT */ -#line 1803 "MachineIndependent/glslang.y" +#line 1753 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; } -#line 7527 "MachineIndependent/glslang_tab.cpp" +#line 7526 "MachineIndependent/glslang_tab.cpp" break; case 223: /* type_specifier_nonarray: INT */ -#line 1807 "MachineIndependent/glslang.y" +#line 1757 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; } -#line 7536 "MachineIndependent/glslang_tab.cpp" +#line 7535 "MachineIndependent/glslang_tab.cpp" break; case 224: /* type_specifier_nonarray: UINT */ -#line 1811 "MachineIndependent/glslang.y" +#line 1761 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; } -#line 7546 "MachineIndependent/glslang_tab.cpp" +#line 7545 "MachineIndependent/glslang_tab.cpp" break; case 225: /* type_specifier_nonarray: BOOL */ -#line 1816 "MachineIndependent/glslang.y" +#line 1766 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtBool; } -#line 7555 "MachineIndependent/glslang_tab.cpp" +#line 7554 "MachineIndependent/glslang_tab.cpp" break; case 226: /* type_specifier_nonarray: VEC2 */ -#line 1820 "MachineIndependent/glslang.y" +#line 1770 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(2); } -#line 7565 "MachineIndependent/glslang_tab.cpp" +#line 7564 "MachineIndependent/glslang_tab.cpp" break; case 227: /* type_specifier_nonarray: VEC3 */ -#line 1825 "MachineIndependent/glslang.y" +#line 1775 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(3); } -#line 7575 "MachineIndependent/glslang_tab.cpp" +#line 7574 "MachineIndependent/glslang_tab.cpp" break; case 228: /* type_specifier_nonarray: VEC4 */ -#line 1830 "MachineIndependent/glslang.y" +#line 1780 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(4); } -#line 7585 "MachineIndependent/glslang_tab.cpp" +#line 7584 "MachineIndependent/glslang_tab.cpp" break; case 229: /* type_specifier_nonarray: BVEC2 */ -#line 1835 "MachineIndependent/glslang.y" +#line 1785 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtBool; (yyval.interm.type).setVector(2); } -#line 7595 "MachineIndependent/glslang_tab.cpp" +#line 7594 "MachineIndependent/glslang_tab.cpp" break; case 230: /* type_specifier_nonarray: BVEC3 */ -#line 1840 "MachineIndependent/glslang.y" +#line 1790 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtBool; (yyval.interm.type).setVector(3); } -#line 7605 "MachineIndependent/glslang_tab.cpp" +#line 7604 "MachineIndependent/glslang_tab.cpp" break; case 231: /* type_specifier_nonarray: BVEC4 */ -#line 1845 "MachineIndependent/glslang.y" +#line 1795 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtBool; (yyval.interm.type).setVector(4); } -#line 7615 "MachineIndependent/glslang_tab.cpp" +#line 7614 "MachineIndependent/glslang_tab.cpp" break; case 232: /* type_specifier_nonarray: IVEC2 */ -#line 1850 "MachineIndependent/glslang.y" +#line 1800 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(2); } -#line 7625 "MachineIndependent/glslang_tab.cpp" +#line 7624 "MachineIndependent/glslang_tab.cpp" break; case 233: /* type_specifier_nonarray: IVEC3 */ -#line 1855 "MachineIndependent/glslang.y" +#line 1805 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(3); } -#line 7635 "MachineIndependent/glslang_tab.cpp" +#line 7634 "MachineIndependent/glslang_tab.cpp" break; case 234: /* type_specifier_nonarray: IVEC4 */ -#line 1860 "MachineIndependent/glslang.y" +#line 1810 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(4); } -#line 7645 "MachineIndependent/glslang_tab.cpp" +#line 7644 "MachineIndependent/glslang_tab.cpp" break; case 235: /* type_specifier_nonarray: UVEC2 */ -#line 1865 "MachineIndependent/glslang.y" +#line 1815 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(2); } -#line 7656 "MachineIndependent/glslang_tab.cpp" +#line 7655 "MachineIndependent/glslang_tab.cpp" break; case 236: /* type_specifier_nonarray: UVEC3 */ -#line 1871 "MachineIndependent/glslang.y" +#line 1821 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(3); } -#line 7667 "MachineIndependent/glslang_tab.cpp" +#line 7666 "MachineIndependent/glslang_tab.cpp" break; case 237: /* type_specifier_nonarray: UVEC4 */ -#line 1877 "MachineIndependent/glslang.y" +#line 1827 "MachineIndependent/glslang.y" { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(4); } -#line 7678 "MachineIndependent/glslang_tab.cpp" +#line 7677 "MachineIndependent/glslang_tab.cpp" break; case 238: /* type_specifier_nonarray: MAT2 */ -#line 1883 "MachineIndependent/glslang.y" +#line 1833 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 2); } -#line 7688 "MachineIndependent/glslang_tab.cpp" +#line 7687 "MachineIndependent/glslang_tab.cpp" break; case 239: /* type_specifier_nonarray: MAT3 */ -#line 1888 "MachineIndependent/glslang.y" +#line 1838 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 3); } -#line 7698 "MachineIndependent/glslang_tab.cpp" +#line 7697 "MachineIndependent/glslang_tab.cpp" break; case 240: /* type_specifier_nonarray: MAT4 */ -#line 1893 "MachineIndependent/glslang.y" +#line 1843 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 4); } -#line 7708 "MachineIndependent/glslang_tab.cpp" +#line 7707 "MachineIndependent/glslang_tab.cpp" break; case 241: /* type_specifier_nonarray: MAT2X2 */ -#line 1898 "MachineIndependent/glslang.y" +#line 1848 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 2); } -#line 7718 "MachineIndependent/glslang_tab.cpp" +#line 7717 "MachineIndependent/glslang_tab.cpp" break; case 242: /* type_specifier_nonarray: MAT2X3 */ -#line 1903 "MachineIndependent/glslang.y" +#line 1853 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 3); } -#line 7728 "MachineIndependent/glslang_tab.cpp" +#line 7727 "MachineIndependent/glslang_tab.cpp" break; case 243: /* type_specifier_nonarray: MAT2X4 */ -#line 1908 "MachineIndependent/glslang.y" +#line 1858 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 4); } -#line 7738 "MachineIndependent/glslang_tab.cpp" +#line 7737 "MachineIndependent/glslang_tab.cpp" break; case 244: /* type_specifier_nonarray: MAT3X2 */ -#line 1913 "MachineIndependent/glslang.y" +#line 1863 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 2); } -#line 7748 "MachineIndependent/glslang_tab.cpp" +#line 7747 "MachineIndependent/glslang_tab.cpp" break; case 245: /* type_specifier_nonarray: MAT3X3 */ -#line 1918 "MachineIndependent/glslang.y" +#line 1868 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 3); } -#line 7758 "MachineIndependent/glslang_tab.cpp" +#line 7757 "MachineIndependent/glslang_tab.cpp" break; case 246: /* type_specifier_nonarray: MAT3X4 */ -#line 1923 "MachineIndependent/glslang.y" +#line 1873 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 4); } -#line 7768 "MachineIndependent/glslang_tab.cpp" +#line 7767 "MachineIndependent/glslang_tab.cpp" break; case 247: /* type_specifier_nonarray: MAT4X2 */ -#line 1928 "MachineIndependent/glslang.y" +#line 1878 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 2); } -#line 7778 "MachineIndependent/glslang_tab.cpp" +#line 7777 "MachineIndependent/glslang_tab.cpp" break; case 248: /* type_specifier_nonarray: MAT4X3 */ -#line 1933 "MachineIndependent/glslang.y" +#line 1883 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 3); } -#line 7788 "MachineIndependent/glslang_tab.cpp" +#line 7787 "MachineIndependent/glslang_tab.cpp" break; case 249: /* type_specifier_nonarray: MAT4X4 */ -#line 1938 "MachineIndependent/glslang.y" +#line 1888 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 4); } -#line 7798 "MachineIndependent/glslang_tab.cpp" +#line 7797 "MachineIndependent/glslang_tab.cpp" break; case 250: /* type_specifier_nonarray: DOUBLE */ -#line 1944 "MachineIndependent/glslang.y" +#line 1893 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -7806,121 +7805,121 @@ yyreduce: (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; } -#line 7810 "MachineIndependent/glslang_tab.cpp" +#line 7809 "MachineIndependent/glslang_tab.cpp" break; case 251: /* type_specifier_nonarray: FLOAT16_T */ -#line 1951 "MachineIndependent/glslang.y" +#line 1900 "MachineIndependent/glslang.y" { parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "float16_t", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; } -#line 7820 "MachineIndependent/glslang_tab.cpp" +#line 7819 "MachineIndependent/glslang_tab.cpp" break; case 252: /* type_specifier_nonarray: FLOAT32_T */ -#line 1956 "MachineIndependent/glslang.y" +#line 1905 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; } -#line 7830 "MachineIndependent/glslang_tab.cpp" +#line 7829 "MachineIndependent/glslang_tab.cpp" break; case 253: /* type_specifier_nonarray: FLOAT64_T */ -#line 1961 "MachineIndependent/glslang.y" +#line 1910 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; } -#line 7840 "MachineIndependent/glslang_tab.cpp" +#line 7839 "MachineIndependent/glslang_tab.cpp" break; case 254: /* type_specifier_nonarray: INT8_T */ -#line 1966 "MachineIndependent/glslang.y" +#line 1915 "MachineIndependent/glslang.y" { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt8; } -#line 7850 "MachineIndependent/glslang_tab.cpp" +#line 7849 "MachineIndependent/glslang_tab.cpp" break; case 255: /* type_specifier_nonarray: UINT8_T */ -#line 1971 "MachineIndependent/glslang.y" +#line 1920 "MachineIndependent/glslang.y" { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint8; } -#line 7860 "MachineIndependent/glslang_tab.cpp" +#line 7859 "MachineIndependent/glslang_tab.cpp" break; case 256: /* type_specifier_nonarray: INT16_T */ -#line 1976 "MachineIndependent/glslang.y" +#line 1925 "MachineIndependent/glslang.y" { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt16; } -#line 7870 "MachineIndependent/glslang_tab.cpp" +#line 7869 "MachineIndependent/glslang_tab.cpp" break; case 257: /* type_specifier_nonarray: UINT16_T */ -#line 1981 "MachineIndependent/glslang.y" +#line 1930 "MachineIndependent/glslang.y" { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint16; } -#line 7880 "MachineIndependent/glslang_tab.cpp" +#line 7879 "MachineIndependent/glslang_tab.cpp" break; case 258: /* type_specifier_nonarray: INT32_T */ -#line 1986 "MachineIndependent/glslang.y" +#line 1935 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; } -#line 7890 "MachineIndependent/glslang_tab.cpp" +#line 7889 "MachineIndependent/glslang_tab.cpp" break; case 259: /* type_specifier_nonarray: UINT32_T */ -#line 1991 "MachineIndependent/glslang.y" +#line 1940 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; } -#line 7900 "MachineIndependent/glslang_tab.cpp" +#line 7899 "MachineIndependent/glslang_tab.cpp" break; case 260: /* type_specifier_nonarray: INT64_T */ -#line 1996 "MachineIndependent/glslang.y" +#line 1945 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt64; } -#line 7910 "MachineIndependent/glslang_tab.cpp" +#line 7909 "MachineIndependent/glslang_tab.cpp" break; case 261: /* type_specifier_nonarray: UINT64_T */ -#line 2001 "MachineIndependent/glslang.y" +#line 1950 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint64; } -#line 7920 "MachineIndependent/glslang_tab.cpp" +#line 7919 "MachineIndependent/glslang_tab.cpp" break; case 262: /* type_specifier_nonarray: DVEC2 */ -#line 2006 "MachineIndependent/glslang.y" +#line 1955 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -7929,11 +7928,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(2); } -#line 7933 "MachineIndependent/glslang_tab.cpp" +#line 7932 "MachineIndependent/glslang_tab.cpp" break; case 263: /* type_specifier_nonarray: DVEC3 */ -#line 2014 "MachineIndependent/glslang.y" +#line 1963 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -7942,11 +7941,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(3); } -#line 7946 "MachineIndependent/glslang_tab.cpp" +#line 7945 "MachineIndependent/glslang_tab.cpp" break; case 264: /* type_specifier_nonarray: DVEC4 */ -#line 2022 "MachineIndependent/glslang.y" +#line 1971 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -7955,374 +7954,374 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(4); } -#line 7959 "MachineIndependent/glslang_tab.cpp" +#line 7958 "MachineIndependent/glslang_tab.cpp" break; case 265: /* type_specifier_nonarray: F16VEC2 */ -#line 2030 "MachineIndependent/glslang.y" +#line 1979 "MachineIndependent/glslang.y" { parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setVector(2); } -#line 7970 "MachineIndependent/glslang_tab.cpp" +#line 7969 "MachineIndependent/glslang_tab.cpp" break; case 266: /* type_specifier_nonarray: F16VEC3 */ -#line 2036 "MachineIndependent/glslang.y" +#line 1985 "MachineIndependent/glslang.y" { parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setVector(3); } -#line 7981 "MachineIndependent/glslang_tab.cpp" +#line 7980 "MachineIndependent/glslang_tab.cpp" break; case 267: /* type_specifier_nonarray: F16VEC4 */ -#line 2042 "MachineIndependent/glslang.y" +#line 1991 "MachineIndependent/glslang.y" { parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setVector(4); } -#line 7992 "MachineIndependent/glslang_tab.cpp" +#line 7991 "MachineIndependent/glslang_tab.cpp" break; case 268: /* type_specifier_nonarray: F32VEC2 */ -#line 2048 "MachineIndependent/glslang.y" +#line 1997 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(2); } -#line 8003 "MachineIndependent/glslang_tab.cpp" +#line 8002 "MachineIndependent/glslang_tab.cpp" break; case 269: /* type_specifier_nonarray: F32VEC3 */ -#line 2054 "MachineIndependent/glslang.y" +#line 2003 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(3); } -#line 8014 "MachineIndependent/glslang_tab.cpp" +#line 8013 "MachineIndependent/glslang_tab.cpp" break; case 270: /* type_specifier_nonarray: F32VEC4 */ -#line 2060 "MachineIndependent/glslang.y" +#line 2009 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(4); } -#line 8025 "MachineIndependent/glslang_tab.cpp" +#line 8024 "MachineIndependent/glslang_tab.cpp" break; case 271: /* type_specifier_nonarray: F64VEC2 */ -#line 2066 "MachineIndependent/glslang.y" +#line 2015 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(2); } -#line 8036 "MachineIndependent/glslang_tab.cpp" +#line 8035 "MachineIndependent/glslang_tab.cpp" break; case 272: /* type_specifier_nonarray: F64VEC3 */ -#line 2072 "MachineIndependent/glslang.y" +#line 2021 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(3); } -#line 8047 "MachineIndependent/glslang_tab.cpp" +#line 8046 "MachineIndependent/glslang_tab.cpp" break; case 273: /* type_specifier_nonarray: F64VEC4 */ -#line 2078 "MachineIndependent/glslang.y" +#line 2027 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(4); } -#line 8058 "MachineIndependent/glslang_tab.cpp" +#line 8057 "MachineIndependent/glslang_tab.cpp" break; case 274: /* type_specifier_nonarray: I8VEC2 */ -#line 2084 "MachineIndependent/glslang.y" +#line 2033 "MachineIndependent/glslang.y" { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt8; (yyval.interm.type).setVector(2); } -#line 8069 "MachineIndependent/glslang_tab.cpp" +#line 8068 "MachineIndependent/glslang_tab.cpp" break; case 275: /* type_specifier_nonarray: I8VEC3 */ -#line 2090 "MachineIndependent/glslang.y" +#line 2039 "MachineIndependent/glslang.y" { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt8; (yyval.interm.type).setVector(3); } -#line 8080 "MachineIndependent/glslang_tab.cpp" +#line 8079 "MachineIndependent/glslang_tab.cpp" break; case 276: /* type_specifier_nonarray: I8VEC4 */ -#line 2096 "MachineIndependent/glslang.y" +#line 2045 "MachineIndependent/glslang.y" { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt8; (yyval.interm.type).setVector(4); } -#line 8091 "MachineIndependent/glslang_tab.cpp" +#line 8090 "MachineIndependent/glslang_tab.cpp" break; case 277: /* type_specifier_nonarray: I16VEC2 */ -#line 2102 "MachineIndependent/glslang.y" +#line 2051 "MachineIndependent/glslang.y" { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt16; (yyval.interm.type).setVector(2); } -#line 8102 "MachineIndependent/glslang_tab.cpp" +#line 8101 "MachineIndependent/glslang_tab.cpp" break; case 278: /* type_specifier_nonarray: I16VEC3 */ -#line 2108 "MachineIndependent/glslang.y" +#line 2057 "MachineIndependent/glslang.y" { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt16; (yyval.interm.type).setVector(3); } -#line 8113 "MachineIndependent/glslang_tab.cpp" +#line 8112 "MachineIndependent/glslang_tab.cpp" break; case 279: /* type_specifier_nonarray: I16VEC4 */ -#line 2114 "MachineIndependent/glslang.y" +#line 2063 "MachineIndependent/glslang.y" { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt16; (yyval.interm.type).setVector(4); } -#line 8124 "MachineIndependent/glslang_tab.cpp" +#line 8123 "MachineIndependent/glslang_tab.cpp" break; case 280: /* type_specifier_nonarray: I32VEC2 */ -#line 2120 "MachineIndependent/glslang.y" +#line 2069 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(2); } -#line 8135 "MachineIndependent/glslang_tab.cpp" +#line 8134 "MachineIndependent/glslang_tab.cpp" break; case 281: /* type_specifier_nonarray: I32VEC3 */ -#line 2126 "MachineIndependent/glslang.y" +#line 2075 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(3); } -#line 8146 "MachineIndependent/glslang_tab.cpp" +#line 8145 "MachineIndependent/glslang_tab.cpp" break; case 282: /* type_specifier_nonarray: I32VEC4 */ -#line 2132 "MachineIndependent/glslang.y" +#line 2081 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(4); } -#line 8157 "MachineIndependent/glslang_tab.cpp" +#line 8156 "MachineIndependent/glslang_tab.cpp" break; case 283: /* type_specifier_nonarray: I64VEC2 */ -#line 2138 "MachineIndependent/glslang.y" +#line 2087 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt64; (yyval.interm.type).setVector(2); } -#line 8168 "MachineIndependent/glslang_tab.cpp" +#line 8167 "MachineIndependent/glslang_tab.cpp" break; case 284: /* type_specifier_nonarray: I64VEC3 */ -#line 2144 "MachineIndependent/glslang.y" +#line 2093 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt64; (yyval.interm.type).setVector(3); } -#line 8179 "MachineIndependent/glslang_tab.cpp" +#line 8178 "MachineIndependent/glslang_tab.cpp" break; case 285: /* type_specifier_nonarray: I64VEC4 */ -#line 2150 "MachineIndependent/glslang.y" +#line 2099 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt64; (yyval.interm.type).setVector(4); } -#line 8190 "MachineIndependent/glslang_tab.cpp" +#line 8189 "MachineIndependent/glslang_tab.cpp" break; case 286: /* type_specifier_nonarray: U8VEC2 */ -#line 2156 "MachineIndependent/glslang.y" +#line 2105 "MachineIndependent/glslang.y" { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint8; (yyval.interm.type).setVector(2); } -#line 8201 "MachineIndependent/glslang_tab.cpp" +#line 8200 "MachineIndependent/glslang_tab.cpp" break; case 287: /* type_specifier_nonarray: U8VEC3 */ -#line 2162 "MachineIndependent/glslang.y" +#line 2111 "MachineIndependent/glslang.y" { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint8; (yyval.interm.type).setVector(3); } -#line 8212 "MachineIndependent/glslang_tab.cpp" +#line 8211 "MachineIndependent/glslang_tab.cpp" break; case 288: /* type_specifier_nonarray: U8VEC4 */ -#line 2168 "MachineIndependent/glslang.y" +#line 2117 "MachineIndependent/glslang.y" { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint8; (yyval.interm.type).setVector(4); } -#line 8223 "MachineIndependent/glslang_tab.cpp" +#line 8222 "MachineIndependent/glslang_tab.cpp" break; case 289: /* type_specifier_nonarray: U16VEC2 */ -#line 2174 "MachineIndependent/glslang.y" +#line 2123 "MachineIndependent/glslang.y" { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint16; (yyval.interm.type).setVector(2); } -#line 8234 "MachineIndependent/glslang_tab.cpp" +#line 8233 "MachineIndependent/glslang_tab.cpp" break; case 290: /* type_specifier_nonarray: U16VEC3 */ -#line 2180 "MachineIndependent/glslang.y" +#line 2129 "MachineIndependent/glslang.y" { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint16; (yyval.interm.type).setVector(3); } -#line 8245 "MachineIndependent/glslang_tab.cpp" +#line 8244 "MachineIndependent/glslang_tab.cpp" break; case 291: /* type_specifier_nonarray: U16VEC4 */ -#line 2186 "MachineIndependent/glslang.y" +#line 2135 "MachineIndependent/glslang.y" { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint16; (yyval.interm.type).setVector(4); } -#line 8256 "MachineIndependent/glslang_tab.cpp" +#line 8255 "MachineIndependent/glslang_tab.cpp" break; case 292: /* type_specifier_nonarray: U32VEC2 */ -#line 2192 "MachineIndependent/glslang.y" +#line 2141 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(2); } -#line 8267 "MachineIndependent/glslang_tab.cpp" +#line 8266 "MachineIndependent/glslang_tab.cpp" break; case 293: /* type_specifier_nonarray: U32VEC3 */ -#line 2198 "MachineIndependent/glslang.y" +#line 2147 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(3); } -#line 8278 "MachineIndependent/glslang_tab.cpp" +#line 8277 "MachineIndependent/glslang_tab.cpp" break; case 294: /* type_specifier_nonarray: U32VEC4 */ -#line 2204 "MachineIndependent/glslang.y" +#line 2153 "MachineIndependent/glslang.y" { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(4); } -#line 8289 "MachineIndependent/glslang_tab.cpp" +#line 8288 "MachineIndependent/glslang_tab.cpp" break; case 295: /* type_specifier_nonarray: U64VEC2 */ -#line 2210 "MachineIndependent/glslang.y" +#line 2159 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint64; (yyval.interm.type).setVector(2); } -#line 8300 "MachineIndependent/glslang_tab.cpp" +#line 8299 "MachineIndependent/glslang_tab.cpp" break; case 296: /* type_specifier_nonarray: U64VEC3 */ -#line 2216 "MachineIndependent/glslang.y" +#line 2165 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint64; (yyval.interm.type).setVector(3); } -#line 8311 "MachineIndependent/glslang_tab.cpp" +#line 8310 "MachineIndependent/glslang_tab.cpp" break; case 297: /* type_specifier_nonarray: U64VEC4 */ -#line 2222 "MachineIndependent/glslang.y" +#line 2171 "MachineIndependent/glslang.y" { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint64; (yyval.interm.type).setVector(4); } -#line 8322 "MachineIndependent/glslang_tab.cpp" +#line 8321 "MachineIndependent/glslang_tab.cpp" break; case 298: /* type_specifier_nonarray: DMAT2 */ -#line 2228 "MachineIndependent/glslang.y" +#line 2177 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8331,11 +8330,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 2); } -#line 8335 "MachineIndependent/glslang_tab.cpp" +#line 8334 "MachineIndependent/glslang_tab.cpp" break; case 299: /* type_specifier_nonarray: DMAT3 */ -#line 2236 "MachineIndependent/glslang.y" +#line 2185 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8344,11 +8343,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 3); } -#line 8348 "MachineIndependent/glslang_tab.cpp" +#line 8347 "MachineIndependent/glslang_tab.cpp" break; case 300: /* type_specifier_nonarray: DMAT4 */ -#line 2244 "MachineIndependent/glslang.y" +#line 2193 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8357,11 +8356,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 4); } -#line 8361 "MachineIndependent/glslang_tab.cpp" +#line 8360 "MachineIndependent/glslang_tab.cpp" break; case 301: /* type_specifier_nonarray: DMAT2X2 */ -#line 2252 "MachineIndependent/glslang.y" +#line 2201 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8370,11 +8369,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 2); } -#line 8374 "MachineIndependent/glslang_tab.cpp" +#line 8373 "MachineIndependent/glslang_tab.cpp" break; case 302: /* type_specifier_nonarray: DMAT2X3 */ -#line 2260 "MachineIndependent/glslang.y" +#line 2209 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8383,11 +8382,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 3); } -#line 8387 "MachineIndependent/glslang_tab.cpp" +#line 8386 "MachineIndependent/glslang_tab.cpp" break; case 303: /* type_specifier_nonarray: DMAT2X4 */ -#line 2268 "MachineIndependent/glslang.y" +#line 2217 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8396,11 +8395,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 4); } -#line 8400 "MachineIndependent/glslang_tab.cpp" +#line 8399 "MachineIndependent/glslang_tab.cpp" break; case 304: /* type_specifier_nonarray: DMAT3X2 */ -#line 2276 "MachineIndependent/glslang.y" +#line 2225 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8409,11 +8408,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 2); } -#line 8413 "MachineIndependent/glslang_tab.cpp" +#line 8412 "MachineIndependent/glslang_tab.cpp" break; case 305: /* type_specifier_nonarray: DMAT3X3 */ -#line 2284 "MachineIndependent/glslang.y" +#line 2233 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8422,11 +8421,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 3); } -#line 8426 "MachineIndependent/glslang_tab.cpp" +#line 8425 "MachineIndependent/glslang_tab.cpp" break; case 306: /* type_specifier_nonarray: DMAT3X4 */ -#line 2292 "MachineIndependent/glslang.y" +#line 2241 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8435,11 +8434,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 4); } -#line 8439 "MachineIndependent/glslang_tab.cpp" +#line 8438 "MachineIndependent/glslang_tab.cpp" break; case 307: /* type_specifier_nonarray: DMAT4X2 */ -#line 2300 "MachineIndependent/glslang.y" +#line 2249 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8448,11 +8447,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 2); } -#line 8452 "MachineIndependent/glslang_tab.cpp" +#line 8451 "MachineIndependent/glslang_tab.cpp" break; case 308: /* type_specifier_nonarray: DMAT4X3 */ -#line 2308 "MachineIndependent/glslang.y" +#line 2257 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8461,11 +8460,11 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 3); } -#line 8465 "MachineIndependent/glslang_tab.cpp" +#line 8464 "MachineIndependent/glslang_tab.cpp" break; case 309: /* type_specifier_nonarray: DMAT4X4 */ -#line 2316 "MachineIndependent/glslang.y" +#line 2265 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); if (! parseContext.symbolTable.atBuiltInLevel()) @@ -8474,2261 +8473,2261 @@ yyreduce: (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 4); } -#line 8478 "MachineIndependent/glslang_tab.cpp" +#line 8477 "MachineIndependent/glslang_tab.cpp" break; case 310: /* type_specifier_nonarray: F16MAT2 */ -#line 2324 "MachineIndependent/glslang.y" +#line 2273 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(2, 2); } -#line 8489 "MachineIndependent/glslang_tab.cpp" +#line 8488 "MachineIndependent/glslang_tab.cpp" break; case 311: /* type_specifier_nonarray: F16MAT3 */ -#line 2330 "MachineIndependent/glslang.y" +#line 2279 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(3, 3); } -#line 8500 "MachineIndependent/glslang_tab.cpp" +#line 8499 "MachineIndependent/glslang_tab.cpp" break; case 312: /* type_specifier_nonarray: F16MAT4 */ -#line 2336 "MachineIndependent/glslang.y" +#line 2285 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(4, 4); } -#line 8511 "MachineIndependent/glslang_tab.cpp" +#line 8510 "MachineIndependent/glslang_tab.cpp" break; case 313: /* type_specifier_nonarray: F16MAT2X2 */ -#line 2342 "MachineIndependent/glslang.y" +#line 2291 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(2, 2); } -#line 8522 "MachineIndependent/glslang_tab.cpp" +#line 8521 "MachineIndependent/glslang_tab.cpp" break; case 314: /* type_specifier_nonarray: F16MAT2X3 */ -#line 2348 "MachineIndependent/glslang.y" +#line 2297 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(2, 3); } -#line 8533 "MachineIndependent/glslang_tab.cpp" +#line 8532 "MachineIndependent/glslang_tab.cpp" break; case 315: /* type_specifier_nonarray: F16MAT2X4 */ -#line 2354 "MachineIndependent/glslang.y" +#line 2303 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(2, 4); } -#line 8544 "MachineIndependent/glslang_tab.cpp" +#line 8543 "MachineIndependent/glslang_tab.cpp" break; case 316: /* type_specifier_nonarray: F16MAT3X2 */ -#line 2360 "MachineIndependent/glslang.y" +#line 2309 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(3, 2); } -#line 8555 "MachineIndependent/glslang_tab.cpp" +#line 8554 "MachineIndependent/glslang_tab.cpp" break; case 317: /* type_specifier_nonarray: F16MAT3X3 */ -#line 2366 "MachineIndependent/glslang.y" +#line 2315 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(3, 3); } -#line 8566 "MachineIndependent/glslang_tab.cpp" +#line 8565 "MachineIndependent/glslang_tab.cpp" break; case 318: /* type_specifier_nonarray: F16MAT3X4 */ -#line 2372 "MachineIndependent/glslang.y" +#line 2321 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(3, 4); } -#line 8577 "MachineIndependent/glslang_tab.cpp" +#line 8576 "MachineIndependent/glslang_tab.cpp" break; case 319: /* type_specifier_nonarray: F16MAT4X2 */ -#line 2378 "MachineIndependent/glslang.y" +#line 2327 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(4, 2); } -#line 8588 "MachineIndependent/glslang_tab.cpp" +#line 8587 "MachineIndependent/glslang_tab.cpp" break; case 320: /* type_specifier_nonarray: F16MAT4X3 */ -#line 2384 "MachineIndependent/glslang.y" +#line 2333 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(4, 3); } -#line 8599 "MachineIndependent/glslang_tab.cpp" +#line 8598 "MachineIndependent/glslang_tab.cpp" break; case 321: /* type_specifier_nonarray: F16MAT4X4 */ -#line 2390 "MachineIndependent/glslang.y" +#line 2339 "MachineIndependent/glslang.y" { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(4, 4); } -#line 8610 "MachineIndependent/glslang_tab.cpp" +#line 8609 "MachineIndependent/glslang_tab.cpp" break; case 322: /* type_specifier_nonarray: F32MAT2 */ -#line 2396 "MachineIndependent/glslang.y" +#line 2345 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 2); } -#line 8621 "MachineIndependent/glslang_tab.cpp" +#line 8620 "MachineIndependent/glslang_tab.cpp" break; case 323: /* type_specifier_nonarray: F32MAT3 */ -#line 2402 "MachineIndependent/glslang.y" +#line 2351 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 3); } -#line 8632 "MachineIndependent/glslang_tab.cpp" +#line 8631 "MachineIndependent/glslang_tab.cpp" break; case 324: /* type_specifier_nonarray: F32MAT4 */ -#line 2408 "MachineIndependent/glslang.y" +#line 2357 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 4); } -#line 8643 "MachineIndependent/glslang_tab.cpp" +#line 8642 "MachineIndependent/glslang_tab.cpp" break; case 325: /* type_specifier_nonarray: F32MAT2X2 */ -#line 2414 "MachineIndependent/glslang.y" +#line 2363 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 2); } -#line 8654 "MachineIndependent/glslang_tab.cpp" +#line 8653 "MachineIndependent/glslang_tab.cpp" break; case 326: /* type_specifier_nonarray: F32MAT2X3 */ -#line 2420 "MachineIndependent/glslang.y" +#line 2369 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 3); } -#line 8665 "MachineIndependent/glslang_tab.cpp" +#line 8664 "MachineIndependent/glslang_tab.cpp" break; case 327: /* type_specifier_nonarray: F32MAT2X4 */ -#line 2426 "MachineIndependent/glslang.y" +#line 2375 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 4); } -#line 8676 "MachineIndependent/glslang_tab.cpp" +#line 8675 "MachineIndependent/glslang_tab.cpp" break; case 328: /* type_specifier_nonarray: F32MAT3X2 */ -#line 2432 "MachineIndependent/glslang.y" +#line 2381 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 2); } -#line 8687 "MachineIndependent/glslang_tab.cpp" +#line 8686 "MachineIndependent/glslang_tab.cpp" break; case 329: /* type_specifier_nonarray: F32MAT3X3 */ -#line 2438 "MachineIndependent/glslang.y" +#line 2387 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 3); } -#line 8698 "MachineIndependent/glslang_tab.cpp" +#line 8697 "MachineIndependent/glslang_tab.cpp" break; case 330: /* type_specifier_nonarray: F32MAT3X4 */ -#line 2444 "MachineIndependent/glslang.y" +#line 2393 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 4); } -#line 8709 "MachineIndependent/glslang_tab.cpp" +#line 8708 "MachineIndependent/glslang_tab.cpp" break; case 331: /* type_specifier_nonarray: F32MAT4X2 */ -#line 2450 "MachineIndependent/glslang.y" +#line 2399 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 2); } -#line 8720 "MachineIndependent/glslang_tab.cpp" +#line 8719 "MachineIndependent/glslang_tab.cpp" break; case 332: /* type_specifier_nonarray: F32MAT4X3 */ -#line 2456 "MachineIndependent/glslang.y" +#line 2405 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 3); } -#line 8731 "MachineIndependent/glslang_tab.cpp" +#line 8730 "MachineIndependent/glslang_tab.cpp" break; case 333: /* type_specifier_nonarray: F32MAT4X4 */ -#line 2462 "MachineIndependent/glslang.y" +#line 2411 "MachineIndependent/glslang.y" { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 4); } -#line 8742 "MachineIndependent/glslang_tab.cpp" +#line 8741 "MachineIndependent/glslang_tab.cpp" break; case 334: /* type_specifier_nonarray: F64MAT2 */ -#line 2468 "MachineIndependent/glslang.y" +#line 2417 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 2); } -#line 8753 "MachineIndependent/glslang_tab.cpp" +#line 8752 "MachineIndependent/glslang_tab.cpp" break; case 335: /* type_specifier_nonarray: F64MAT3 */ -#line 2474 "MachineIndependent/glslang.y" +#line 2423 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 3); } -#line 8764 "MachineIndependent/glslang_tab.cpp" +#line 8763 "MachineIndependent/glslang_tab.cpp" break; case 336: /* type_specifier_nonarray: F64MAT4 */ -#line 2480 "MachineIndependent/glslang.y" +#line 2429 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 4); } -#line 8775 "MachineIndependent/glslang_tab.cpp" +#line 8774 "MachineIndependent/glslang_tab.cpp" break; case 337: /* type_specifier_nonarray: F64MAT2X2 */ -#line 2486 "MachineIndependent/glslang.y" +#line 2435 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 2); } -#line 8786 "MachineIndependent/glslang_tab.cpp" +#line 8785 "MachineIndependent/glslang_tab.cpp" break; case 338: /* type_specifier_nonarray: F64MAT2X3 */ -#line 2492 "MachineIndependent/glslang.y" +#line 2441 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 3); } -#line 8797 "MachineIndependent/glslang_tab.cpp" +#line 8796 "MachineIndependent/glslang_tab.cpp" break; case 339: /* type_specifier_nonarray: F64MAT2X4 */ -#line 2498 "MachineIndependent/glslang.y" +#line 2447 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 4); } -#line 8808 "MachineIndependent/glslang_tab.cpp" +#line 8807 "MachineIndependent/glslang_tab.cpp" break; case 340: /* type_specifier_nonarray: F64MAT3X2 */ -#line 2504 "MachineIndependent/glslang.y" +#line 2453 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 2); } -#line 8819 "MachineIndependent/glslang_tab.cpp" +#line 8818 "MachineIndependent/glslang_tab.cpp" break; case 341: /* type_specifier_nonarray: F64MAT3X3 */ -#line 2510 "MachineIndependent/glslang.y" +#line 2459 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 3); } -#line 8830 "MachineIndependent/glslang_tab.cpp" +#line 8829 "MachineIndependent/glslang_tab.cpp" break; case 342: /* type_specifier_nonarray: F64MAT3X4 */ -#line 2516 "MachineIndependent/glslang.y" +#line 2465 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 4); } -#line 8841 "MachineIndependent/glslang_tab.cpp" +#line 8840 "MachineIndependent/glslang_tab.cpp" break; case 343: /* type_specifier_nonarray: F64MAT4X2 */ -#line 2522 "MachineIndependent/glslang.y" +#line 2471 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 2); } -#line 8852 "MachineIndependent/glslang_tab.cpp" +#line 8851 "MachineIndependent/glslang_tab.cpp" break; case 344: /* type_specifier_nonarray: F64MAT4X3 */ -#line 2528 "MachineIndependent/glslang.y" +#line 2477 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 3); } -#line 8863 "MachineIndependent/glslang_tab.cpp" +#line 8862 "MachineIndependent/glslang_tab.cpp" break; case 345: /* type_specifier_nonarray: F64MAT4X4 */ -#line 2534 "MachineIndependent/glslang.y" +#line 2483 "MachineIndependent/glslang.y" { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 4); } -#line 8874 "MachineIndependent/glslang_tab.cpp" +#line 8873 "MachineIndependent/glslang_tab.cpp" break; case 346: /* type_specifier_nonarray: ACCSTRUCTNV */ -#line 2540 "MachineIndependent/glslang.y" +#line 2489 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtAccStruct; } -#line 8883 "MachineIndependent/glslang_tab.cpp" +#line 8882 "MachineIndependent/glslang_tab.cpp" break; case 347: /* type_specifier_nonarray: ACCSTRUCTEXT */ -#line 2544 "MachineIndependent/glslang.y" +#line 2493 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtAccStruct; } -#line 8892 "MachineIndependent/glslang_tab.cpp" +#line 8891 "MachineIndependent/glslang_tab.cpp" break; case 348: /* type_specifier_nonarray: RAYQUERYEXT */ -#line 2548 "MachineIndependent/glslang.y" +#line 2497 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtRayQuery; } -#line 8901 "MachineIndependent/glslang_tab.cpp" +#line 8900 "MachineIndependent/glslang_tab.cpp" break; case 349: /* type_specifier_nonarray: ATOMIC_UINT */ -#line 2552 "MachineIndependent/glslang.y" +#line 2501 "MachineIndependent/glslang.y" { parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtAtomicUint; } -#line 8911 "MachineIndependent/glslang_tab.cpp" +#line 8910 "MachineIndependent/glslang_tab.cpp" break; case 350: /* type_specifier_nonarray: SAMPLER1D */ -#line 2557 "MachineIndependent/glslang.y" +#line 2506 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd1D); } -#line 8921 "MachineIndependent/glslang_tab.cpp" +#line 8920 "MachineIndependent/glslang_tab.cpp" break; case 351: /* type_specifier_nonarray: SAMPLER2D */ -#line 2563 "MachineIndependent/glslang.y" +#line 2511 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D); } -#line 8931 "MachineIndependent/glslang_tab.cpp" +#line 8930 "MachineIndependent/glslang_tab.cpp" break; case 352: /* type_specifier_nonarray: SAMPLER3D */ -#line 2568 "MachineIndependent/glslang.y" +#line 2516 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd3D); } -#line 8941 "MachineIndependent/glslang_tab.cpp" +#line 8940 "MachineIndependent/glslang_tab.cpp" break; case 353: /* type_specifier_nonarray: SAMPLERCUBE */ -#line 2573 "MachineIndependent/glslang.y" +#line 2521 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdCube); } -#line 8951 "MachineIndependent/glslang_tab.cpp" +#line 8950 "MachineIndependent/glslang_tab.cpp" break; case 354: /* type_specifier_nonarray: SAMPLER2DSHADOW */ -#line 2578 "MachineIndependent/glslang.y" +#line 2526 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true); } -#line 8961 "MachineIndependent/glslang_tab.cpp" +#line 8960 "MachineIndependent/glslang_tab.cpp" break; case 355: /* type_specifier_nonarray: SAMPLERCUBESHADOW */ -#line 2583 "MachineIndependent/glslang.y" +#line 2531 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true); } -#line 8971 "MachineIndependent/glslang_tab.cpp" +#line 8970 "MachineIndependent/glslang_tab.cpp" break; case 356: /* type_specifier_nonarray: SAMPLER2DARRAY */ -#line 2588 "MachineIndependent/glslang.y" +#line 2536 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true); } -#line 8981 "MachineIndependent/glslang_tab.cpp" +#line 8980 "MachineIndependent/glslang_tab.cpp" break; case 357: /* type_specifier_nonarray: SAMPLER2DARRAYSHADOW */ -#line 2593 "MachineIndependent/glslang.y" +#line 2541 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true); } -#line 8991 "MachineIndependent/glslang_tab.cpp" +#line 8990 "MachineIndependent/glslang_tab.cpp" break; case 358: /* type_specifier_nonarray: SAMPLER1DSHADOW */ -#line 2599 "MachineIndependent/glslang.y" +#line 2546 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true); } -#line 9001 "MachineIndependent/glslang_tab.cpp" +#line 9000 "MachineIndependent/glslang_tab.cpp" break; case 359: /* type_specifier_nonarray: SAMPLER1DARRAY */ -#line 2604 "MachineIndependent/glslang.y" +#line 2551 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true); } -#line 9011 "MachineIndependent/glslang_tab.cpp" +#line 9010 "MachineIndependent/glslang_tab.cpp" break; case 360: /* type_specifier_nonarray: SAMPLER1DARRAYSHADOW */ -#line 2609 "MachineIndependent/glslang.y" +#line 2556 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true); } -#line 9021 "MachineIndependent/glslang_tab.cpp" +#line 9020 "MachineIndependent/glslang_tab.cpp" break; case 361: /* type_specifier_nonarray: SAMPLERCUBEARRAY */ -#line 2614 "MachineIndependent/glslang.y" +#line 2561 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true); } -#line 9031 "MachineIndependent/glslang_tab.cpp" +#line 9030 "MachineIndependent/glslang_tab.cpp" break; case 362: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOW */ -#line 2619 "MachineIndependent/glslang.y" +#line 2566 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true); } -#line 9041 "MachineIndependent/glslang_tab.cpp" +#line 9040 "MachineIndependent/glslang_tab.cpp" break; case 363: /* type_specifier_nonarray: F16SAMPLER1D */ -#line 2624 "MachineIndependent/glslang.y" +#line 2571 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd1D); } -#line 9052 "MachineIndependent/glslang_tab.cpp" +#line 9051 "MachineIndependent/glslang_tab.cpp" break; case 364: /* type_specifier_nonarray: F16SAMPLER2D */ -#line 2630 "MachineIndependent/glslang.y" +#line 2577 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D); } -#line 9063 "MachineIndependent/glslang_tab.cpp" +#line 9062 "MachineIndependent/glslang_tab.cpp" break; case 365: /* type_specifier_nonarray: F16SAMPLER3D */ -#line 2636 "MachineIndependent/glslang.y" +#line 2583 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd3D); } -#line 9074 "MachineIndependent/glslang_tab.cpp" +#line 9073 "MachineIndependent/glslang_tab.cpp" break; case 366: /* type_specifier_nonarray: F16SAMPLERCUBE */ -#line 2642 "MachineIndependent/glslang.y" +#line 2589 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdCube); } -#line 9085 "MachineIndependent/glslang_tab.cpp" +#line 9084 "MachineIndependent/glslang_tab.cpp" break; case 367: /* type_specifier_nonarray: F16SAMPLER1DSHADOW */ -#line 2648 "MachineIndependent/glslang.y" +#line 2595 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, false, true); } -#line 9096 "MachineIndependent/glslang_tab.cpp" +#line 9095 "MachineIndependent/glslang_tab.cpp" break; case 368: /* type_specifier_nonarray: F16SAMPLER2DSHADOW */ -#line 2654 "MachineIndependent/glslang.y" +#line 2601 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, true); } -#line 9107 "MachineIndependent/glslang_tab.cpp" +#line 9106 "MachineIndependent/glslang_tab.cpp" break; case 369: /* type_specifier_nonarray: F16SAMPLERCUBESHADOW */ -#line 2660 "MachineIndependent/glslang.y" +#line 2607 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, false, true); } -#line 9118 "MachineIndependent/glslang_tab.cpp" +#line 9117 "MachineIndependent/glslang_tab.cpp" break; case 370: /* type_specifier_nonarray: F16SAMPLER1DARRAY */ -#line 2666 "MachineIndependent/glslang.y" +#line 2613 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true); } -#line 9129 "MachineIndependent/glslang_tab.cpp" +#line 9128 "MachineIndependent/glslang_tab.cpp" break; case 371: /* type_specifier_nonarray: F16SAMPLER2DARRAY */ -#line 2672 "MachineIndependent/glslang.y" +#line 2619 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true); } -#line 9140 "MachineIndependent/glslang_tab.cpp" +#line 9139 "MachineIndependent/glslang_tab.cpp" break; case 372: /* type_specifier_nonarray: F16SAMPLER1DARRAYSHADOW */ -#line 2678 "MachineIndependent/glslang.y" +#line 2625 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true, true); } -#line 9151 "MachineIndependent/glslang_tab.cpp" +#line 9150 "MachineIndependent/glslang_tab.cpp" break; case 373: /* type_specifier_nonarray: F16SAMPLER2DARRAYSHADOW */ -#line 2684 "MachineIndependent/glslang.y" +#line 2631 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, true); } -#line 9162 "MachineIndependent/glslang_tab.cpp" +#line 9161 "MachineIndependent/glslang_tab.cpp" break; case 374: /* type_specifier_nonarray: F16SAMPLERCUBEARRAY */ -#line 2690 "MachineIndependent/glslang.y" +#line 2637 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true); } -#line 9173 "MachineIndependent/glslang_tab.cpp" +#line 9172 "MachineIndependent/glslang_tab.cpp" break; case 375: /* type_specifier_nonarray: F16SAMPLERCUBEARRAYSHADOW */ -#line 2696 "MachineIndependent/glslang.y" +#line 2643 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true, true); } -#line 9184 "MachineIndependent/glslang_tab.cpp" +#line 9183 "MachineIndependent/glslang_tab.cpp" break; case 376: /* type_specifier_nonarray: ISAMPLER1D */ -#line 2702 "MachineIndependent/glslang.y" +#line 2649 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd1D); } -#line 9194 "MachineIndependent/glslang_tab.cpp" +#line 9193 "MachineIndependent/glslang_tab.cpp" break; case 377: /* type_specifier_nonarray: ISAMPLER2D */ -#line 2708 "MachineIndependent/glslang.y" +#line 2654 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd2D); } -#line 9204 "MachineIndependent/glslang_tab.cpp" +#line 9203 "MachineIndependent/glslang_tab.cpp" break; case 378: /* type_specifier_nonarray: ISAMPLER3D */ -#line 2713 "MachineIndependent/glslang.y" +#line 2659 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd3D); } -#line 9214 "MachineIndependent/glslang_tab.cpp" +#line 9213 "MachineIndependent/glslang_tab.cpp" break; case 379: /* type_specifier_nonarray: ISAMPLERCUBE */ -#line 2718 "MachineIndependent/glslang.y" +#line 2664 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, EsdCube); } -#line 9224 "MachineIndependent/glslang_tab.cpp" +#line 9223 "MachineIndependent/glslang_tab.cpp" break; case 380: /* type_specifier_nonarray: ISAMPLER2DARRAY */ -#line 2723 "MachineIndependent/glslang.y" +#line 2669 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd2D, true); } -#line 9234 "MachineIndependent/glslang_tab.cpp" +#line 9233 "MachineIndependent/glslang_tab.cpp" break; case 381: /* type_specifier_nonarray: USAMPLER2D */ -#line 2728 "MachineIndependent/glslang.y" +#line 2674 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd2D); } -#line 9244 "MachineIndependent/glslang_tab.cpp" +#line 9243 "MachineIndependent/glslang_tab.cpp" break; case 382: /* type_specifier_nonarray: USAMPLER3D */ -#line 2733 "MachineIndependent/glslang.y" +#line 2679 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd3D); } -#line 9254 "MachineIndependent/glslang_tab.cpp" +#line 9253 "MachineIndependent/glslang_tab.cpp" break; case 383: /* type_specifier_nonarray: USAMPLERCUBE */ -#line 2738 "MachineIndependent/glslang.y" +#line 2684 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, EsdCube); } -#line 9264 "MachineIndependent/glslang_tab.cpp" +#line 9263 "MachineIndependent/glslang_tab.cpp" break; case 384: /* type_specifier_nonarray: ISAMPLER1DARRAY */ -#line 2744 "MachineIndependent/glslang.y" +#line 2689 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd1D, true); } -#line 9274 "MachineIndependent/glslang_tab.cpp" +#line 9273 "MachineIndependent/glslang_tab.cpp" break; case 385: /* type_specifier_nonarray: ISAMPLERCUBEARRAY */ -#line 2749 "MachineIndependent/glslang.y" +#line 2694 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, EsdCube, true); } -#line 9284 "MachineIndependent/glslang_tab.cpp" +#line 9283 "MachineIndependent/glslang_tab.cpp" break; case 386: /* type_specifier_nonarray: USAMPLER1D */ -#line 2754 "MachineIndependent/glslang.y" +#line 2699 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd1D); } -#line 9294 "MachineIndependent/glslang_tab.cpp" +#line 9293 "MachineIndependent/glslang_tab.cpp" break; case 387: /* type_specifier_nonarray: USAMPLER1DARRAY */ -#line 2759 "MachineIndependent/glslang.y" +#line 2704 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd1D, true); } -#line 9304 "MachineIndependent/glslang_tab.cpp" +#line 9303 "MachineIndependent/glslang_tab.cpp" break; case 388: /* type_specifier_nonarray: USAMPLERCUBEARRAY */ -#line 2764 "MachineIndependent/glslang.y" +#line 2709 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, EsdCube, true); } -#line 9314 "MachineIndependent/glslang_tab.cpp" +#line 9313 "MachineIndependent/glslang_tab.cpp" break; case 389: /* type_specifier_nonarray: TEXTURECUBEARRAY */ -#line 2769 "MachineIndependent/glslang.y" +#line 2714 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true); } -#line 9324 "MachineIndependent/glslang_tab.cpp" +#line 9323 "MachineIndependent/glslang_tab.cpp" break; case 390: /* type_specifier_nonarray: ITEXTURECUBEARRAY */ -#line 2774 "MachineIndependent/glslang.y" +#line 2719 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true); } -#line 9334 "MachineIndependent/glslang_tab.cpp" +#line 9333 "MachineIndependent/glslang_tab.cpp" break; case 391: /* type_specifier_nonarray: UTEXTURECUBEARRAY */ -#line 2779 "MachineIndependent/glslang.y" +#line 2724 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true); } -#line 9344 "MachineIndependent/glslang_tab.cpp" +#line 9343 "MachineIndependent/glslang_tab.cpp" break; case 392: /* type_specifier_nonarray: USAMPLER2DARRAY */ -#line 2785 "MachineIndependent/glslang.y" +#line 2729 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd2D, true); } -#line 9354 "MachineIndependent/glslang_tab.cpp" +#line 9353 "MachineIndependent/glslang_tab.cpp" break; case 393: /* type_specifier_nonarray: TEXTURE2D */ -#line 2790 "MachineIndependent/glslang.y" +#line 2734 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D); } -#line 9364 "MachineIndependent/glslang_tab.cpp" +#line 9363 "MachineIndependent/glslang_tab.cpp" break; case 394: /* type_specifier_nonarray: TEXTURE3D */ -#line 2795 "MachineIndependent/glslang.y" +#line 2739 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D); } -#line 9374 "MachineIndependent/glslang_tab.cpp" +#line 9373 "MachineIndependent/glslang_tab.cpp" break; case 395: /* type_specifier_nonarray: TEXTURE2DARRAY */ -#line 2800 "MachineIndependent/glslang.y" +#line 2744 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true); } -#line 9384 "MachineIndependent/glslang_tab.cpp" +#line 9383 "MachineIndependent/glslang_tab.cpp" break; case 396: /* type_specifier_nonarray: TEXTURECUBE */ -#line 2805 "MachineIndependent/glslang.y" +#line 2749 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube); } -#line 9394 "MachineIndependent/glslang_tab.cpp" +#line 9393 "MachineIndependent/glslang_tab.cpp" break; case 397: /* type_specifier_nonarray: ITEXTURE2D */ -#line 2810 "MachineIndependent/glslang.y" +#line 2754 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D); } -#line 9404 "MachineIndependent/glslang_tab.cpp" +#line 9403 "MachineIndependent/glslang_tab.cpp" break; case 398: /* type_specifier_nonarray: ITEXTURE3D */ -#line 2815 "MachineIndependent/glslang.y" +#line 2759 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D); } -#line 9414 "MachineIndependent/glslang_tab.cpp" +#line 9413 "MachineIndependent/glslang_tab.cpp" break; case 399: /* type_specifier_nonarray: ITEXTURECUBE */ -#line 2820 "MachineIndependent/glslang.y" +#line 2764 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube); } -#line 9424 "MachineIndependent/glslang_tab.cpp" +#line 9423 "MachineIndependent/glslang_tab.cpp" break; case 400: /* type_specifier_nonarray: ITEXTURE2DARRAY */ -#line 2825 "MachineIndependent/glslang.y" +#line 2769 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true); } -#line 9434 "MachineIndependent/glslang_tab.cpp" +#line 9433 "MachineIndependent/glslang_tab.cpp" break; case 401: /* type_specifier_nonarray: UTEXTURE2D */ -#line 2830 "MachineIndependent/glslang.y" +#line 2774 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D); } -#line 9444 "MachineIndependent/glslang_tab.cpp" +#line 9443 "MachineIndependent/glslang_tab.cpp" break; case 402: /* type_specifier_nonarray: UTEXTURE3D */ -#line 2835 "MachineIndependent/glslang.y" +#line 2779 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D); } -#line 9454 "MachineIndependent/glslang_tab.cpp" +#line 9453 "MachineIndependent/glslang_tab.cpp" break; case 403: /* type_specifier_nonarray: UTEXTURECUBE */ -#line 2840 "MachineIndependent/glslang.y" +#line 2784 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube); } -#line 9464 "MachineIndependent/glslang_tab.cpp" +#line 9463 "MachineIndependent/glslang_tab.cpp" break; case 404: /* type_specifier_nonarray: UTEXTURE2DARRAY */ -#line 2845 "MachineIndependent/glslang.y" +#line 2789 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true); } -#line 9474 "MachineIndependent/glslang_tab.cpp" +#line 9473 "MachineIndependent/glslang_tab.cpp" break; case 405: /* type_specifier_nonarray: SAMPLER */ -#line 2850 "MachineIndependent/glslang.y" +#line 2794 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setPureSampler(false); } -#line 9484 "MachineIndependent/glslang_tab.cpp" +#line 9483 "MachineIndependent/glslang_tab.cpp" break; case 406: /* type_specifier_nonarray: SAMPLERSHADOW */ -#line 2855 "MachineIndependent/glslang.y" +#line 2799 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setPureSampler(true); } -#line 9494 "MachineIndependent/glslang_tab.cpp" +#line 9493 "MachineIndependent/glslang_tab.cpp" break; case 407: /* type_specifier_nonarray: SAMPLER2DRECT */ -#line 2861 "MachineIndependent/glslang.y" +#line 2804 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdRect); } -#line 9504 "MachineIndependent/glslang_tab.cpp" +#line 9503 "MachineIndependent/glslang_tab.cpp" break; case 408: /* type_specifier_nonarray: SAMPLER2DRECTSHADOW */ -#line 2866 "MachineIndependent/glslang.y" +#line 2809 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true); } -#line 9514 "MachineIndependent/glslang_tab.cpp" +#line 9513 "MachineIndependent/glslang_tab.cpp" break; case 409: /* type_specifier_nonarray: F16SAMPLER2DRECT */ -#line 2871 "MachineIndependent/glslang.y" +#line 2814 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdRect); } -#line 9525 "MachineIndependent/glslang_tab.cpp" +#line 9524 "MachineIndependent/glslang_tab.cpp" break; case 410: /* type_specifier_nonarray: F16SAMPLER2DRECTSHADOW */ -#line 2877 "MachineIndependent/glslang.y" +#line 2820 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdRect, false, true); } -#line 9536 "MachineIndependent/glslang_tab.cpp" +#line 9535 "MachineIndependent/glslang_tab.cpp" break; case 411: /* type_specifier_nonarray: ISAMPLER2DRECT */ -#line 2883 "MachineIndependent/glslang.y" +#line 2826 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, EsdRect); } -#line 9546 "MachineIndependent/glslang_tab.cpp" +#line 9545 "MachineIndependent/glslang_tab.cpp" break; case 412: /* type_specifier_nonarray: USAMPLER2DRECT */ -#line 2888 "MachineIndependent/glslang.y" +#line 2831 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, EsdRect); } -#line 9556 "MachineIndependent/glslang_tab.cpp" +#line 9555 "MachineIndependent/glslang_tab.cpp" break; case 413: /* type_specifier_nonarray: SAMPLERBUFFER */ -#line 2893 "MachineIndependent/glslang.y" +#line 2836 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer); } -#line 9566 "MachineIndependent/glslang_tab.cpp" +#line 9565 "MachineIndependent/glslang_tab.cpp" break; case 414: /* type_specifier_nonarray: F16SAMPLERBUFFER */ -#line 2898 "MachineIndependent/glslang.y" +#line 2841 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdBuffer); } -#line 9577 "MachineIndependent/glslang_tab.cpp" +#line 9576 "MachineIndependent/glslang_tab.cpp" break; case 415: /* type_specifier_nonarray: ISAMPLERBUFFER */ -#line 2904 "MachineIndependent/glslang.y" +#line 2847 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, EsdBuffer); } -#line 9587 "MachineIndependent/glslang_tab.cpp" +#line 9586 "MachineIndependent/glslang_tab.cpp" break; case 416: /* type_specifier_nonarray: USAMPLERBUFFER */ -#line 2909 "MachineIndependent/glslang.y" +#line 2852 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, EsdBuffer); } -#line 9597 "MachineIndependent/glslang_tab.cpp" +#line 9596 "MachineIndependent/glslang_tab.cpp" break; case 417: /* type_specifier_nonarray: SAMPLER2DMS */ -#line 2914 "MachineIndependent/glslang.y" +#line 2857 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true); } -#line 9607 "MachineIndependent/glslang_tab.cpp" +#line 9606 "MachineIndependent/glslang_tab.cpp" break; case 418: /* type_specifier_nonarray: F16SAMPLER2DMS */ -#line 2919 "MachineIndependent/glslang.y" +#line 2862 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, false, true); } -#line 9618 "MachineIndependent/glslang_tab.cpp" +#line 9617 "MachineIndependent/glslang_tab.cpp" break; case 419: /* type_specifier_nonarray: ISAMPLER2DMS */ -#line 2925 "MachineIndependent/glslang.y" +#line 2868 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true); } -#line 9628 "MachineIndependent/glslang_tab.cpp" +#line 9627 "MachineIndependent/glslang_tab.cpp" break; case 420: /* type_specifier_nonarray: USAMPLER2DMS */ -#line 2930 "MachineIndependent/glslang.y" +#line 2873 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true); } -#line 9638 "MachineIndependent/glslang_tab.cpp" +#line 9637 "MachineIndependent/glslang_tab.cpp" break; case 421: /* type_specifier_nonarray: SAMPLER2DMSARRAY */ -#line 2935 "MachineIndependent/glslang.y" +#line 2878 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true); } -#line 9648 "MachineIndependent/glslang_tab.cpp" +#line 9647 "MachineIndependent/glslang_tab.cpp" break; case 422: /* type_specifier_nonarray: F16SAMPLER2DMSARRAY */ -#line 2940 "MachineIndependent/glslang.y" +#line 2883 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, false, true); } -#line 9659 "MachineIndependent/glslang_tab.cpp" +#line 9658 "MachineIndependent/glslang_tab.cpp" break; case 423: /* type_specifier_nonarray: ISAMPLER2DMSARRAY */ -#line 2946 "MachineIndependent/glslang.y" +#line 2889 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true); } -#line 9669 "MachineIndependent/glslang_tab.cpp" +#line 9668 "MachineIndependent/glslang_tab.cpp" break; case 424: /* type_specifier_nonarray: USAMPLER2DMSARRAY */ -#line 2951 "MachineIndependent/glslang.y" +#line 2894 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true); } -#line 9679 "MachineIndependent/glslang_tab.cpp" +#line 9678 "MachineIndependent/glslang_tab.cpp" break; case 425: /* type_specifier_nonarray: TEXTURE1D */ -#line 2956 "MachineIndependent/glslang.y" +#line 2899 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D); } -#line 9689 "MachineIndependent/glslang_tab.cpp" +#line 9688 "MachineIndependent/glslang_tab.cpp" break; case 426: /* type_specifier_nonarray: F16TEXTURE1D */ -#line 2961 "MachineIndependent/glslang.y" +#line 2904 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D); } -#line 9700 "MachineIndependent/glslang_tab.cpp" +#line 9699 "MachineIndependent/glslang_tab.cpp" break; case 427: /* type_specifier_nonarray: F16TEXTURE2D */ -#line 2967 "MachineIndependent/glslang.y" +#line 2910 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D); } -#line 9711 "MachineIndependent/glslang_tab.cpp" +#line 9710 "MachineIndependent/glslang_tab.cpp" break; case 428: /* type_specifier_nonarray: F16TEXTURE3D */ -#line 2973 "MachineIndependent/glslang.y" +#line 2916 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd3D); } -#line 9722 "MachineIndependent/glslang_tab.cpp" +#line 9721 "MachineIndependent/glslang_tab.cpp" break; case 429: /* type_specifier_nonarray: F16TEXTURECUBE */ -#line 2979 "MachineIndependent/glslang.y" +#line 2922 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube); } -#line 9733 "MachineIndependent/glslang_tab.cpp" +#line 9732 "MachineIndependent/glslang_tab.cpp" break; case 430: /* type_specifier_nonarray: TEXTURE1DARRAY */ -#line 2985 "MachineIndependent/glslang.y" +#line 2928 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true); } -#line 9743 "MachineIndependent/glslang_tab.cpp" +#line 9742 "MachineIndependent/glslang_tab.cpp" break; case 431: /* type_specifier_nonarray: F16TEXTURE1DARRAY */ -#line 2990 "MachineIndependent/glslang.y" +#line 2933 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D, true); } -#line 9754 "MachineIndependent/glslang_tab.cpp" +#line 9753 "MachineIndependent/glslang_tab.cpp" break; case 432: /* type_specifier_nonarray: F16TEXTURE2DARRAY */ -#line 2996 "MachineIndependent/glslang.y" +#line 2939 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true); } -#line 9765 "MachineIndependent/glslang_tab.cpp" +#line 9764 "MachineIndependent/glslang_tab.cpp" break; case 433: /* type_specifier_nonarray: F16TEXTURECUBEARRAY */ -#line 3002 "MachineIndependent/glslang.y" +#line 2945 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube, true); } -#line 9776 "MachineIndependent/glslang_tab.cpp" +#line 9775 "MachineIndependent/glslang_tab.cpp" break; case 434: /* type_specifier_nonarray: ITEXTURE1D */ -#line 3008 "MachineIndependent/glslang.y" +#line 2951 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D); } -#line 9786 "MachineIndependent/glslang_tab.cpp" +#line 9785 "MachineIndependent/glslang_tab.cpp" break; case 435: /* type_specifier_nonarray: ITEXTURE1DARRAY */ -#line 3013 "MachineIndependent/glslang.y" +#line 2956 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true); } -#line 9796 "MachineIndependent/glslang_tab.cpp" +#line 9795 "MachineIndependent/glslang_tab.cpp" break; case 436: /* type_specifier_nonarray: UTEXTURE1D */ -#line 3018 "MachineIndependent/glslang.y" +#line 2961 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D); } -#line 9806 "MachineIndependent/glslang_tab.cpp" +#line 9805 "MachineIndependent/glslang_tab.cpp" break; case 437: /* type_specifier_nonarray: UTEXTURE1DARRAY */ -#line 3023 "MachineIndependent/glslang.y" +#line 2966 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true); } -#line 9816 "MachineIndependent/glslang_tab.cpp" +#line 9815 "MachineIndependent/glslang_tab.cpp" break; case 438: /* type_specifier_nonarray: TEXTURE2DRECT */ -#line 3028 "MachineIndependent/glslang.y" +#line 2971 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect); } -#line 9826 "MachineIndependent/glslang_tab.cpp" +#line 9825 "MachineIndependent/glslang_tab.cpp" break; case 439: /* type_specifier_nonarray: F16TEXTURE2DRECT */ -#line 3033 "MachineIndependent/glslang.y" +#line 2976 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdRect); } -#line 9837 "MachineIndependent/glslang_tab.cpp" +#line 9836 "MachineIndependent/glslang_tab.cpp" break; case 440: /* type_specifier_nonarray: ITEXTURE2DRECT */ -#line 3039 "MachineIndependent/glslang.y" +#line 2982 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect); } -#line 9847 "MachineIndependent/glslang_tab.cpp" +#line 9846 "MachineIndependent/glslang_tab.cpp" break; case 441: /* type_specifier_nonarray: UTEXTURE2DRECT */ -#line 3044 "MachineIndependent/glslang.y" +#line 2987 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect); } -#line 9857 "MachineIndependent/glslang_tab.cpp" +#line 9856 "MachineIndependent/glslang_tab.cpp" break; case 442: /* type_specifier_nonarray: TEXTUREBUFFER */ -#line 3049 "MachineIndependent/glslang.y" +#line 2992 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer); } -#line 9867 "MachineIndependent/glslang_tab.cpp" +#line 9866 "MachineIndependent/glslang_tab.cpp" break; case 443: /* type_specifier_nonarray: F16TEXTUREBUFFER */ -#line 3054 "MachineIndependent/glslang.y" +#line 2997 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdBuffer); } -#line 9878 "MachineIndependent/glslang_tab.cpp" +#line 9877 "MachineIndependent/glslang_tab.cpp" break; case 444: /* type_specifier_nonarray: ITEXTUREBUFFER */ -#line 3060 "MachineIndependent/glslang.y" +#line 3003 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer); } -#line 9888 "MachineIndependent/glslang_tab.cpp" +#line 9887 "MachineIndependent/glslang_tab.cpp" break; case 445: /* type_specifier_nonarray: UTEXTUREBUFFER */ -#line 3065 "MachineIndependent/glslang.y" +#line 3008 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer); } -#line 9898 "MachineIndependent/glslang_tab.cpp" +#line 9897 "MachineIndependent/glslang_tab.cpp" break; case 446: /* type_specifier_nonarray: TEXTURE2DMS */ -#line 3070 "MachineIndependent/glslang.y" +#line 3013 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true); } -#line 9908 "MachineIndependent/glslang_tab.cpp" +#line 9907 "MachineIndependent/glslang_tab.cpp" break; case 447: /* type_specifier_nonarray: F16TEXTURE2DMS */ -#line 3075 "MachineIndependent/glslang.y" +#line 3018 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, false, false, true); } -#line 9919 "MachineIndependent/glslang_tab.cpp" +#line 9918 "MachineIndependent/glslang_tab.cpp" break; case 448: /* type_specifier_nonarray: ITEXTURE2DMS */ -#line 3081 "MachineIndependent/glslang.y" +#line 3024 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true); } -#line 9929 "MachineIndependent/glslang_tab.cpp" +#line 9928 "MachineIndependent/glslang_tab.cpp" break; case 449: /* type_specifier_nonarray: UTEXTURE2DMS */ -#line 3086 "MachineIndependent/glslang.y" +#line 3029 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true); } -#line 9939 "MachineIndependent/glslang_tab.cpp" +#line 9938 "MachineIndependent/glslang_tab.cpp" break; case 450: /* type_specifier_nonarray: TEXTURE2DMSARRAY */ -#line 3091 "MachineIndependent/glslang.y" +#line 3034 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true); } -#line 9949 "MachineIndependent/glslang_tab.cpp" +#line 9948 "MachineIndependent/glslang_tab.cpp" break; case 451: /* type_specifier_nonarray: F16TEXTURE2DMSARRAY */ -#line 3096 "MachineIndependent/glslang.y" +#line 3039 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true, false, true); } -#line 9960 "MachineIndependent/glslang_tab.cpp" +#line 9959 "MachineIndependent/glslang_tab.cpp" break; case 452: /* type_specifier_nonarray: ITEXTURE2DMSARRAY */ -#line 3102 "MachineIndependent/glslang.y" +#line 3045 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true); } -#line 9970 "MachineIndependent/glslang_tab.cpp" +#line 9969 "MachineIndependent/glslang_tab.cpp" break; case 453: /* type_specifier_nonarray: UTEXTURE2DMSARRAY */ -#line 3107 "MachineIndependent/glslang.y" +#line 3050 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true); } -#line 9980 "MachineIndependent/glslang_tab.cpp" +#line 9979 "MachineIndependent/glslang_tab.cpp" break; case 454: /* type_specifier_nonarray: IMAGE1D */ -#line 3112 "MachineIndependent/glslang.y" +#line 3055 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D); } -#line 9990 "MachineIndependent/glslang_tab.cpp" +#line 9989 "MachineIndependent/glslang_tab.cpp" break; case 455: /* type_specifier_nonarray: F16IMAGE1D */ -#line 3117 "MachineIndependent/glslang.y" +#line 3060 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D); } -#line 10001 "MachineIndependent/glslang_tab.cpp" +#line 10000 "MachineIndependent/glslang_tab.cpp" break; case 456: /* type_specifier_nonarray: IIMAGE1D */ -#line 3123 "MachineIndependent/glslang.y" +#line 3066 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd1D); } -#line 10011 "MachineIndependent/glslang_tab.cpp" +#line 10010 "MachineIndependent/glslang_tab.cpp" break; case 457: /* type_specifier_nonarray: UIMAGE1D */ -#line 3128 "MachineIndependent/glslang.y" +#line 3071 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd1D); } -#line 10021 "MachineIndependent/glslang_tab.cpp" +#line 10020 "MachineIndependent/glslang_tab.cpp" break; case 458: /* type_specifier_nonarray: IMAGE2D */ -#line 3133 "MachineIndependent/glslang.y" +#line 3076 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D); } -#line 10031 "MachineIndependent/glslang_tab.cpp" +#line 10030 "MachineIndependent/glslang_tab.cpp" break; case 459: /* type_specifier_nonarray: F16IMAGE2D */ -#line 3138 "MachineIndependent/glslang.y" +#line 3081 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D); } -#line 10042 "MachineIndependent/glslang_tab.cpp" +#line 10041 "MachineIndependent/glslang_tab.cpp" break; case 460: /* type_specifier_nonarray: IIMAGE2D */ -#line 3144 "MachineIndependent/glslang.y" +#line 3087 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd2D); } -#line 10052 "MachineIndependent/glslang_tab.cpp" +#line 10051 "MachineIndependent/glslang_tab.cpp" break; case 461: /* type_specifier_nonarray: UIMAGE2D */ -#line 3149 "MachineIndependent/glslang.y" +#line 3092 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd2D); } -#line 10062 "MachineIndependent/glslang_tab.cpp" +#line 10061 "MachineIndependent/glslang_tab.cpp" break; case 462: /* type_specifier_nonarray: IMAGE3D */ -#line 3154 "MachineIndependent/glslang.y" +#line 3097 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D); } -#line 10072 "MachineIndependent/glslang_tab.cpp" +#line 10071 "MachineIndependent/glslang_tab.cpp" break; case 463: /* type_specifier_nonarray: F16IMAGE3D */ -#line 3159 "MachineIndependent/glslang.y" +#line 3102 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd3D); } -#line 10083 "MachineIndependent/glslang_tab.cpp" +#line 10082 "MachineIndependent/glslang_tab.cpp" break; case 464: /* type_specifier_nonarray: IIMAGE3D */ -#line 3165 "MachineIndependent/glslang.y" +#line 3108 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd3D); } -#line 10093 "MachineIndependent/glslang_tab.cpp" +#line 10092 "MachineIndependent/glslang_tab.cpp" break; case 465: /* type_specifier_nonarray: UIMAGE3D */ -#line 3170 "MachineIndependent/glslang.y" +#line 3113 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd3D); } -#line 10103 "MachineIndependent/glslang_tab.cpp" +#line 10102 "MachineIndependent/glslang_tab.cpp" break; case 466: /* type_specifier_nonarray: IMAGE2DRECT */ -#line 3175 "MachineIndependent/glslang.y" +#line 3118 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect); } -#line 10113 "MachineIndependent/glslang_tab.cpp" +#line 10112 "MachineIndependent/glslang_tab.cpp" break; case 467: /* type_specifier_nonarray: F16IMAGE2DRECT */ -#line 3180 "MachineIndependent/glslang.y" +#line 3123 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, EsdRect); } -#line 10124 "MachineIndependent/glslang_tab.cpp" +#line 10123 "MachineIndependent/glslang_tab.cpp" break; case 468: /* type_specifier_nonarray: IIMAGE2DRECT */ -#line 3186 "MachineIndependent/glslang.y" +#line 3129 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, EsdRect); } -#line 10134 "MachineIndependent/glslang_tab.cpp" +#line 10133 "MachineIndependent/glslang_tab.cpp" break; case 469: /* type_specifier_nonarray: UIMAGE2DRECT */ -#line 3191 "MachineIndependent/glslang.y" +#line 3134 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, EsdRect); } -#line 10144 "MachineIndependent/glslang_tab.cpp" +#line 10143 "MachineIndependent/glslang_tab.cpp" break; case 470: /* type_specifier_nonarray: IMAGECUBE */ -#line 3196 "MachineIndependent/glslang.y" +#line 3139 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube); } -#line 10154 "MachineIndependent/glslang_tab.cpp" +#line 10153 "MachineIndependent/glslang_tab.cpp" break; case 471: /* type_specifier_nonarray: F16IMAGECUBE */ -#line 3201 "MachineIndependent/glslang.y" +#line 3144 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube); } -#line 10165 "MachineIndependent/glslang_tab.cpp" +#line 10164 "MachineIndependent/glslang_tab.cpp" break; case 472: /* type_specifier_nonarray: IIMAGECUBE */ -#line 3207 "MachineIndependent/glslang.y" +#line 3150 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, EsdCube); } -#line 10175 "MachineIndependent/glslang_tab.cpp" +#line 10174 "MachineIndependent/glslang_tab.cpp" break; case 473: /* type_specifier_nonarray: UIMAGECUBE */ -#line 3212 "MachineIndependent/glslang.y" +#line 3155 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, EsdCube); } -#line 10185 "MachineIndependent/glslang_tab.cpp" +#line 10184 "MachineIndependent/glslang_tab.cpp" break; case 474: /* type_specifier_nonarray: IMAGEBUFFER */ -#line 3217 "MachineIndependent/glslang.y" +#line 3160 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer); } -#line 10195 "MachineIndependent/glslang_tab.cpp" +#line 10194 "MachineIndependent/glslang_tab.cpp" break; case 475: /* type_specifier_nonarray: F16IMAGEBUFFER */ -#line 3222 "MachineIndependent/glslang.y" +#line 3165 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, EsdBuffer); } -#line 10206 "MachineIndependent/glslang_tab.cpp" +#line 10205 "MachineIndependent/glslang_tab.cpp" break; case 476: /* type_specifier_nonarray: IIMAGEBUFFER */ -#line 3228 "MachineIndependent/glslang.y" +#line 3171 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer); } -#line 10216 "MachineIndependent/glslang_tab.cpp" +#line 10215 "MachineIndependent/glslang_tab.cpp" break; case 477: /* type_specifier_nonarray: UIMAGEBUFFER */ -#line 3233 "MachineIndependent/glslang.y" +#line 3176 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer); } -#line 10226 "MachineIndependent/glslang_tab.cpp" +#line 10225 "MachineIndependent/glslang_tab.cpp" break; case 478: /* type_specifier_nonarray: IMAGE1DARRAY */ -#line 3238 "MachineIndependent/glslang.y" +#line 3181 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true); } -#line 10236 "MachineIndependent/glslang_tab.cpp" +#line 10235 "MachineIndependent/glslang_tab.cpp" break; case 479: /* type_specifier_nonarray: F16IMAGE1DARRAY */ -#line 3243 "MachineIndependent/glslang.y" +#line 3186 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D, true); } -#line 10247 "MachineIndependent/glslang_tab.cpp" +#line 10246 "MachineIndependent/glslang_tab.cpp" break; case 480: /* type_specifier_nonarray: IIMAGE1DARRAY */ -#line 3249 "MachineIndependent/glslang.y" +#line 3192 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true); } -#line 10257 "MachineIndependent/glslang_tab.cpp" +#line 10256 "MachineIndependent/glslang_tab.cpp" break; case 481: /* type_specifier_nonarray: UIMAGE1DARRAY */ -#line 3254 "MachineIndependent/glslang.y" +#line 3197 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true); } -#line 10267 "MachineIndependent/glslang_tab.cpp" +#line 10266 "MachineIndependent/glslang_tab.cpp" break; case 482: /* type_specifier_nonarray: IMAGE2DARRAY */ -#line 3259 "MachineIndependent/glslang.y" +#line 3202 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true); } -#line 10277 "MachineIndependent/glslang_tab.cpp" +#line 10276 "MachineIndependent/glslang_tab.cpp" break; case 483: /* type_specifier_nonarray: F16IMAGE2DARRAY */ -#line 3264 "MachineIndependent/glslang.y" +#line 3207 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true); } -#line 10288 "MachineIndependent/glslang_tab.cpp" +#line 10287 "MachineIndependent/glslang_tab.cpp" break; case 484: /* type_specifier_nonarray: IIMAGE2DARRAY */ -#line 3270 "MachineIndependent/glslang.y" +#line 3213 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true); } -#line 10298 "MachineIndependent/glslang_tab.cpp" +#line 10297 "MachineIndependent/glslang_tab.cpp" break; case 485: /* type_specifier_nonarray: UIMAGE2DARRAY */ -#line 3275 "MachineIndependent/glslang.y" +#line 3218 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true); } -#line 10308 "MachineIndependent/glslang_tab.cpp" +#line 10307 "MachineIndependent/glslang_tab.cpp" break; case 486: /* type_specifier_nonarray: IMAGECUBEARRAY */ -#line 3280 "MachineIndependent/glslang.y" +#line 3223 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true); } -#line 10318 "MachineIndependent/glslang_tab.cpp" +#line 10317 "MachineIndependent/glslang_tab.cpp" break; case 487: /* type_specifier_nonarray: F16IMAGECUBEARRAY */ -#line 3285 "MachineIndependent/glslang.y" +#line 3228 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube, true); } -#line 10329 "MachineIndependent/glslang_tab.cpp" +#line 10328 "MachineIndependent/glslang_tab.cpp" break; case 488: /* type_specifier_nonarray: IIMAGECUBEARRAY */ -#line 3291 "MachineIndependent/glslang.y" +#line 3234 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true); } -#line 10339 "MachineIndependent/glslang_tab.cpp" +#line 10338 "MachineIndependent/glslang_tab.cpp" break; case 489: /* type_specifier_nonarray: UIMAGECUBEARRAY */ -#line 3296 "MachineIndependent/glslang.y" +#line 3239 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true); } -#line 10349 "MachineIndependent/glslang_tab.cpp" +#line 10348 "MachineIndependent/glslang_tab.cpp" break; case 490: /* type_specifier_nonarray: IMAGE2DMS */ -#line 3301 "MachineIndependent/glslang.y" +#line 3244 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true); } -#line 10359 "MachineIndependent/glslang_tab.cpp" +#line 10358 "MachineIndependent/glslang_tab.cpp" break; case 491: /* type_specifier_nonarray: F16IMAGE2DMS */ -#line 3306 "MachineIndependent/glslang.y" +#line 3249 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, false, false, true); } -#line 10370 "MachineIndependent/glslang_tab.cpp" +#line 10369 "MachineIndependent/glslang_tab.cpp" break; case 492: /* type_specifier_nonarray: IIMAGE2DMS */ -#line 3312 "MachineIndependent/glslang.y" +#line 3255 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true); } -#line 10380 "MachineIndependent/glslang_tab.cpp" +#line 10379 "MachineIndependent/glslang_tab.cpp" break; case 493: /* type_specifier_nonarray: UIMAGE2DMS */ -#line 3317 "MachineIndependent/glslang.y" +#line 3260 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true); } -#line 10390 "MachineIndependent/glslang_tab.cpp" +#line 10389 "MachineIndependent/glslang_tab.cpp" break; case 494: /* type_specifier_nonarray: IMAGE2DMSARRAY */ -#line 3322 "MachineIndependent/glslang.y" +#line 3265 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true); } -#line 10400 "MachineIndependent/glslang_tab.cpp" +#line 10399 "MachineIndependent/glslang_tab.cpp" break; case 495: /* type_specifier_nonarray: F16IMAGE2DMSARRAY */ -#line 3327 "MachineIndependent/glslang.y" +#line 3270 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true, false, true); } -#line 10411 "MachineIndependent/glslang_tab.cpp" +#line 10410 "MachineIndependent/glslang_tab.cpp" break; case 496: /* type_specifier_nonarray: IIMAGE2DMSARRAY */ -#line 3333 "MachineIndependent/glslang.y" +#line 3276 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true); } -#line 10421 "MachineIndependent/glslang_tab.cpp" +#line 10420 "MachineIndependent/glslang_tab.cpp" break; case 497: /* type_specifier_nonarray: UIMAGE2DMSARRAY */ -#line 3338 "MachineIndependent/glslang.y" +#line 3281 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true); } -#line 10431 "MachineIndependent/glslang_tab.cpp" +#line 10430 "MachineIndependent/glslang_tab.cpp" break; case 498: /* type_specifier_nonarray: I64IMAGE1D */ -#line 3343 "MachineIndependent/glslang.y" +#line 3286 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, Esd1D); } -#line 10441 "MachineIndependent/glslang_tab.cpp" +#line 10440 "MachineIndependent/glslang_tab.cpp" break; case 499: /* type_specifier_nonarray: U64IMAGE1D */ -#line 3348 "MachineIndependent/glslang.y" +#line 3291 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, Esd1D); } -#line 10451 "MachineIndependent/glslang_tab.cpp" +#line 10450 "MachineIndependent/glslang_tab.cpp" break; case 500: /* type_specifier_nonarray: I64IMAGE2D */ -#line 3353 "MachineIndependent/glslang.y" +#line 3296 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D); } -#line 10461 "MachineIndependent/glslang_tab.cpp" +#line 10460 "MachineIndependent/glslang_tab.cpp" break; case 501: /* type_specifier_nonarray: U64IMAGE2D */ -#line 3358 "MachineIndependent/glslang.y" +#line 3301 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D); } -#line 10471 "MachineIndependent/glslang_tab.cpp" +#line 10470 "MachineIndependent/glslang_tab.cpp" break; case 502: /* type_specifier_nonarray: I64IMAGE3D */ -#line 3363 "MachineIndependent/glslang.y" +#line 3306 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, Esd3D); } -#line 10481 "MachineIndependent/glslang_tab.cpp" +#line 10480 "MachineIndependent/glslang_tab.cpp" break; case 503: /* type_specifier_nonarray: U64IMAGE3D */ -#line 3368 "MachineIndependent/glslang.y" +#line 3311 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, Esd3D); } -#line 10491 "MachineIndependent/glslang_tab.cpp" +#line 10490 "MachineIndependent/glslang_tab.cpp" break; case 504: /* type_specifier_nonarray: I64IMAGE2DRECT */ -#line 3373 "MachineIndependent/glslang.y" +#line 3316 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, EsdRect); } -#line 10501 "MachineIndependent/glslang_tab.cpp" +#line 10500 "MachineIndependent/glslang_tab.cpp" break; case 505: /* type_specifier_nonarray: U64IMAGE2DRECT */ -#line 3378 "MachineIndependent/glslang.y" +#line 3321 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, EsdRect); } -#line 10511 "MachineIndependent/glslang_tab.cpp" +#line 10510 "MachineIndependent/glslang_tab.cpp" break; case 506: /* type_specifier_nonarray: I64IMAGECUBE */ -#line 3383 "MachineIndependent/glslang.y" +#line 3326 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, EsdCube); } -#line 10521 "MachineIndependent/glslang_tab.cpp" +#line 10520 "MachineIndependent/glslang_tab.cpp" break; case 507: /* type_specifier_nonarray: U64IMAGECUBE */ -#line 3388 "MachineIndependent/glslang.y" +#line 3331 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, EsdCube); } -#line 10531 "MachineIndependent/glslang_tab.cpp" +#line 10530 "MachineIndependent/glslang_tab.cpp" break; case 508: /* type_specifier_nonarray: I64IMAGEBUFFER */ -#line 3393 "MachineIndependent/glslang.y" +#line 3336 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, EsdBuffer); } -#line 10541 "MachineIndependent/glslang_tab.cpp" +#line 10540 "MachineIndependent/glslang_tab.cpp" break; case 509: /* type_specifier_nonarray: U64IMAGEBUFFER */ -#line 3398 "MachineIndependent/glslang.y" +#line 3341 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, EsdBuffer); } -#line 10551 "MachineIndependent/glslang_tab.cpp" +#line 10550 "MachineIndependent/glslang_tab.cpp" break; case 510: /* type_specifier_nonarray: I64IMAGE1DARRAY */ -#line 3403 "MachineIndependent/glslang.y" +#line 3346 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, Esd1D, true); } -#line 10561 "MachineIndependent/glslang_tab.cpp" +#line 10560 "MachineIndependent/glslang_tab.cpp" break; case 511: /* type_specifier_nonarray: U64IMAGE1DARRAY */ -#line 3408 "MachineIndependent/glslang.y" +#line 3351 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, Esd1D, true); } -#line 10571 "MachineIndependent/glslang_tab.cpp" +#line 10570 "MachineIndependent/glslang_tab.cpp" break; case 512: /* type_specifier_nonarray: I64IMAGE2DARRAY */ -#line 3413 "MachineIndependent/glslang.y" +#line 3356 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, true); } -#line 10581 "MachineIndependent/glslang_tab.cpp" +#line 10580 "MachineIndependent/glslang_tab.cpp" break; case 513: /* type_specifier_nonarray: U64IMAGE2DARRAY */ -#line 3418 "MachineIndependent/glslang.y" +#line 3361 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, true); } -#line 10591 "MachineIndependent/glslang_tab.cpp" +#line 10590 "MachineIndependent/glslang_tab.cpp" break; case 514: /* type_specifier_nonarray: I64IMAGECUBEARRAY */ -#line 3423 "MachineIndependent/glslang.y" +#line 3366 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, EsdCube, true); } -#line 10601 "MachineIndependent/glslang_tab.cpp" +#line 10600 "MachineIndependent/glslang_tab.cpp" break; case 515: /* type_specifier_nonarray: U64IMAGECUBEARRAY */ -#line 3428 "MachineIndependent/glslang.y" +#line 3371 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, EsdCube, true); } -#line 10611 "MachineIndependent/glslang_tab.cpp" +#line 10610 "MachineIndependent/glslang_tab.cpp" break; case 516: /* type_specifier_nonarray: I64IMAGE2DMS */ -#line 3433 "MachineIndependent/glslang.y" +#line 3376 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, false, false, true); } -#line 10621 "MachineIndependent/glslang_tab.cpp" +#line 10620 "MachineIndependent/glslang_tab.cpp" break; case 517: /* type_specifier_nonarray: U64IMAGE2DMS */ -#line 3438 "MachineIndependent/glslang.y" +#line 3381 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, false, false, true); } -#line 10631 "MachineIndependent/glslang_tab.cpp" +#line 10630 "MachineIndependent/glslang_tab.cpp" break; case 518: /* type_specifier_nonarray: I64IMAGE2DMSARRAY */ -#line 3443 "MachineIndependent/glslang.y" +#line 3386 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, true, false, true); } -#line 10641 "MachineIndependent/glslang_tab.cpp" +#line 10640 "MachineIndependent/glslang_tab.cpp" break; case 519: /* type_specifier_nonarray: U64IMAGE2DMSARRAY */ -#line 3448 "MachineIndependent/glslang.y" +#line 3391 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, true, false, true); } -#line 10651 "MachineIndependent/glslang_tab.cpp" +#line 10650 "MachineIndependent/glslang_tab.cpp" break; case 520: /* type_specifier_nonarray: SAMPLEREXTERNALOES */ -#line 3453 "MachineIndependent/glslang.y" +#line 3396 "MachineIndependent/glslang.y" { // GL_OES_EGL_image_external (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D); (yyval.interm.type).sampler.external = true; } -#line 10662 "MachineIndependent/glslang_tab.cpp" +#line 10661 "MachineIndependent/glslang_tab.cpp" break; case 521: /* type_specifier_nonarray: SAMPLEREXTERNAL2DY2YEXT */ -#line 3459 "MachineIndependent/glslang.y" +#line 3402 "MachineIndependent/glslang.y" { // GL_EXT_YUV_target (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D); (yyval.interm.type).sampler.yuv = true; } -#line 10673 "MachineIndependent/glslang_tab.cpp" +#line 10672 "MachineIndependent/glslang_tab.cpp" break; case 522: /* type_specifier_nonarray: ATTACHMENTEXT */ -#line 3465 "MachineIndependent/glslang.y" +#line 3408 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "attachmentEXT input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setAttachmentEXT(EbtFloat); } -#line 10684 "MachineIndependent/glslang_tab.cpp" +#line 10683 "MachineIndependent/glslang_tab.cpp" break; case 523: /* type_specifier_nonarray: IATTACHMENTEXT */ -#line 3471 "MachineIndependent/glslang.y" +#line 3414 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "attachmentEXT input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setAttachmentEXT(EbtInt); } -#line 10695 "MachineIndependent/glslang_tab.cpp" +#line 10694 "MachineIndependent/glslang_tab.cpp" break; case 524: /* type_specifier_nonarray: UATTACHMENTEXT */ -#line 3477 "MachineIndependent/glslang.y" +#line 3420 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "attachmentEXT input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setAttachmentEXT(EbtUint); } -#line 10706 "MachineIndependent/glslang_tab.cpp" +#line 10705 "MachineIndependent/glslang_tab.cpp" break; case 525: /* type_specifier_nonarray: SUBPASSINPUT */ -#line 3483 "MachineIndependent/glslang.y" +#line 3426 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtFloat); } -#line 10717 "MachineIndependent/glslang_tab.cpp" +#line 10716 "MachineIndependent/glslang_tab.cpp" break; case 526: /* type_specifier_nonarray: SUBPASSINPUTMS */ -#line 3489 "MachineIndependent/glslang.y" +#line 3432 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtFloat, true); } -#line 10728 "MachineIndependent/glslang_tab.cpp" +#line 10727 "MachineIndependent/glslang_tab.cpp" break; case 527: /* type_specifier_nonarray: F16SUBPASSINPUT */ -#line 3495 "MachineIndependent/glslang.y" +#line 3438 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); @@ -10736,11 +10735,11 @@ yyreduce: (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtFloat16); } -#line 10740 "MachineIndependent/glslang_tab.cpp" +#line 10739 "MachineIndependent/glslang_tab.cpp" break; case 528: /* type_specifier_nonarray: F16SUBPASSINPUTMS */ -#line 3502 "MachineIndependent/glslang.y" +#line 3445 "MachineIndependent/glslang.y" { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); @@ -10748,55 +10747,55 @@ yyreduce: (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtFloat16, true); } -#line 10752 "MachineIndependent/glslang_tab.cpp" +#line 10751 "MachineIndependent/glslang_tab.cpp" break; case 529: /* type_specifier_nonarray: ISUBPASSINPUT */ -#line 3509 "MachineIndependent/glslang.y" +#line 3452 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtInt); } -#line 10763 "MachineIndependent/glslang_tab.cpp" +#line 10762 "MachineIndependent/glslang_tab.cpp" break; case 530: /* type_specifier_nonarray: ISUBPASSINPUTMS */ -#line 3515 "MachineIndependent/glslang.y" +#line 3458 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtInt, true); } -#line 10774 "MachineIndependent/glslang_tab.cpp" +#line 10773 "MachineIndependent/glslang_tab.cpp" break; case 531: /* type_specifier_nonarray: USUBPASSINPUT */ -#line 3521 "MachineIndependent/glslang.y" +#line 3464 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtUint); } -#line 10785 "MachineIndependent/glslang_tab.cpp" +#line 10784 "MachineIndependent/glslang_tab.cpp" break; case 532: /* type_specifier_nonarray: USUBPASSINPUTMS */ -#line 3527 "MachineIndependent/glslang.y" +#line 3470 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtUint, true); } -#line 10796 "MachineIndependent/glslang_tab.cpp" +#line 10795 "MachineIndependent/glslang_tab.cpp" break; case 533: /* type_specifier_nonarray: FCOOPMATNV */ -#line 3533 "MachineIndependent/glslang.y" +#line 3476 "MachineIndependent/glslang.y" { parseContext.fcoopmatCheckNV((yyvsp[0].lex).loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); @@ -10804,11 +10803,11 @@ yyreduce: (yyval.interm.type).coopmatNV = true; (yyval.interm.type).coopmatKHR = false; } -#line 10808 "MachineIndependent/glslang_tab.cpp" +#line 10807 "MachineIndependent/glslang_tab.cpp" break; case 534: /* type_specifier_nonarray: ICOOPMATNV */ -#line 3540 "MachineIndependent/glslang.y" +#line 3483 "MachineIndependent/glslang.y" { parseContext.intcoopmatCheckNV((yyvsp[0].lex).loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); @@ -10816,11 +10815,11 @@ yyreduce: (yyval.interm.type).coopmatNV = true; (yyval.interm.type).coopmatKHR = false; } -#line 10820 "MachineIndependent/glslang_tab.cpp" +#line 10819 "MachineIndependent/glslang_tab.cpp" break; case 535: /* type_specifier_nonarray: UCOOPMATNV */ -#line 3547 "MachineIndependent/glslang.y" +#line 3490 "MachineIndependent/glslang.y" { parseContext.intcoopmatCheckNV((yyvsp[0].lex).loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); @@ -10828,11 +10827,11 @@ yyreduce: (yyval.interm.type).coopmatNV = true; (yyval.interm.type).coopmatKHR = false; } -#line 10832 "MachineIndependent/glslang_tab.cpp" +#line 10831 "MachineIndependent/glslang_tab.cpp" break; case 536: /* type_specifier_nonarray: COOPMAT */ -#line 3554 "MachineIndependent/glslang.y" +#line 3497 "MachineIndependent/glslang.y" { parseContext.coopmatCheck((yyvsp[0].lex).loc, "coopmat", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); @@ -10840,39 +10839,39 @@ yyreduce: (yyval.interm.type).coopmatNV = false; (yyval.interm.type).coopmatKHR = true; } -#line 10844 "MachineIndependent/glslang_tab.cpp" +#line 10843 "MachineIndependent/glslang_tab.cpp" break; case 537: /* type_specifier_nonarray: spirv_type_specifier */ -#line 3561 "MachineIndependent/glslang.y" +#line 3504 "MachineIndependent/glslang.y" { parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier"); (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 10853 "MachineIndependent/glslang_tab.cpp" +#line 10852 "MachineIndependent/glslang_tab.cpp" break; case 538: /* type_specifier_nonarray: HITOBJECTNV */ -#line 3565 "MachineIndependent/glslang.y" +#line 3508 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtHitObjectNV; } -#line 10862 "MachineIndependent/glslang_tab.cpp" +#line 10861 "MachineIndependent/glslang_tab.cpp" break; case 539: /* type_specifier_nonarray: struct_specifier */ -#line 3570 "MachineIndependent/glslang.y" +#line 3512 "MachineIndependent/glslang.y" { (yyval.interm.type) = (yyvsp[0].interm.type); (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type)); } -#line 10872 "MachineIndependent/glslang_tab.cpp" +#line 10871 "MachineIndependent/glslang_tab.cpp" break; case 540: /* type_specifier_nonarray: TYPE_NAME */ -#line 3575 "MachineIndependent/glslang.y" +#line 3517 "MachineIndependent/glslang.y" { // // This is for user defined type names. The lexical phase looked up the @@ -10886,47 +10885,47 @@ yyreduce: } else parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), ""); } -#line 10890 "MachineIndependent/glslang_tab.cpp" +#line 10889 "MachineIndependent/glslang_tab.cpp" break; case 541: /* precision_qualifier: HIGH_PRECISION */ -#line 3591 "MachineIndependent/glslang.y" +#line 3533 "MachineIndependent/glslang.y" { parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqHigh); } -#line 10900 "MachineIndependent/glslang_tab.cpp" +#line 10899 "MachineIndependent/glslang_tab.cpp" break; case 542: /* precision_qualifier: MEDIUM_PRECISION */ -#line 3596 "MachineIndependent/glslang.y" +#line 3538 "MachineIndependent/glslang.y" { parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqMedium); } -#line 10910 "MachineIndependent/glslang_tab.cpp" +#line 10909 "MachineIndependent/glslang_tab.cpp" break; case 543: /* precision_qualifier: LOW_PRECISION */ -#line 3601 "MachineIndependent/glslang.y" +#line 3543 "MachineIndependent/glslang.y" { parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqLow); } -#line 10920 "MachineIndependent/glslang_tab.cpp" +#line 10919 "MachineIndependent/glslang_tab.cpp" break; case 544: /* $@3: %empty */ -#line 3609 "MachineIndependent/glslang.y" +#line 3551 "MachineIndependent/glslang.y" { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); } -#line 10926 "MachineIndependent/glslang_tab.cpp" +#line 10925 "MachineIndependent/glslang_tab.cpp" break; case 545: /* struct_specifier: STRUCT IDENTIFIER LEFT_BRACE $@3 struct_declaration_list RIGHT_BRACE */ -#line 3609 "MachineIndependent/glslang.y" +#line 3551 "MachineIndependent/glslang.y" { TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string); parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure); @@ -10938,17 +10937,17 @@ yyreduce: (yyval.interm.type).userDef = structure; --parseContext.structNestingLevel; } -#line 10942 "MachineIndependent/glslang_tab.cpp" +#line 10941 "MachineIndependent/glslang_tab.cpp" break; case 546: /* $@4: %empty */ -#line 3620 "MachineIndependent/glslang.y" +#line 3562 "MachineIndependent/glslang.y" { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); } -#line 10948 "MachineIndependent/glslang_tab.cpp" +#line 10947 "MachineIndependent/glslang_tab.cpp" break; case 547: /* struct_specifier: STRUCT LEFT_BRACE $@4 struct_declaration_list RIGHT_BRACE */ -#line 3620 "MachineIndependent/glslang.y" +#line 3562 "MachineIndependent/glslang.y" { TType* structure = new TType((yyvsp[-1].interm.typeList), TString("")); (yyval.interm.type).init((yyvsp[-4].lex).loc); @@ -10956,19 +10955,19 @@ yyreduce: (yyval.interm.type).userDef = structure; --parseContext.structNestingLevel; } -#line 10960 "MachineIndependent/glslang_tab.cpp" +#line 10959 "MachineIndependent/glslang_tab.cpp" break; case 548: /* struct_declaration_list: struct_declaration */ -#line 3630 "MachineIndependent/glslang.y" +#line 3572 "MachineIndependent/glslang.y" { (yyval.interm.typeList) = (yyvsp[0].interm.typeList); } -#line 10968 "MachineIndependent/glslang_tab.cpp" +#line 10967 "MachineIndependent/glslang_tab.cpp" break; case 549: /* struct_declaration_list: struct_declaration_list struct_declaration */ -#line 3633 "MachineIndependent/glslang.y" +#line 3575 "MachineIndependent/glslang.y" { (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) { @@ -10979,11 +10978,11 @@ yyreduce: (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]); } } -#line 10983 "MachineIndependent/glslang_tab.cpp" +#line 10982 "MachineIndependent/glslang_tab.cpp" break; case 550: /* struct_declaration: type_specifier struct_declarator_list SEMICOLON */ -#line 3646 "MachineIndependent/glslang.y" +#line 3588 "MachineIndependent/glslang.y" { if ((yyvsp[-2].interm.type).arraySizes) { parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); @@ -11006,11 +11005,11 @@ yyreduce: (*(yyval.interm.typeList))[i].type->shallowCopy(type); } } -#line 11010 "MachineIndependent/glslang_tab.cpp" +#line 11009 "MachineIndependent/glslang_tab.cpp" break; case 551: /* struct_declaration: type_qualifier type_specifier struct_declarator_list SEMICOLON */ -#line 3668 "MachineIndependent/glslang.y" +#line 3610 "MachineIndependent/glslang.y" { if ((yyvsp[-2].interm.type).arraySizes) { parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); @@ -11035,38 +11034,38 @@ yyreduce: (*(yyval.interm.typeList))[i].type->shallowCopy(type); } } -#line 11039 "MachineIndependent/glslang_tab.cpp" +#line 11038 "MachineIndependent/glslang_tab.cpp" break; case 552: /* struct_declarator_list: struct_declarator */ -#line 3695 "MachineIndependent/glslang.y" +#line 3637 "MachineIndependent/glslang.y" { (yyval.interm.typeList) = new TTypeList; (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); } -#line 11048 "MachineIndependent/glslang_tab.cpp" +#line 11047 "MachineIndependent/glslang_tab.cpp" break; case 553: /* struct_declarator_list: struct_declarator_list COMMA struct_declarator */ -#line 3699 "MachineIndependent/glslang.y" +#line 3641 "MachineIndependent/glslang.y" { (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); } -#line 11056 "MachineIndependent/glslang_tab.cpp" +#line 11055 "MachineIndependent/glslang_tab.cpp" break; case 554: /* struct_declarator: IDENTIFIER */ -#line 3705 "MachineIndependent/glslang.y" +#line 3647 "MachineIndependent/glslang.y" { (yyval.interm.typeLine).type = new TType(EbtVoid); (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc; (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string); } -#line 11066 "MachineIndependent/glslang_tab.cpp" +#line 11065 "MachineIndependent/glslang_tab.cpp" break; case 555: /* struct_declarator: IDENTIFIER array_specifier */ -#line 3710 "MachineIndependent/glslang.y" +#line 3652 "MachineIndependent/glslang.y" { parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes); @@ -11075,246 +11074,246 @@ yyreduce: (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string); (yyval.interm.typeLine).type->transferArraySizes((yyvsp[0].interm).arraySizes); } -#line 11079 "MachineIndependent/glslang_tab.cpp" +#line 11078 "MachineIndependent/glslang_tab.cpp" break; case 556: /* initializer: assignment_expression */ -#line 3721 "MachineIndependent/glslang.y" +#line 3663 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 11087 "MachineIndependent/glslang_tab.cpp" +#line 11086 "MachineIndependent/glslang_tab.cpp" break; case 557: /* initializer: LEFT_BRACE initializer_list RIGHT_BRACE */ -#line 3725 "MachineIndependent/glslang.y" +#line 3666 "MachineIndependent/glslang.y" { const char* initFeature = "{ } style initializers"; parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature); parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); } -#line 11098 "MachineIndependent/glslang_tab.cpp" +#line 11097 "MachineIndependent/glslang_tab.cpp" break; case 558: /* initializer: LEFT_BRACE initializer_list COMMA RIGHT_BRACE */ -#line 3731 "MachineIndependent/glslang.y" +#line 3672 "MachineIndependent/glslang.y" { const char* initFeature = "{ } style initializers"; parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature); parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 11109 "MachineIndependent/glslang_tab.cpp" +#line 11108 "MachineIndependent/glslang_tab.cpp" break; case 559: /* initializer: LEFT_BRACE RIGHT_BRACE */ -#line 3737 "MachineIndependent/glslang.y" +#line 3678 "MachineIndependent/glslang.y" { const char* initFeature = "empty { } initializer"; parseContext.profileRequires((yyvsp[-1].lex).loc, EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); parseContext.profileRequires((yyvsp[-1].lex).loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); (yyval.interm.intermTypedNode) = parseContext.intermediate.makeAggregate((yyvsp[-1].lex).loc); } -#line 11120 "MachineIndependent/glslang_tab.cpp" +#line 11119 "MachineIndependent/glslang_tab.cpp" break; case 560: /* initializer_list: initializer */ -#line 3748 "MachineIndependent/glslang.y" +#line 3687 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc()); } -#line 11128 "MachineIndependent/glslang_tab.cpp" +#line 11127 "MachineIndependent/glslang_tab.cpp" break; case 561: /* initializer_list: initializer_list COMMA initializer */ -#line 3751 "MachineIndependent/glslang.y" +#line 3690 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); } -#line 11136 "MachineIndependent/glslang_tab.cpp" +#line 11135 "MachineIndependent/glslang_tab.cpp" break; case 562: /* declaration_statement: declaration */ -#line 3758 "MachineIndependent/glslang.y" +#line 3696 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11142 "MachineIndependent/glslang_tab.cpp" +#line 11141 "MachineIndependent/glslang_tab.cpp" break; case 563: /* statement: compound_statement */ -#line 3762 "MachineIndependent/glslang.y" +#line 3700 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11148 "MachineIndependent/glslang_tab.cpp" +#line 11147 "MachineIndependent/glslang_tab.cpp" break; case 564: /* statement: simple_statement */ -#line 3763 "MachineIndependent/glslang.y" +#line 3701 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11154 "MachineIndependent/glslang_tab.cpp" +#line 11153 "MachineIndependent/glslang_tab.cpp" break; case 565: /* simple_statement: declaration_statement */ -#line 3769 "MachineIndependent/glslang.y" +#line 3707 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11160 "MachineIndependent/glslang_tab.cpp" +#line 11159 "MachineIndependent/glslang_tab.cpp" break; case 566: /* simple_statement: expression_statement */ -#line 3770 "MachineIndependent/glslang.y" +#line 3708 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11166 "MachineIndependent/glslang_tab.cpp" +#line 11165 "MachineIndependent/glslang_tab.cpp" break; case 567: /* simple_statement: selection_statement */ -#line 3771 "MachineIndependent/glslang.y" +#line 3709 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11172 "MachineIndependent/glslang_tab.cpp" +#line 11171 "MachineIndependent/glslang_tab.cpp" break; case 568: /* simple_statement: switch_statement */ -#line 3772 "MachineIndependent/glslang.y" +#line 3710 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11178 "MachineIndependent/glslang_tab.cpp" +#line 11177 "MachineIndependent/glslang_tab.cpp" break; case 569: /* simple_statement: case_label */ -#line 3773 "MachineIndependent/glslang.y" +#line 3711 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11184 "MachineIndependent/glslang_tab.cpp" +#line 11183 "MachineIndependent/glslang_tab.cpp" break; case 570: /* simple_statement: iteration_statement */ -#line 3774 "MachineIndependent/glslang.y" +#line 3712 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11190 "MachineIndependent/glslang_tab.cpp" +#line 11189 "MachineIndependent/glslang_tab.cpp" break; case 571: /* simple_statement: jump_statement */ -#line 3775 "MachineIndependent/glslang.y" +#line 3713 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11196 "MachineIndependent/glslang_tab.cpp" +#line 11195 "MachineIndependent/glslang_tab.cpp" break; case 572: /* simple_statement: demote_statement */ -#line 3777 "MachineIndependent/glslang.y" +#line 3714 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11202 "MachineIndependent/glslang_tab.cpp" +#line 11201 "MachineIndependent/glslang_tab.cpp" break; case 573: /* demote_statement: DEMOTE SEMICOLON */ -#line 3783 "MachineIndependent/glslang.y" +#line 3718 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "demote"); parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote"); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDemote, (yyvsp[-1].lex).loc); } -#line 11212 "MachineIndependent/glslang_tab.cpp" +#line 11211 "MachineIndependent/glslang_tab.cpp" break; case 574: /* compound_statement: LEFT_BRACE RIGHT_BRACE */ -#line 3792 "MachineIndependent/glslang.y" +#line 3726 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = 0; } -#line 11218 "MachineIndependent/glslang_tab.cpp" +#line 11217 "MachineIndependent/glslang_tab.cpp" break; case 575: /* $@5: %empty */ -#line 3793 "MachineIndependent/glslang.y" +#line 3727 "MachineIndependent/glslang.y" { parseContext.symbolTable.push(); ++parseContext.statementNestingLevel; } -#line 11227 "MachineIndependent/glslang_tab.cpp" +#line 11226 "MachineIndependent/glslang_tab.cpp" break; case 576: /* $@6: %empty */ -#line 3797 "MachineIndependent/glslang.y" +#line 3731 "MachineIndependent/glslang.y" { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); --parseContext.statementNestingLevel; } -#line 11236 "MachineIndependent/glslang_tab.cpp" +#line 11235 "MachineIndependent/glslang_tab.cpp" break; case 577: /* compound_statement: LEFT_BRACE $@5 statement_list $@6 RIGHT_BRACE */ -#line 3801 "MachineIndependent/glslang.y" +#line 3735 "MachineIndependent/glslang.y" { if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate()) (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(parseContext.intermediate.getDebugInfo() ? EOpScope : EOpSequence); (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode); } -#line 11246 "MachineIndependent/glslang_tab.cpp" +#line 11245 "MachineIndependent/glslang_tab.cpp" break; case 578: /* statement_no_new_scope: compound_statement_no_new_scope */ -#line 3809 "MachineIndependent/glslang.y" +#line 3743 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11252 "MachineIndependent/glslang_tab.cpp" +#line 11251 "MachineIndependent/glslang_tab.cpp" break; case 579: /* statement_no_new_scope: simple_statement */ -#line 3810 "MachineIndependent/glslang.y" +#line 3744 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11258 "MachineIndependent/glslang_tab.cpp" +#line 11257 "MachineIndependent/glslang_tab.cpp" break; case 580: /* $@7: %empty */ -#line 3814 "MachineIndependent/glslang.y" +#line 3748 "MachineIndependent/glslang.y" { ++parseContext.controlFlowNestingLevel; } -#line 11266 "MachineIndependent/glslang_tab.cpp" +#line 11265 "MachineIndependent/glslang_tab.cpp" break; case 581: /* statement_scoped: $@7 compound_statement */ -#line 3817 "MachineIndependent/glslang.y" +#line 3751 "MachineIndependent/glslang.y" { --parseContext.controlFlowNestingLevel; (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11275 "MachineIndependent/glslang_tab.cpp" +#line 11274 "MachineIndependent/glslang_tab.cpp" break; case 582: /* $@8: %empty */ -#line 3821 "MachineIndependent/glslang.y" +#line 3755 "MachineIndependent/glslang.y" { parseContext.symbolTable.push(); ++parseContext.statementNestingLevel; ++parseContext.controlFlowNestingLevel; } -#line 11285 "MachineIndependent/glslang_tab.cpp" +#line 11284 "MachineIndependent/glslang_tab.cpp" break; case 583: /* statement_scoped: $@8 simple_statement */ -#line 3826 "MachineIndependent/glslang.y" +#line 3760 "MachineIndependent/glslang.y" { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11296 "MachineIndependent/glslang_tab.cpp" +#line 11295 "MachineIndependent/glslang_tab.cpp" break; case 584: /* compound_statement_no_new_scope: LEFT_BRACE RIGHT_BRACE */ -#line 3835 "MachineIndependent/glslang.y" +#line 3769 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = 0; } -#line 11304 "MachineIndependent/glslang_tab.cpp" +#line 11303 "MachineIndependent/glslang_tab.cpp" break; case 585: /* compound_statement_no_new_scope: LEFT_BRACE statement_list RIGHT_BRACE */ -#line 3838 "MachineIndependent/glslang.y" +#line 3772 "MachineIndependent/glslang.y" { if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate()) (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode); } -#line 11314 "MachineIndependent/glslang_tab.cpp" +#line 11313 "MachineIndependent/glslang_tab.cpp" break; case 586: /* statement_list: statement */ -#line 3846 "MachineIndependent/glslang.y" +#line 3780 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || @@ -11323,11 +11322,11 @@ yyreduce: (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case } } -#line 11327 "MachineIndependent/glslang_tab.cpp" +#line 11326 "MachineIndependent/glslang_tab.cpp" break; case 587: /* statement_list: statement_list statement */ -#line 3854 "MachineIndependent/glslang.y" +#line 3788 "MachineIndependent/glslang.y" { if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { @@ -11336,77 +11335,77 @@ yyreduce: } else (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); } -#line 11340 "MachineIndependent/glslang_tab.cpp" +#line 11339 "MachineIndependent/glslang_tab.cpp" break; case 588: /* expression_statement: SEMICOLON */ -#line 3865 "MachineIndependent/glslang.y" +#line 3799 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = 0; } -#line 11346 "MachineIndependent/glslang_tab.cpp" +#line 11345 "MachineIndependent/glslang_tab.cpp" break; case 589: /* expression_statement: expression SEMICOLON */ -#line 3866 "MachineIndependent/glslang.y" +#line 3800 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[-1].interm.intermTypedNode)); } -#line 11352 "MachineIndependent/glslang_tab.cpp" +#line 11351 "MachineIndependent/glslang_tab.cpp" break; case 590: /* selection_statement: selection_statement_nonattributed */ -#line 3870 "MachineIndependent/glslang.y" +#line 3804 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11360 "MachineIndependent/glslang_tab.cpp" +#line 11359 "MachineIndependent/glslang_tab.cpp" break; case 591: /* selection_statement: attribute selection_statement_nonattributed */ -#line 3874 "MachineIndependent/glslang.y" +#line 3807 "MachineIndependent/glslang.y" { parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleSelectionAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11370 "MachineIndependent/glslang_tab.cpp" +#line 11369 "MachineIndependent/glslang_tab.cpp" break; case 592: /* selection_statement_nonattributed: IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement */ -#line 3882 "MachineIndependent/glslang.y" +#line 3814 "MachineIndependent/glslang.y" { parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode)); (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc); } -#line 11379 "MachineIndependent/glslang_tab.cpp" +#line 11378 "MachineIndependent/glslang_tab.cpp" break; case 593: /* selection_rest_statement: statement_scoped ELSE statement_scoped */ -#line 3889 "MachineIndependent/glslang.y" +#line 3821 "MachineIndependent/glslang.y" { (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode); } -#line 11388 "MachineIndependent/glslang_tab.cpp" +#line 11387 "MachineIndependent/glslang_tab.cpp" break; case 594: /* selection_rest_statement: statement_scoped */ -#line 3893 "MachineIndependent/glslang.y" +#line 3825 "MachineIndependent/glslang.y" { (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); (yyval.interm.nodePair).node2 = 0; } -#line 11397 "MachineIndependent/glslang_tab.cpp" +#line 11396 "MachineIndependent/glslang_tab.cpp" break; case 595: /* condition: expression */ -#line 3901 "MachineIndependent/glslang.y" +#line 3833 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)); } -#line 11406 "MachineIndependent/glslang_tab.cpp" +#line 11405 "MachineIndependent/glslang_tab.cpp" break; case 596: /* condition: fully_specified_type IDENTIFIER EQUAL initializer */ -#line 3905 "MachineIndependent/glslang.y" +#line 3837 "MachineIndependent/glslang.y" { parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type)); @@ -11417,29 +11416,29 @@ yyreduce: else (yyval.interm.intermTypedNode) = 0; } -#line 11421 "MachineIndependent/glslang_tab.cpp" +#line 11420 "MachineIndependent/glslang_tab.cpp" break; case 597: /* switch_statement: switch_statement_nonattributed */ -#line 3918 "MachineIndependent/glslang.y" +#line 3850 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11429 "MachineIndependent/glslang_tab.cpp" +#line 11428 "MachineIndependent/glslang_tab.cpp" break; case 598: /* switch_statement: attribute switch_statement_nonattributed */ -#line 3922 "MachineIndependent/glslang.y" +#line 3853 "MachineIndependent/glslang.y" { parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleSwitchAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11439 "MachineIndependent/glslang_tab.cpp" +#line 11438 "MachineIndependent/glslang_tab.cpp" break; case 599: /* $@9: %empty */ -#line 3930 "MachineIndependent/glslang.y" +#line 3860 "MachineIndependent/glslang.y" { // start new switch sequence on the switch stack ++parseContext.controlFlowNestingLevel; @@ -11448,11 +11447,11 @@ yyreduce: parseContext.switchLevel.push_back(parseContext.statementNestingLevel); parseContext.symbolTable.push(); } -#line 11452 "MachineIndependent/glslang_tab.cpp" +#line 11451 "MachineIndependent/glslang_tab.cpp" break; case 600: /* switch_statement_nonattributed: SWITCH LEFT_PAREN expression RIGHT_PAREN $@9 LEFT_BRACE switch_statement_list RIGHT_BRACE */ -#line 3938 "MachineIndependent/glslang.y" +#line 3868 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0); delete parseContext.switchSequenceStack.back(); @@ -11462,27 +11461,27 @@ yyreduce: --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; } -#line 11466 "MachineIndependent/glslang_tab.cpp" +#line 11465 "MachineIndependent/glslang_tab.cpp" break; case 601: /* switch_statement_list: %empty */ -#line 3950 "MachineIndependent/glslang.y" +#line 3880 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = 0; } -#line 11474 "MachineIndependent/glslang_tab.cpp" +#line 11473 "MachineIndependent/glslang_tab.cpp" break; case 602: /* switch_statement_list: statement_list */ -#line 3953 "MachineIndependent/glslang.y" +#line 3883 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11482 "MachineIndependent/glslang_tab.cpp" +#line 11481 "MachineIndependent/glslang_tab.cpp" break; case 603: /* case_label: CASE expression COLON */ -#line 3959 "MachineIndependent/glslang.y" +#line 3889 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = 0; if (parseContext.switchLevel.size() == 0) @@ -11495,11 +11494,11 @@ yyreduce: (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc); } } -#line 11499 "MachineIndependent/glslang_tab.cpp" +#line 11498 "MachineIndependent/glslang_tab.cpp" break; case 604: /* case_label: DEFAULT COLON */ -#line 3971 "MachineIndependent/glslang.y" +#line 3901 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = 0; if (parseContext.switchLevel.size() == 0) @@ -11509,29 +11508,29 @@ yyreduce: else (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc); } -#line 11513 "MachineIndependent/glslang_tab.cpp" +#line 11512 "MachineIndependent/glslang_tab.cpp" break; case 605: /* iteration_statement: iteration_statement_nonattributed */ -#line 3983 "MachineIndependent/glslang.y" +#line 3913 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11521 "MachineIndependent/glslang_tab.cpp" +#line 11520 "MachineIndependent/glslang_tab.cpp" break; case 606: /* iteration_statement: attribute iteration_statement_nonattributed */ -#line 3987 "MachineIndependent/glslang.y" +#line 3916 "MachineIndependent/glslang.y" { parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleLoopAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11531 "MachineIndependent/glslang_tab.cpp" +#line 11530 "MachineIndependent/glslang_tab.cpp" break; case 607: /* $@10: %empty */ -#line 3995 "MachineIndependent/glslang.y" +#line 3923 "MachineIndependent/glslang.y" { if (! parseContext.limits.whileLoops) parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", ""); @@ -11540,11 +11539,11 @@ yyreduce: ++parseContext.statementNestingLevel; ++parseContext.controlFlowNestingLevel; } -#line 11544 "MachineIndependent/glslang_tab.cpp" +#line 11543 "MachineIndependent/glslang_tab.cpp" break; case 608: /* iteration_statement_nonattributed: WHILE LEFT_PAREN $@10 condition RIGHT_PAREN statement_no_new_scope */ -#line 4003 "MachineIndependent/glslang.y" +#line 3931 "MachineIndependent/glslang.y" { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc); @@ -11552,22 +11551,22 @@ yyreduce: --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; } -#line 11556 "MachineIndependent/glslang_tab.cpp" +#line 11555 "MachineIndependent/glslang_tab.cpp" break; case 609: /* $@11: %empty */ -#line 4010 "MachineIndependent/glslang.y" +#line 3938 "MachineIndependent/glslang.y" { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; ++parseContext.statementNestingLevel; ++parseContext.controlFlowNestingLevel; } -#line 11567 "MachineIndependent/glslang_tab.cpp" +#line 11566 "MachineIndependent/glslang_tab.cpp" break; case 610: /* iteration_statement_nonattributed: DO $@11 statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON */ -#line 4016 "MachineIndependent/glslang.y" +#line 3944 "MachineIndependent/glslang.y" { if (! parseContext.limits.whileLoops) parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", ""); @@ -11580,22 +11579,22 @@ yyreduce: --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; } -#line 11584 "MachineIndependent/glslang_tab.cpp" +#line 11583 "MachineIndependent/glslang_tab.cpp" break; case 611: /* $@12: %empty */ -#line 4028 "MachineIndependent/glslang.y" +#line 3956 "MachineIndependent/glslang.y" { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; ++parseContext.statementNestingLevel; ++parseContext.controlFlowNestingLevel; } -#line 11595 "MachineIndependent/glslang_tab.cpp" +#line 11594 "MachineIndependent/glslang_tab.cpp" break; case 612: /* iteration_statement_nonattributed: FOR LEFT_PAREN $@12 for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope */ -#line 4034 "MachineIndependent/glslang.y" +#line 3962 "MachineIndependent/glslang.y" { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc); @@ -11608,81 +11607,81 @@ yyreduce: --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; } -#line 11612 "MachineIndependent/glslang_tab.cpp" +#line 11611 "MachineIndependent/glslang_tab.cpp" break; case 613: /* for_init_statement: expression_statement */ -#line 4049 "MachineIndependent/glslang.y" +#line 3977 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11620 "MachineIndependent/glslang_tab.cpp" +#line 11619 "MachineIndependent/glslang_tab.cpp" break; case 614: /* for_init_statement: declaration_statement */ -#line 4052 "MachineIndependent/glslang.y" +#line 3980 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11628 "MachineIndependent/glslang_tab.cpp" +#line 11627 "MachineIndependent/glslang_tab.cpp" break; case 615: /* conditionopt: condition */ -#line 4058 "MachineIndependent/glslang.y" +#line 3986 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 11636 "MachineIndependent/glslang_tab.cpp" +#line 11635 "MachineIndependent/glslang_tab.cpp" break; case 616: /* conditionopt: %empty */ -#line 4061 "MachineIndependent/glslang.y" +#line 3989 "MachineIndependent/glslang.y" { (yyval.interm.intermTypedNode) = 0; } -#line 11644 "MachineIndependent/glslang_tab.cpp" +#line 11643 "MachineIndependent/glslang_tab.cpp" break; case 617: /* for_rest_statement: conditionopt SEMICOLON */ -#line 4067 "MachineIndependent/glslang.y" +#line 3995 "MachineIndependent/glslang.y" { (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode); (yyval.interm.nodePair).node2 = 0; } -#line 11653 "MachineIndependent/glslang_tab.cpp" +#line 11652 "MachineIndependent/glslang_tab.cpp" break; case 618: /* for_rest_statement: conditionopt SEMICOLON expression */ -#line 4071 "MachineIndependent/glslang.y" +#line 3999 "MachineIndependent/glslang.y" { (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode); (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode); } -#line 11662 "MachineIndependent/glslang_tab.cpp" +#line 11661 "MachineIndependent/glslang_tab.cpp" break; case 619: /* jump_statement: CONTINUE SEMICOLON */ -#line 4078 "MachineIndependent/glslang.y" +#line 4006 "MachineIndependent/glslang.y" { if (parseContext.loopNestingLevel <= 0) parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", ""); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc); } -#line 11672 "MachineIndependent/glslang_tab.cpp" +#line 11671 "MachineIndependent/glslang_tab.cpp" break; case 620: /* jump_statement: BREAK SEMICOLON */ -#line 4083 "MachineIndependent/glslang.y" +#line 4011 "MachineIndependent/glslang.y" { if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", ""); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc); } -#line 11682 "MachineIndependent/glslang_tab.cpp" +#line 11681 "MachineIndependent/glslang_tab.cpp" break; case 621: /* jump_statement: RETURN SEMICOLON */ -#line 4088 "MachineIndependent/glslang.y" +#line 4016 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc); if (parseContext.currentFunctionType->getBasicType() != EbtVoid) @@ -11690,101 +11689,101 @@ yyreduce: if (parseContext.inMain) parseContext.postEntryPointReturn = true; } -#line 11694 "MachineIndependent/glslang_tab.cpp" +#line 11693 "MachineIndependent/glslang_tab.cpp" break; case 622: /* jump_statement: RETURN expression SEMICOLON */ -#line 4095 "MachineIndependent/glslang.y" +#line 4023 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.handleReturnValue((yyvsp[-2].lex).loc, (yyvsp[-1].interm.intermTypedNode)); } -#line 11702 "MachineIndependent/glslang_tab.cpp" +#line 11701 "MachineIndependent/glslang_tab.cpp" break; case 623: /* jump_statement: DISCARD SEMICOLON */ -#line 4098 "MachineIndependent/glslang.y" +#line 4026 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard"); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc); } -#line 11711 "MachineIndependent/glslang_tab.cpp" +#line 11710 "MachineIndependent/glslang_tab.cpp" break; case 624: /* jump_statement: TERMINATE_INVOCATION SEMICOLON */ -#line 4102 "MachineIndependent/glslang.y" +#line 4030 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "terminateInvocation"); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpTerminateInvocation, (yyvsp[-1].lex).loc); } -#line 11720 "MachineIndependent/glslang_tab.cpp" +#line 11719 "MachineIndependent/glslang_tab.cpp" break; case 625: /* jump_statement: TERMINATE_RAY SEMICOLON */ -#line 4107 "MachineIndependent/glslang.y" +#line 4034 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[-1].lex).loc, EShLangAnyHit, "terminateRayEXT"); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpTerminateRayKHR, (yyvsp[-1].lex).loc); } -#line 11729 "MachineIndependent/glslang_tab.cpp" +#line 11728 "MachineIndependent/glslang_tab.cpp" break; case 626: /* jump_statement: IGNORE_INTERSECTION SEMICOLON */ -#line 4111 "MachineIndependent/glslang.y" +#line 4038 "MachineIndependent/glslang.y" { parseContext.requireStage((yyvsp[-1].lex).loc, EShLangAnyHit, "ignoreIntersectionEXT"); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpIgnoreIntersectionKHR, (yyvsp[-1].lex).loc); } -#line 11738 "MachineIndependent/glslang_tab.cpp" +#line 11737 "MachineIndependent/glslang_tab.cpp" break; case 627: /* translation_unit: external_declaration */ -#line 4121 "MachineIndependent/glslang.y" +#line 4047 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); } -#line 11747 "MachineIndependent/glslang_tab.cpp" +#line 11746 "MachineIndependent/glslang_tab.cpp" break; case 628: /* translation_unit: translation_unit external_declaration */ -#line 4125 "MachineIndependent/glslang.y" +#line 4051 "MachineIndependent/glslang.y" { if ((yyvsp[0].interm.intermNode) != nullptr) { (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); } } -#line 11758 "MachineIndependent/glslang_tab.cpp" +#line 11757 "MachineIndependent/glslang_tab.cpp" break; case 629: /* external_declaration: function_definition */ -#line 4134 "MachineIndependent/glslang.y" +#line 4060 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11766 "MachineIndependent/glslang_tab.cpp" +#line 11765 "MachineIndependent/glslang_tab.cpp" break; case 630: /* external_declaration: declaration */ -#line 4137 "MachineIndependent/glslang.y" +#line 4063 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11774 "MachineIndependent/glslang_tab.cpp" +#line 11773 "MachineIndependent/glslang_tab.cpp" break; case 631: /* external_declaration: SEMICOLON */ -#line 4141 "MachineIndependent/glslang.y" +#line 4066 "MachineIndependent/glslang.y" { parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "extraneous semicolon"); parseContext.profileRequires((yyvsp[0].lex).loc, ~EEsProfile, 460, nullptr, "extraneous semicolon"); (yyval.interm.intermNode) = nullptr; } -#line 11784 "MachineIndependent/glslang_tab.cpp" +#line 11783 "MachineIndependent/glslang_tab.cpp" break; case 632: /* $@13: %empty */ -#line 4150 "MachineIndependent/glslang.y" +#line 4074 "MachineIndependent/glslang.y" { (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */); (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function); @@ -11797,17 +11796,18 @@ yyreduce: ++parseContext.statementNestingLevel; } } -#line 11801 "MachineIndependent/glslang_tab.cpp" +#line 11800 "MachineIndependent/glslang_tab.cpp" break; case 633: /* function_definition: function_prototype $@13 compound_statement_no_new_scope */ -#line 4162 "MachineIndependent/glslang.y" +#line 4086 "MachineIndependent/glslang.y" { // May be best done as post process phase on intermediate code if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) parseContext.error((yyvsp[-2].interm).loc, "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str()); parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermNode)); + (yyval.interm.intermNode)->getAsAggregate()->setLinkType((yyvsp[-2].interm).function->getLinkType()); parseContext.intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[-2].interm).function->getType(), (yyvsp[-2].interm).loc); (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str()); @@ -11832,7 +11832,7 @@ yyreduce: break; case 634: /* attribute: LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET */ -#line 4192 "MachineIndependent/glslang.y" +#line 4116 "MachineIndependent/glslang.y" { (yyval.interm.attributes) = (yyvsp[-2].interm.attributes); } @@ -11840,7 +11840,7 @@ yyreduce: break; case 635: /* attribute_list: single_attribute */ -#line 4197 "MachineIndependent/glslang.y" +#line 4121 "MachineIndependent/glslang.y" { (yyval.interm.attributes) = (yyvsp[0].interm.attributes); } @@ -11848,7 +11848,7 @@ yyreduce: break; case 636: /* attribute_list: attribute_list COMMA single_attribute */ -#line 4200 "MachineIndependent/glslang.y" +#line 4124 "MachineIndependent/glslang.y" { (yyval.interm.attributes) = parseContext.mergeAttributes((yyvsp[-2].interm.attributes), (yyvsp[0].interm.attributes)); } @@ -11856,7 +11856,7 @@ yyreduce: break; case 637: /* single_attribute: IDENTIFIER */ -#line 4205 "MachineIndependent/glslang.y" +#line 4129 "MachineIndependent/glslang.y" { (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[0].lex).string); } @@ -11864,7 +11864,7 @@ yyreduce: break; case 638: /* single_attribute: IDENTIFIER LEFT_PAREN constant_expression RIGHT_PAREN */ -#line 4208 "MachineIndependent/glslang.y" +#line 4132 "MachineIndependent/glslang.y" { (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[-3].lex).string, (yyvsp[-1].interm.intermTypedNode)); } @@ -11872,7 +11872,7 @@ yyreduce: break; case 639: /* spirv_requirements_list: spirv_requirements_parameter */ -#line 4215 "MachineIndependent/glslang.y" +#line 4137 "MachineIndependent/glslang.y" { (yyval.interm.spirvReq) = (yyvsp[0].interm.spirvReq); } @@ -11880,7 +11880,7 @@ yyreduce: break; case 640: /* spirv_requirements_list: spirv_requirements_list COMMA spirv_requirements_parameter */ -#line 4218 "MachineIndependent/glslang.y" +#line 4140 "MachineIndependent/glslang.y" { (yyval.interm.spirvReq) = parseContext.mergeSpirvRequirements((yyvsp[-1].lex).loc, (yyvsp[-2].interm.spirvReq), (yyvsp[0].interm.spirvReq)); } @@ -11888,7 +11888,7 @@ yyreduce: break; case 641: /* spirv_requirements_parameter: IDENTIFIER EQUAL LEFT_BRACKET spirv_extension_list RIGHT_BRACKET */ -#line 4223 "MachineIndependent/glslang.y" +#line 4145 "MachineIndependent/glslang.y" { (yyval.interm.spirvReq) = parseContext.makeSpirvRequirement((yyvsp[-3].lex).loc, *(yyvsp[-4].lex).string, (yyvsp[-1].interm.intermNode)->getAsAggregate(), nullptr); } @@ -11896,7 +11896,7 @@ yyreduce: break; case 642: /* spirv_requirements_parameter: IDENTIFIER EQUAL LEFT_BRACKET spirv_capability_list RIGHT_BRACKET */ -#line 4226 "MachineIndependent/glslang.y" +#line 4148 "MachineIndependent/glslang.y" { (yyval.interm.spirvReq) = parseContext.makeSpirvRequirement((yyvsp[-3].lex).loc, *(yyvsp[-4].lex).string, nullptr, (yyvsp[-1].interm.intermNode)->getAsAggregate()); } @@ -11904,7 +11904,7 @@ yyreduce: break; case 643: /* spirv_extension_list: STRING_LITERAL */ -#line 4231 "MachineIndependent/glslang.y" +#line 4153 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); } @@ -11912,7 +11912,7 @@ yyreduce: break; case 644: /* spirv_extension_list: spirv_extension_list COMMA STRING_LITERAL */ -#line 4234 "MachineIndependent/glslang.y" +#line 4156 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); } @@ -11920,7 +11920,7 @@ yyreduce: break; case 645: /* spirv_capability_list: INTCONSTANT */ -#line 4239 "MachineIndependent/glslang.y" +#line 4161 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true)); } @@ -11928,7 +11928,7 @@ yyreduce: break; case 646: /* spirv_capability_list: spirv_capability_list COMMA INTCONSTANT */ -#line 4242 "MachineIndependent/glslang.y" +#line 4164 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true)); } @@ -11936,7 +11936,7 @@ yyreduce: break; case 647: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT RIGHT_PAREN */ -#line 4247 "MachineIndependent/glslang.y" +#line 4169 "MachineIndependent/glslang.y" { parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-1].lex).i); (yyval.interm.intermNode) = 0; @@ -11945,7 +11945,7 @@ yyreduce: break; case 648: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ -#line 4251 "MachineIndependent/glslang.y" +#line 4173 "MachineIndependent/glslang.y" { parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-1].lex).i); @@ -11955,7 +11955,7 @@ yyreduce: break; case 649: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN */ -#line 4256 "MachineIndependent/glslang.y" +#line 4178 "MachineIndependent/glslang.y" { parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); (yyval.interm.intermNode) = 0; @@ -11964,7 +11964,7 @@ yyreduce: break; case 650: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN */ -#line 4260 "MachineIndependent/glslang.y" +#line 4182 "MachineIndependent/glslang.y" { parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); @@ -11974,7 +11974,7 @@ yyreduce: break; case 651: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE_ID LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN */ -#line 4265 "MachineIndependent/glslang.y" +#line 4187 "MachineIndependent/glslang.y" { parseContext.intermediate.insertSpirvExecutionModeId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); (yyval.interm.intermNode) = 0; @@ -11983,7 +11983,7 @@ yyreduce: break; case 652: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN */ -#line 4269 "MachineIndependent/glslang.y" +#line 4191 "MachineIndependent/glslang.y" { parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); parseContext.intermediate.insertSpirvExecutionModeId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); @@ -11993,7 +11993,7 @@ yyreduce: break; case 653: /* spirv_execution_mode_parameter_list: spirv_execution_mode_parameter */ -#line 4276 "MachineIndependent/glslang.y" +#line 4198 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); } @@ -12001,7 +12001,7 @@ yyreduce: break; case 654: /* spirv_execution_mode_parameter_list: spirv_execution_mode_parameter_list COMMA spirv_execution_mode_parameter */ -#line 4279 "MachineIndependent/glslang.y" +#line 4201 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermNode)); } @@ -12009,7 +12009,7 @@ yyreduce: break; case 655: /* spirv_execution_mode_parameter: FLOATCONSTANT */ -#line 4284 "MachineIndependent/glslang.y" +#line 4206 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); } @@ -12017,7 +12017,7 @@ yyreduce: break; case 656: /* spirv_execution_mode_parameter: INTCONSTANT */ -#line 4287 "MachineIndependent/glslang.y" +#line 4209 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); } @@ -12025,7 +12025,7 @@ yyreduce: break; case 657: /* spirv_execution_mode_parameter: UINTCONSTANT */ -#line 4290 "MachineIndependent/glslang.y" +#line 4212 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); } @@ -12033,7 +12033,7 @@ yyreduce: break; case 658: /* spirv_execution_mode_parameter: BOOLCONSTANT */ -#line 4293 "MachineIndependent/glslang.y" +#line 4215 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); } @@ -12041,7 +12041,7 @@ yyreduce: break; case 659: /* spirv_execution_mode_parameter: STRING_LITERAL */ -#line 4296 "MachineIndependent/glslang.y" +#line 4218 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true); } @@ -12049,7 +12049,7 @@ yyreduce: break; case 660: /* spirv_execution_mode_id_parameter_list: constant_expression */ -#line 4301 "MachineIndependent/glslang.y" +#line 4223 "MachineIndependent/glslang.y" { if ((yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtFloat && (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtInt && @@ -12063,7 +12063,7 @@ yyreduce: break; case 661: /* spirv_execution_mode_id_parameter_list: spirv_execution_mode_id_parameter_list COMMA constant_expression */ -#line 4310 "MachineIndependent/glslang.y" +#line 4232 "MachineIndependent/glslang.y" { if ((yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtFloat && (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtInt && @@ -12077,7 +12077,7 @@ yyreduce: break; case 662: /* spirv_storage_class_qualifier: SPIRV_STORAGE_CLASS LEFT_PAREN INTCONSTANT RIGHT_PAREN */ -#line 4321 "MachineIndependent/glslang.y" +#line 4243 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-3].lex).loc); (yyval.interm.type).qualifier.storage = EvqSpirvStorageClass; @@ -12087,7 +12087,7 @@ yyreduce: break; case 663: /* spirv_storage_class_qualifier: SPIRV_STORAGE_CLASS LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ -#line 4326 "MachineIndependent/glslang.y" +#line 4248 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-5].lex).loc); parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); @@ -12098,7 +12098,7 @@ yyreduce: break; case 664: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN INTCONSTANT RIGHT_PAREN */ -#line 4334 "MachineIndependent/glslang.y" +#line 4256 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-3].lex).loc); (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-1].lex).i); @@ -12107,7 +12107,7 @@ yyreduce: break; case 665: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ -#line 4338 "MachineIndependent/glslang.y" +#line 4260 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-5].lex).loc); parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); @@ -12117,7 +12117,7 @@ yyreduce: break; case 666: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN */ -#line 4343 "MachineIndependent/glslang.y" +#line 4265 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-5].lex).loc); (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); @@ -12126,7 +12126,7 @@ yyreduce: break; case 667: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN */ -#line 4347 "MachineIndependent/glslang.y" +#line 4269 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-7].lex).loc); parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); @@ -12136,7 +12136,7 @@ yyreduce: break; case 668: /* spirv_decorate_qualifier: SPIRV_DECORATE_ID LEFT_PAREN INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN */ -#line 4352 "MachineIndependent/glslang.y" +#line 4274 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-5].lex).loc); (yyval.interm.type).qualifier.setSpirvDecorateId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); @@ -12145,7 +12145,7 @@ yyreduce: break; case 669: /* spirv_decorate_qualifier: SPIRV_DECORATE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN */ -#line 4356 "MachineIndependent/glslang.y" +#line 4278 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-7].lex).loc); parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); @@ -12155,7 +12155,7 @@ yyreduce: break; case 670: /* spirv_decorate_qualifier: SPIRV_DECORATE_STRING LEFT_PAREN INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN */ -#line 4361 "MachineIndependent/glslang.y" +#line 4283 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-5].lex).loc); (yyval.interm.type).qualifier.setSpirvDecorateString((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); @@ -12164,7 +12164,7 @@ yyreduce: break; case 671: /* spirv_decorate_qualifier: SPIRV_DECORATE_STRING LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN */ -#line 4365 "MachineIndependent/glslang.y" +#line 4287 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-7].lex).loc); parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); @@ -12174,7 +12174,7 @@ yyreduce: break; case 672: /* spirv_decorate_parameter_list: spirv_decorate_parameter */ -#line 4372 "MachineIndependent/glslang.y" +#line 4294 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); } @@ -12182,7 +12182,7 @@ yyreduce: break; case 673: /* spirv_decorate_parameter_list: spirv_decorate_parameter_list COMMA spirv_decorate_parameter */ -#line 4375 "MachineIndependent/glslang.y" +#line 4297 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermNode)); } @@ -12190,7 +12190,7 @@ yyreduce: break; case 674: /* spirv_decorate_parameter: FLOATCONSTANT */ -#line 4380 "MachineIndependent/glslang.y" +#line 4302 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); } @@ -12198,7 +12198,7 @@ yyreduce: break; case 675: /* spirv_decorate_parameter: INTCONSTANT */ -#line 4383 "MachineIndependent/glslang.y" +#line 4305 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); } @@ -12206,7 +12206,7 @@ yyreduce: break; case 676: /* spirv_decorate_parameter: UINTCONSTANT */ -#line 4386 "MachineIndependent/glslang.y" +#line 4308 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); } @@ -12214,7 +12214,7 @@ yyreduce: break; case 677: /* spirv_decorate_parameter: BOOLCONSTANT */ -#line 4389 "MachineIndependent/glslang.y" +#line 4311 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); } @@ -12222,7 +12222,7 @@ yyreduce: break; case 678: /* spirv_decorate_id_parameter_list: spirv_decorate_id_parameter */ -#line 4394 "MachineIndependent/glslang.y" +#line 4316 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); } @@ -12230,7 +12230,7 @@ yyreduce: break; case 679: /* spirv_decorate_id_parameter_list: spirv_decorate_id_parameter_list COMMA spirv_decorate_id_parameter */ -#line 4397 "MachineIndependent/glslang.y" +#line 4319 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermNode)); } @@ -12238,7 +12238,7 @@ yyreduce: break; case 680: /* spirv_decorate_id_parameter: variable_identifier */ -#line 4402 "MachineIndependent/glslang.y" +#line 4324 "MachineIndependent/glslang.y" { if ((yyvsp[0].interm.intermTypedNode)->getAsConstantUnion() || (yyvsp[0].interm.intermTypedNode)->getAsSymbolNode()) (yyval.interm.intermNode) = (yyvsp[0].interm.intermTypedNode); @@ -12249,7 +12249,7 @@ yyreduce: break; case 681: /* spirv_decorate_id_parameter: FLOATCONSTANT */ -#line 4408 "MachineIndependent/glslang.y" +#line 4330 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); } @@ -12257,7 +12257,7 @@ yyreduce: break; case 682: /* spirv_decorate_id_parameter: INTCONSTANT */ -#line 4411 "MachineIndependent/glslang.y" +#line 4333 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); } @@ -12265,7 +12265,7 @@ yyreduce: break; case 683: /* spirv_decorate_id_parameter: UINTCONSTANT */ -#line 4414 "MachineIndependent/glslang.y" +#line 4336 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); } @@ -12273,7 +12273,7 @@ yyreduce: break; case 684: /* spirv_decorate_id_parameter: BOOLCONSTANT */ -#line 4417 "MachineIndependent/glslang.y" +#line 4339 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); } @@ -12281,7 +12281,7 @@ yyreduce: break; case 685: /* spirv_decorate_string_parameter_list: STRING_LITERAL */ -#line 4422 "MachineIndependent/glslang.y" +#line 4344 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate( parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); @@ -12290,7 +12290,7 @@ yyreduce: break; case 686: /* spirv_decorate_string_parameter_list: spirv_decorate_string_parameter_list COMMA STRING_LITERAL */ -#line 4426 "MachineIndependent/glslang.y" +#line 4348 "MachineIndependent/glslang.y" { (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); } @@ -12298,7 +12298,7 @@ yyreduce: break; case 687: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN */ -#line 4431 "MachineIndependent/glslang.y" +#line 4353 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-5].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).setSpirvType(*(yyvsp[-3].interm.spirvInst), (yyvsp[-1].interm.spirvTypeParams)); @@ -12307,7 +12307,7 @@ yyreduce: break; case 688: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN */ -#line 4435 "MachineIndependent/glslang.y" +#line 4357 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-7].lex).loc, parseContext.symbolTable.atGlobalLevel()); parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); @@ -12317,7 +12317,7 @@ yyreduce: break; case 689: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN */ -#line 4440 "MachineIndependent/glslang.y" +#line 4362 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-3].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).setSpirvType(*(yyvsp[-1].interm.spirvInst)); @@ -12326,7 +12326,7 @@ yyreduce: break; case 690: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN */ -#line 4444 "MachineIndependent/glslang.y" +#line 4366 "MachineIndependent/glslang.y" { (yyval.interm.type).init((yyvsp[-5].lex).loc, parseContext.symbolTable.atGlobalLevel()); parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); @@ -12336,7 +12336,7 @@ yyreduce: break; case 691: /* spirv_type_parameter_list: spirv_type_parameter */ -#line 4451 "MachineIndependent/glslang.y" +#line 4373 "MachineIndependent/glslang.y" { (yyval.interm.spirvTypeParams) = (yyvsp[0].interm.spirvTypeParams); } @@ -12344,7 +12344,7 @@ yyreduce: break; case 692: /* spirv_type_parameter_list: spirv_type_parameter_list COMMA spirv_type_parameter */ -#line 4454 "MachineIndependent/glslang.y" +#line 4376 "MachineIndependent/glslang.y" { (yyval.interm.spirvTypeParams) = parseContext.mergeSpirvTypeParameters((yyvsp[-2].interm.spirvTypeParams), (yyvsp[0].interm.spirvTypeParams)); } @@ -12352,7 +12352,7 @@ yyreduce: break; case 693: /* spirv_type_parameter: constant_expression */ -#line 4459 "MachineIndependent/glslang.y" +#line 4381 "MachineIndependent/glslang.y" { (yyval.interm.spirvTypeParams) = parseContext.makeSpirvTypeParameters((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)->getAsConstantUnion()); } @@ -12360,7 +12360,7 @@ yyreduce: break; case 694: /* spirv_type_parameter: type_specifier_nonarray */ -#line 4462 "MachineIndependent/glslang.y" +#line 4384 "MachineIndependent/glslang.y" { (yyval.interm.spirvTypeParams) = parseContext.makeSpirvTypeParameters((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); } @@ -12368,7 +12368,7 @@ yyreduce: break; case 695: /* spirv_instruction_qualifier: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN */ -#line 4467 "MachineIndependent/glslang.y" +#line 4389 "MachineIndependent/glslang.y" { (yyval.interm.spirvInst) = (yyvsp[-1].interm.spirvInst); } @@ -12376,7 +12376,7 @@ yyreduce: break; case 696: /* spirv_instruction_qualifier: SPIRV_INSTRUCTION LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN */ -#line 4470 "MachineIndependent/glslang.y" +#line 4392 "MachineIndependent/glslang.y" { parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); (yyval.interm.spirvInst) = (yyvsp[-1].interm.spirvInst); @@ -12385,7 +12385,7 @@ yyreduce: break; case 697: /* spirv_instruction_qualifier_list: spirv_instruction_qualifier_id */ -#line 4476 "MachineIndependent/glslang.y" +#line 4398 "MachineIndependent/glslang.y" { (yyval.interm.spirvInst) = (yyvsp[0].interm.spirvInst); } @@ -12393,7 +12393,7 @@ yyreduce: break; case 698: /* spirv_instruction_qualifier_list: spirv_instruction_qualifier_list COMMA spirv_instruction_qualifier_id */ -#line 4479 "MachineIndependent/glslang.y" +#line 4401 "MachineIndependent/glslang.y" { (yyval.interm.spirvInst) = parseContext.mergeSpirvInstruction((yyvsp[-1].lex).loc, (yyvsp[-2].interm.spirvInst), (yyvsp[0].interm.spirvInst)); } @@ -12401,7 +12401,7 @@ yyreduce: break; case 699: /* spirv_instruction_qualifier_id: IDENTIFIER EQUAL STRING_LITERAL */ -#line 4484 "MachineIndependent/glslang.y" +#line 4406 "MachineIndependent/glslang.y" { (yyval.interm.spirvInst) = parseContext.makeSpirvInstruction((yyvsp[-1].lex).loc, *(yyvsp[-2].lex).string, *(yyvsp[0].lex).string); } @@ -12409,7 +12409,7 @@ yyreduce: break; case 700: /* spirv_instruction_qualifier_id: IDENTIFIER EQUAL INTCONSTANT */ -#line 4487 "MachineIndependent/glslang.y" +#line 4409 "MachineIndependent/glslang.y" { (yyval.interm.spirvInst) = parseContext.makeSpirvInstruction((yyvsp[-1].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[0].lex).i); } @@ -12641,5 +12641,5 @@ yyreturnlab: return yyresult; } -#line 4492 "MachineIndependent/glslang.y" +#line 4413 "MachineIndependent/glslang.y" diff --git a/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h b/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h index 39455f276d..d6484924d6 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h +++ b/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h @@ -524,7 +524,7 @@ extern int yydebug; #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { -#line 97 "MachineIndependent/glslang.y" +#line 72 "MachineIndependent/glslang.y" struct { glslang::TSourceLoc loc; diff --git a/thirdparty/glslang/glslang/MachineIndependent/intermOut.cpp b/thirdparty/glslang/glslang/MachineIndependent/intermOut.cpp index d5fc26bbf2..32c3c573f9 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/intermOut.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/intermOut.cpp @@ -1141,6 +1141,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node case EOpHitObjectGetShaderBindingTableRecordIndexNV: out.debug << "HitObjectGetShaderBindingTableRecordIndexNV"; break; case EOpHitObjectGetShaderRecordBufferHandleNV: out.debug << "HitObjectReadShaderRecordBufferHandleNV"; break; case EOpReorderThreadNV: out.debug << "ReorderThreadNV"; break; + case EOpFetchMicroTriangleVertexPositionNV: out.debug << "MicroTriangleVertexPositionNV"; break; + case EOpFetchMicroTriangleVertexBarycentricNV: out.debug << "MicroTriangleVertexBarycentricNV"; break; case EOpSpirvInst: out.debug << "spirv_instruction"; break; case EOpStencilAttachmentReadEXT: out.debug << "stencilAttachmentReadEXT"; break; diff --git a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp index 8d2e85f0be..16b9d24376 100644 --- a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -378,8 +378,6 @@ namespace { int op_cmpl(int a) { return ~a; } int op_not(int a) { return !a; } -}; - struct TBinop { int token, precedence, (*op)(int, int); } binop[] = { @@ -412,6 +410,8 @@ struct TUnop { { '!', op_not }, }; +} // anonymous namespace + #define NUM_ELEMENTS(A) (sizeof(A) / sizeof(A[0])) int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) diff --git a/thirdparty/glslang/glslang/Public/ShaderLang.h b/thirdparty/glslang/glslang/Public/ShaderLang.h index e037e63f0b..c22cb2b43e 100644 --- a/thirdparty/glslang/glslang/Public/ShaderLang.h +++ b/thirdparty/glslang/glslang/Public/ShaderLang.h @@ -573,6 +573,9 @@ public: void setEnvInputVulkanRulesRelaxed() { environment.input.vulkanRulesRelaxed = true; } bool getEnvInputVulkanRulesRelaxed() const { return environment.input.vulkanRulesRelaxed; } + void setCompileOnly() { compileOnly = true; } + bool getCompileOnly() const { return compileOnly; } + // Interface to #include handlers. // // To support #include, a client of Glslang does the following: @@ -722,6 +725,9 @@ protected: TEnvironment environment; + // Indicates this shader is meant to be used without linking + bool compileOnly = false; + friend class TProgram; private: diff --git a/thirdparty/glslang/glslang/build_info.h b/thirdparty/glslang/glslang/build_info.h index 8bffae570a..c25117eefe 100644 --- a/thirdparty/glslang/glslang/build_info.h +++ b/thirdparty/glslang/glslang/build_info.h @@ -34,8 +34,8 @@ #ifndef GLSLANG_BUILD_INFO #define GLSLANG_BUILD_INFO -#define GLSLANG_VERSION_MAJOR 12 -#define GLSLANG_VERSION_MINOR 3 +#define GLSLANG_VERSION_MAJOR 13 +#define GLSLANG_VERSION_MINOR 1 #define GLSLANG_VERSION_PATCH 1 #define GLSLANG_VERSION_FLAVOR "" diff --git a/thirdparty/icu4c/LICENSE b/thirdparty/icu4c/LICENSE index 22472dc2ec..9f54372feb 100644 --- a/thirdparty/icu4c/LICENSE +++ b/thirdparty/icu4c/LICENSE @@ -1,49 +1,42 @@ -UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE - -See Terms of Use <https://www.unicode.org/copyright.html> -for definitions of Unicode Inc.’s Data Files and Software. - -NOTICE TO USER: Carefully read the following legal agreement. -BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S -DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), -YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE -TERMS AND CONDITIONS OF THIS AGREEMENT. -IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE -THE DATA FILES OR SOFTWARE. +UNICODE LICENSE V3 COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2023 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in https://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that either -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, or -(b) this copyright and permission notice appear in associated -Documentation. - -THE DATA FILES AND SOFTWARE ARE 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 OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. +Copyright © 2016-2023 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +software and any associated documentation (the "Software") to deal in the +Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that either (a) +this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE 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 OF +THIRD PARTY RIGHTS. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. ---------------------------------------------------------------------- diff --git a/thirdparty/icu4c/common/brkeng.cpp b/thirdparty/icu4c/common/brkeng.cpp index ce3d09cf23..3f58287532 100644 --- a/thirdparty/icu4c/common/brkeng.cpp +++ b/thirdparty/icu4c/common/brkeng.cpp @@ -21,6 +21,7 @@ #include "unicode/uscript.h" #include "unicode/ucharstrie.h" #include "unicode/bytestrie.h" +#include "unicode/rbbi.h" #include "brkeng.h" #include "cmemory.h" @@ -70,19 +71,21 @@ UnhandledEngine::~UnhandledEngine() { } UBool -UnhandledEngine::handles(UChar32 c) const { +UnhandledEngine::handles(UChar32 c, const char* locale) const { + (void)locale; // Unused return fHandled && fHandled->contains(c); } int32_t UnhandledEngine::findBreaks( UText *text, - int32_t /* startPos */, + int32_t startPos, int32_t endPos, UVector32 &/*foundBreaks*/, UBool /* isPhraseBreaking */, UErrorCode &status) const { if (U_FAILURE(status)) return 0; - UChar32 c = utext_current32(text); + utext_setNativeIndex(text, startPos); + UChar32 c = utext_current32(text); while((int32_t)utext_getNativeIndex(text) < endPos && fHandled->contains(c)) { utext_next32(text); // TODO: recast loop to work with post-increment operations. c = utext_current32(text); @@ -120,41 +123,39 @@ ICULanguageBreakFactory::~ICULanguageBreakFactory() { } } -U_NAMESPACE_END -U_CDECL_BEGIN -static void U_CALLCONV _deleteEngine(void *obj) { - delete (const icu::LanguageBreakEngine *) obj; +void ICULanguageBreakFactory::ensureEngines(UErrorCode& status) { + static UMutex gBreakEngineMutex; + Mutex m(&gBreakEngineMutex); + if (fEngines == nullptr) { + LocalPointer<UStack> engines(new UStack(uprv_deleteUObject, nullptr, status), status); + if (U_SUCCESS(status)) { + fEngines = engines.orphan(); + } + } } -U_CDECL_END -U_NAMESPACE_BEGIN const LanguageBreakEngine * -ICULanguageBreakFactory::getEngineFor(UChar32 c) { +ICULanguageBreakFactory::getEngineFor(UChar32 c, const char* locale) { const LanguageBreakEngine *lbe = nullptr; UErrorCode status = U_ZERO_ERROR; + ensureEngines(status); + if (U_FAILURE(status) ) { + // Note: no way to return error code to caller. + return nullptr; + } static UMutex gBreakEngineMutex; Mutex m(&gBreakEngineMutex); - - if (fEngines == nullptr) { - LocalPointer<UStack> engines(new UStack(_deleteEngine, nullptr, status), status); - if (U_FAILURE(status) ) { - // Note: no way to return error code to caller. - return nullptr; - } - fEngines = engines.orphan(); - } else { - int32_t i = fEngines->size(); - while (--i >= 0) { - lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); - if (lbe != nullptr && lbe->handles(c)) { - return lbe; - } + int32_t i = fEngines->size(); + while (--i >= 0) { + lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); + if (lbe != nullptr && lbe->handles(c, locale)) { + return lbe; } } - + // We didn't find an engine. Create one. - lbe = loadEngineFor(c); + lbe = loadEngineFor(c, locale); if (lbe != nullptr) { fEngines->push((void *)lbe, status); } @@ -162,7 +163,7 @@ ICULanguageBreakFactory::getEngineFor(UChar32 c) { } const LanguageBreakEngine * -ICULanguageBreakFactory::loadEngineFor(UChar32 c) { +ICULanguageBreakFactory::loadEngineFor(UChar32 c, const char*) { UErrorCode status = U_ZERO_ERROR; UScriptCode code = uscript_getScript(c, &status); if (U_SUCCESS(status)) { @@ -299,6 +300,70 @@ ICULanguageBreakFactory::loadDictionaryMatcherFor(UScriptCode script) { return nullptr; } + +void ICULanguageBreakFactory::addExternalEngine( + ExternalBreakEngine* external, UErrorCode& status) { + LocalPointer<ExternalBreakEngine> engine(external, status); + ensureEngines(status); + LocalPointer<BreakEngineWrapper> wrapper( + new BreakEngineWrapper(engine.orphan(), status), status); + static UMutex gBreakEngineMutex; + Mutex m(&gBreakEngineMutex); + fEngines->push(wrapper.getAlias(), status); + wrapper.orphan(); +} + +BreakEngineWrapper::BreakEngineWrapper( + ExternalBreakEngine* engine, UErrorCode &status) : delegate(engine, status) { +} + +BreakEngineWrapper::~BreakEngineWrapper() { +} + +UBool BreakEngineWrapper::handles(UChar32 c, const char* locale) const { + return delegate->isFor(c, locale); +} + +int32_t BreakEngineWrapper::findBreaks( + UText *text, + int32_t startPos, + int32_t endPos, + UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, + UErrorCode &status) const { + if (U_FAILURE(status)) return 0; + int32_t result = 0; + + // Find the span of characters included in the set. + // The span to break begins at the current position in the text, and + // extends towards the start or end of the text, depending on 'reverse'. + + utext_setNativeIndex(text, startPos); + int32_t start = (int32_t)utext_getNativeIndex(text); + int32_t current; + int32_t rangeStart; + int32_t rangeEnd; + UChar32 c = utext_current32(text); + while((current = (int32_t)utext_getNativeIndex(text)) < endPos && delegate->handles(c)) { + utext_next32(text); // TODO: recast loop for postincrement + c = utext_current32(text); + } + rangeStart = start; + rangeEnd = current; + int32_t beforeSize = foundBreaks.size(); + int32_t additionalCapacity = rangeEnd - rangeStart + 1; + // enlarge to contains (rangeEnd-rangeStart+1) more items + foundBreaks.ensureCapacity(beforeSize+additionalCapacity, status); + if (U_FAILURE(status)) return 0; + foundBreaks.setSize(beforeSize + beforeSize+additionalCapacity); + result = delegate->fillBreaks(text, rangeStart, rangeEnd, foundBreaks.getBuffer()+beforeSize, + additionalCapacity, status); + if (U_FAILURE(status)) return 0; + foundBreaks.setSize(beforeSize + result); + utext_setNativeIndex(text, current); + return result; +} + U_NAMESPACE_END #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ diff --git a/thirdparty/icu4c/common/brkeng.h b/thirdparty/icu4c/common/brkeng.h index 240dc8f4d3..42a3d697cf 100644 --- a/thirdparty/icu4c/common/brkeng.h +++ b/thirdparty/icu4c/common/brkeng.h @@ -10,6 +10,7 @@ #ifndef BRKENG_H #define BRKENG_H +#include "unicode/umisc.h" #include "unicode/utypes.h" #include "unicode/uobject.h" #include "unicode/utext.h" @@ -21,6 +22,7 @@ class UnicodeSet; class UStack; class UVector32; class DictionaryMatcher; +class ExternalBreakEngine; /******************************************************************* * LanguageBreakEngine @@ -35,7 +37,7 @@ class DictionaryMatcher; * <p>LanguageBreakEngines should normally be implemented so as to * be shared between threads without locking.</p> */ -class LanguageBreakEngine : public UMemory { +class LanguageBreakEngine : public UObject { public: /** @@ -54,10 +56,11 @@ class LanguageBreakEngine : public UMemory { * a particular kind of break.</p> * * @param c A character which begins a run that the engine might handle + * @param locale The locale. * @return true if this engine handles the particular character and break * type. */ - virtual UBool handles(UChar32 c) const = 0; + virtual UBool handles(UChar32 c, const char* locale) const = 0; /** * <p>Find any breaks within a run in the supplied text.</p> @@ -81,6 +84,35 @@ class LanguageBreakEngine : public UMemory { }; /******************************************************************* + * BreakEngineWrapper + */ + +/** + * <p>BreakEngineWrapper implement LanguageBreakEngine by + * a thin wrapper that delegate the task to ExternalBreakEngine + * </p> + */ +class BreakEngineWrapper : public LanguageBreakEngine { + public: + + BreakEngineWrapper(ExternalBreakEngine* engine, UErrorCode &status); + + virtual ~BreakEngineWrapper(); + + virtual UBool handles(UChar32 c, const char* locale) const override; + + virtual int32_t findBreaks( UText *text, + int32_t startPos, + int32_t endPos, + UVector32 &foundBreaks, + UBool isPhraseBreaking, + UErrorCode &status) const override; + + private: + LocalPointer<ExternalBreakEngine> delegate; +}; + +/******************************************************************* * LanguageBreakFactory */ @@ -125,9 +157,10 @@ class LanguageBreakFactory : public UMemory { * * @param c A character that begins a run for which a LanguageBreakEngine is * sought. + * @param locale The locale. * @return A LanguageBreakEngine with the desired characteristics, or 0. */ - virtual const LanguageBreakEngine *getEngineFor(UChar32 c) = 0; + virtual const LanguageBreakEngine *getEngineFor(UChar32 c, const char* locale) = 0; }; @@ -174,10 +207,11 @@ class UnhandledEngine : public LanguageBreakEngine { * a particular kind of break.</p> * * @param c A character which begins a run that the engine might handle + * @param locale The locale. * @return true if this engine handles the particular character and break * type. */ - virtual UBool handles(UChar32 c) const override; + virtual UBool handles(UChar32 c, const char* locale) const override; /** * <p>Find any breaks within a run in the supplied text.</p> @@ -247,9 +281,18 @@ class ICULanguageBreakFactory : public LanguageBreakFactory { * * @param c A character that begins a run for which a LanguageBreakEngine is * sought. + * @param locale The locale. * @return A LanguageBreakEngine with the desired characteristics, or 0. */ - virtual const LanguageBreakEngine *getEngineFor(UChar32 c) override; + virtual const LanguageBreakEngine *getEngineFor(UChar32 c, const char* locale) override; + + /** + * Add and adopt the engine and return an URegistryKey. + * @param engine The ExternalBreakEngine to be added and adopt. The caller + * pass the ownership and should not release the memory after this. + * @param status the error code. + */ + virtual void addExternalEngine(ExternalBreakEngine* engine, UErrorCode& status); protected: /** @@ -258,9 +301,10 @@ protected: * * @param c A character that begins a run for which a LanguageBreakEngine is * sought. + * @param locale The locale. * @return A LanguageBreakEngine with the desired characteristics, or 0. */ - virtual const LanguageBreakEngine *loadEngineFor(UChar32 c); + virtual const LanguageBreakEngine *loadEngineFor(UChar32 c, const char* locale); /** * <p>Create a DictionaryMatcher for the specified script and break type.</p> @@ -269,6 +313,9 @@ protected: * @return A DictionaryMatcher with the desired characteristics, or nullptr. */ virtual DictionaryMatcher *loadDictionaryMatcherFor(UScriptCode script); + + private: + void ensureEngines(UErrorCode& status); }; U_NAMESPACE_END diff --git a/thirdparty/icu4c/common/brkiter.cpp b/thirdparty/icu4c/common/brkiter.cpp index 41e4e0dff5..b452cf2c05 100644 --- a/thirdparty/icu4c/common/brkiter.cpp +++ b/thirdparty/icu4c/common/brkiter.cpp @@ -27,6 +27,7 @@ #include "unicode/rbbi.h" #include "unicode/brkiter.h" #include "unicode/udata.h" +#include "unicode/uloc.h" #include "unicode/ures.h" #include "unicode/ustring.h" #include "unicode/filteredbrk.h" @@ -121,8 +122,11 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st // If there is a result, set the valid locale and actual locale, and the kind if (U_SUCCESS(status) && result != nullptr) { U_LOCALE_BASED(locBased, *(BreakIterator*)result); + locBased.setLocaleIDs(ures_getLocaleByType(b, ULOC_VALID_LOCALE, &status), actualLocale.data()); + uprv_strncpy(result->requestLocale, loc.getName(), ULOC_FULLNAME_CAPACITY); + result->requestLocale[ULOC_FULLNAME_CAPACITY-1] = 0; // always terminate } ures_close(b); @@ -202,18 +206,20 @@ BreakIterator::getAvailableLocales(int32_t& count) BreakIterator::BreakIterator() { - *validLocale = *actualLocale = 0; + *validLocale = *actualLocale = *requestLocale = 0; } BreakIterator::BreakIterator(const BreakIterator &other) : UObject(other) { uprv_strncpy(actualLocale, other.actualLocale, sizeof(actualLocale)); uprv_strncpy(validLocale, other.validLocale, sizeof(validLocale)); + uprv_strncpy(requestLocale, other.requestLocale, sizeof(requestLocale)); } BreakIterator &BreakIterator::operator =(const BreakIterator &other) { if (this != &other) { uprv_strncpy(actualLocale, other.actualLocale, sizeof(actualLocale)); uprv_strncpy(validLocale, other.validLocale, sizeof(validLocale)); + uprv_strncpy(requestLocale, other.requestLocale, sizeof(requestLocale)); } return *this; } @@ -493,12 +499,18 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) Locale BreakIterator::getLocale(ULocDataLocaleType type, UErrorCode& status) const { + if (type == ULOC_REQUESTED_LOCALE) { + return Locale(requestLocale); + } U_LOCALE_BASED(locBased, *this); return locBased.getLocale(type, status); } const char * BreakIterator::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { + if (type == ULOC_REQUESTED_LOCALE) { + return requestLocale; + } U_LOCALE_BASED(locBased, *this); return locBased.getLocaleID(type, status); } diff --git a/thirdparty/icu4c/common/characterproperties.cpp b/thirdparty/icu4c/common/characterproperties.cpp index 978e6761ce..f1e15b488d 100644 --- a/thirdparty/icu4c/common/characterproperties.cpp +++ b/thirdparty/icu4c/common/characterproperties.cpp @@ -169,7 +169,7 @@ void U_CALLCONV initInclusion(UPropertySource src, UErrorCode &errorCode) { case UPROPS_SRC_INPC: case UPROPS_SRC_INSC: case UPROPS_SRC_VO: - uprops_addPropertyStarts((UPropertySource)src, &sa, &errorCode); + uprops_addPropertyStarts(src, &sa, &errorCode); break; case UPROPS_SRC_EMOJI: { const icu::EmojiProps *ep = icu::EmojiProps::getSingleton(errorCode); @@ -178,6 +178,14 @@ void U_CALLCONV initInclusion(UPropertySource src, UErrorCode &errorCode) { } break; } + case UPROPS_SRC_IDSU: + // New in Unicode 15.1 for just two characters. + sa.add(sa.set, 0x2FFE); + sa.add(sa.set, 0x2FFF + 1); + break; + case UPROPS_SRC_ID_COMPAT_MATH: + uprops_addPropertyStarts(src, &sa, &errorCode); + break; default: errorCode = U_INTERNAL_PROGRAM_ERROR; break; diff --git a/thirdparty/icu4c/common/dictbe.cpp b/thirdparty/icu4c/common/dictbe.cpp index 0e420c67c5..3d672c03bf 100644 --- a/thirdparty/icu4c/common/dictbe.cpp +++ b/thirdparty/icu4c/common/dictbe.cpp @@ -42,7 +42,7 @@ DictionaryBreakEngine::~DictionaryBreakEngine() { } UBool -DictionaryBreakEngine::handles(UChar32 c) const { +DictionaryBreakEngine::handles(UChar32 c, const char*) const { return fSet.contains(c); } @@ -54,13 +54,13 @@ DictionaryBreakEngine::findBreaks( UText *text, UBool isPhraseBreaking, UErrorCode& status) const { if (U_FAILURE(status)) return 0; - (void)startPos; // TODO: remove this param? int32_t result = 0; // Find the span of characters included in the set. // The span to break begins at the current position in the text, and // extends towards the start or end of the text, depending on 'reverse'. + utext_setNativeIndex(text, startPos); int32_t start = (int32_t)utext_getNativeIndex(text); int32_t current; int32_t rangeStart; diff --git a/thirdparty/icu4c/common/dictbe.h b/thirdparty/icu4c/common/dictbe.h index a2c761bdc3..e512071fa4 100644 --- a/thirdparty/icu4c/common/dictbe.h +++ b/thirdparty/icu4c/common/dictbe.h @@ -62,10 +62,11 @@ class DictionaryBreakEngine : public LanguageBreakEngine { * a particular kind of break.</p> * * @param c A character which begins a run that the engine might handle + * @param locale The locale. * @return true if this engine handles the particular character and break * type. */ - virtual UBool handles(UChar32 c) const override; + virtual UBool handles(UChar32 c, const char* locale) const override; /** * <p>Find any breaks within a run in the supplied text.</p> diff --git a/thirdparty/icu4c/common/loadednormalizer2impl.cpp b/thirdparty/icu4c/common/loadednormalizer2impl.cpp index 768564edc8..99b8f3e86c 100644 --- a/thirdparty/icu4c/common/loadednormalizer2impl.cpp +++ b/thirdparty/icu4c/common/loadednormalizer2impl.cpp @@ -143,6 +143,9 @@ static icu::UInitOnce nfkcInitOnce {}; static Norm2AllModes *nfkc_cfSingleton; static icu::UInitOnce nfkc_cfInitOnce {}; +static Norm2AllModes *nfkc_scfSingleton; +static icu::UInitOnce nfkc_scfInitOnce {}; + static UHashtable *cache=nullptr; // UInitOnce singleton initialization function @@ -156,6 +159,8 @@ static void U_CALLCONV initSingletons(const char *what, UErrorCode &errorCode) { nfkcSingleton = Norm2AllModes::createInstance(nullptr, "nfkc", errorCode); } else if (uprv_strcmp(what, "nfkc_cf") == 0) { nfkc_cfSingleton = Norm2AllModes::createInstance(nullptr, "nfkc_cf", errorCode); + } else if (uprv_strcmp(what, "nfkc_scf") == 0) { + nfkc_scfSingleton = Norm2AllModes::createInstance(nullptr, "nfkc_scf", errorCode); } else { UPRV_UNREACHABLE_EXIT; // Unknown singleton } @@ -183,6 +188,10 @@ static UBool U_CALLCONV uprv_loaded_normalizer2_cleanup() { nfkc_cfSingleton = nullptr; nfkc_cfInitOnce.reset(); + delete nfkc_scfSingleton; + nfkc_scfSingleton = nullptr; + nfkc_scfInitOnce.reset(); + uhash_close(cache); cache=nullptr; return true; @@ -213,6 +222,13 @@ Norm2AllModes::getNFKC_CFInstance(UErrorCode &errorCode) { return nfkc_cfSingleton; } +const Norm2AllModes * +Norm2AllModes::getNFKC_SCFInstance(UErrorCode &errorCode) { + if(U_FAILURE(errorCode)) { return nullptr; } + umtx_initOnce(nfkc_scfInitOnce, &initSingletons, "nfkc_scf", errorCode); + return nfkc_scfSingleton; +} + #if !NORM2_HARDCODE_NFC_DATA const Normalizer2 * Normalizer2::getNFCInstance(UErrorCode &errorCode) { @@ -262,6 +278,12 @@ Normalizer2::getNFKCCasefoldInstance(UErrorCode &errorCode) { } const Normalizer2 * +Normalizer2::getNFKCSimpleCasefoldInstance(UErrorCode &errorCode) { + const Norm2AllModes *allModes=Norm2AllModes::getNFKC_SCFInstance(errorCode); + return allModes!=nullptr ? &allModes->comp : nullptr; +} + +const Normalizer2 * Normalizer2::getInstance(const char *packageName, const char *name, UNormalization2Mode mode, @@ -281,6 +303,8 @@ Normalizer2::getInstance(const char *packageName, allModes=Norm2AllModes::getNFKCInstance(errorCode); } else if(0==uprv_strcmp(name, "nfkc_cf")) { allModes=Norm2AllModes::getNFKC_CFInstance(errorCode); + } else if(0==uprv_strcmp(name, "nfkc_scf")) { + allModes=Norm2AllModes::getNFKC_SCFInstance(errorCode); } } if(allModes==nullptr && U_SUCCESS(errorCode)) { @@ -394,6 +418,11 @@ unorm2_getNFKCCasefoldInstance(UErrorCode *pErrorCode) { } U_CAPI const UNormalizer2 * U_EXPORT2 +unorm2_getNFKCSimpleCasefoldInstance(UErrorCode *pErrorCode) { + return (const UNormalizer2 *)Normalizer2::getNFKCSimpleCasefoldInstance(*pErrorCode); +} + +U_CAPI const UNormalizer2 * U_EXPORT2 unorm2_getInstance(const char *packageName, const char *name, UNormalization2Mode mode, diff --git a/thirdparty/icu4c/common/localefallback_data.h b/thirdparty/icu4c/common/localefallback_data.h index d2eb7eaafd..c847edefff 100644 --- a/thirdparty/icu4c/common/localefallback_data.h +++ b/thirdparty/icu4c/common/localefallback_data.h @@ -18,94 +18,93 @@ const char scriptCodeChars[] = "Kana\0Kawi\0Khar\0Khmr\0Kits\0Knda\0Kore\0Lana\0Laoo\0Lepc\0Lina\0" "Linb\0Lisu\0Lyci\0Lydi\0Mand\0Mani\0Marc\0Medf\0Merc\0Mlym\0Modi\0" "Mong\0Mroo\0Mtei\0Mymr\0Narb\0Newa\0Nkoo\0Nshu\0Ogam\0Olck\0Orkh\0" - "Orya\0Osge\0Ougr\0Pauc\0Phli\0Phnx\0Plrd\0Prti\0Rjng\0Rohg\0Runr\0" - "Samr\0Sarb\0Saur\0Sgnw\0Sinh\0Sogd\0Sora\0Soyo\0Syrc\0Tagb\0Takr\0" - "Tale\0Talu\0Taml\0Tang\0Tavt\0Telu\0Tfng\0Thaa\0Thai\0Tibt\0Tnsa\0" - "Toto\0Ugar\0Vaii\0Wcho\0Xpeo\0Xsux\0Yiii\0"; + "Orya\0Osge\0Pauc\0Phli\0Phnx\0Plrd\0Prti\0Rjng\0Rohg\0Runr\0Samr\0" + "Sarb\0Saur\0Sgnw\0Sinh\0Sogd\0Sora\0Soyo\0Syrc\0Tagb\0Takr\0Tale\0" + "Talu\0Taml\0Tang\0Tavt\0Telu\0Tfng\0Thaa\0Thai\0Tibt\0Tnsa\0Toto\0" + "Ugar\0Vaii\0Wcho\0Xpeo\0Xsux\0Yiii\0"; const char dsLocaleIDChars[] = - "aaf\0aao\0aat\0ab\0abh\0abl\0abq\0abv\0acm\0acq\0acw\0acx\0adf\0" - "adp\0adx\0ady\0ae\0aeb\0aec\0aee\0aeq\0afb\0agi\0agj\0agx\0ahg\0" - "aho\0ahr\0aib\0aij\0ain\0aio\0aiq\0ajp\0ajt\0akk\0akv\0alk\0all\0" - "alr\0alt\0alw\0am\0ams\0amw\0ani\0anp\0anr\0anu\0aot\0apc\0apd\0" - "aph\0aqc\0ar\0arc\0arq\0ars\0ary\0arz\0as\0ase\0ask\0atn\0atv\0" - "auj\0auz\0av\0avd\0avl\0awa\0awn\0axm\0ayh\0ayl\0ayn\0ayp\0az_IQ\0" - "az_IR\0az_RU\0azb\0ba\0bal\0bap\0bax\0bbl\0bcq\0bdv\0bdz\0be\0" - "bee\0bej\0bfb\0bfq\0bft\0bfu\0bfw\0bfy\0bfz\0bg\0bgc\0bgd\0bgn\0" - "bgp\0bgq\0bgw\0bgx\0bha\0bhb\0bhd\0bhe\0bhh\0bhi\0bhj\0bhm\0bhn\0" - "bho\0bht\0bhu\0biy\0bjf\0bji\0bjj\0bjm\0blk\0blt\0bmj\0bn\0bns\0" - "bo\0bph\0bpx\0bpy\0bqi\0bra\0brb\0brd\0brh\0brk\0brv\0brx\0bsh\0" - "bsk\0bsq\0bst\0btd\0btm\0btv\0bua\0bwe\0bxm\0bxu\0byh\0byn\0byw\0" - "bzi\0cbn\0ccp\0cde\0cdh\0cdi\0cdj\0cdm\0cdo\0cdz\0ce\0cgk\0chg\0" - "chm\0chr\0chx\0cih\0cja\0cji\0cjm\0cjy\0ckb\0ckt\0clh\0clw\0cmg\0" - "cna\0cnp\0cog\0cop\0cpg\0cr\0crh\0crj\0crk\0crl\0crm\0csh\0csp\0" - "csw\0ctd\0ctg\0ctn\0ctt\0cu\0cuu\0cv\0czh\0czk\0daq\0dar\0dcc\0" - "ddo\0def\0deh\0der\0dgl\0dhi\0dhn\0dho\0dhw\0dka\0dlg\0dmf\0dmk\0" - "dml\0dng\0dnu\0dnv\0doi\0dox\0dre\0drh\0drq\0drs\0dry\0dso\0dty\0" - "dub\0duh\0dus\0dv\0dwk\0dwz\0dz\0dzl\0ecr\0ecy\0egy\0eky\0el\0" - "emg\0emu\0enf\0enh\0era\0esg\0esh\0ett\0eve\0evn\0fa\0fay\0faz\0" - "fia\0fmu\0fub\0gan\0gaq\0gas\0gau\0gbj\0gbk\0gbl\0gbm\0gbz\0gdb\0" - "gdo\0gdx\0gez\0ggg\0ggn\0gha\0ghe\0ghr\0ght\0gig\0gin\0gjk\0gju\0" - "gld\0glh\0glk\0gmv\0gmy\0goe\0gof\0gok\0gom\0gon\0got\0gra\0grc\0" - "grt\0gru\0gu\0gvr\0gwc\0gwf\0gwt\0gyo\0gzi\0ha_CM\0ha_SD\0hac\0" - "hak\0har\0haz\0hbo\0hdy\0he\0hi\0hii\0hit\0hkh\0hlb\0hlu\0hmd\0" - "hmj\0hmq\0hnd\0hne\0hnj\0hnj_AU\0hnj_CN\0hnj_FR\0hnj_GF\0hnj_LA\0" - "hnj_MM\0hnj_SR\0hnj_TH\0hnj_US\0hnj_VN\0hno\0hoc\0hoh\0hoj\0how\0" - "hoy\0hpo\0hrt\0hrz\0hsn\0hss\0htx\0hut\0huy\0huz\0hy\0hyw\0ii\0" - "imy\0inh\0int\0ior\0iru\0isk\0itk\0itl\0iu\0iw\0ja\0jad\0jat\0" - "jbe\0jbn\0jct\0jda\0jdg\0jdt\0jee\0jge\0ji\0jje\0jkm\0jml\0jna\0" - "jnd\0jnl\0jns\0jog\0jpa\0jpr\0jul\0jun\0juy\0jya\0jye\0ka\0kaa\0" - "kap\0kaw\0kbd\0kbu\0kby\0kca\0kdq\0kdt\0ket\0kex\0key\0kfa\0kfb\0" - "kfc\0kfd\0kfe\0kfh\0kfi\0kfk\0kfm\0kfp\0kfq\0kfr\0kfs\0kfx\0kfy\0" - "kgj\0kgy\0khb\0khf\0khg\0khn\0kht\0khv\0khw\0kif\0kim\0kip\0kjg\0" - "kjh\0kjl\0kjo\0kjp\0kjt\0kk\0kk_AF\0kk_CN\0kk_IR\0kk_MN\0kkf\0" - "kkh\0kkt\0kle\0klj\0klr\0km\0kmj\0kmz\0kn\0ko\0koi\0kok\0kpt\0" - "kpy\0kqd\0kqy\0kra\0krc\0krk\0krr\0kru\0krv\0ks\0ksu\0ksw\0ksz\0" - "ktb\0ktl\0ktp\0ku_LB\0kuf\0kum\0kv\0kva\0kvq\0kvt\0kvx\0kvy\0" - "kxc\0kxf\0kxk\0kxl\0kxm\0kxp\0kxv\0ky\0ky_CN\0kyu\0kyv\0kyw\0" - "kzh\0lab\0lad\0lae\0lah\0lbc\0lbe\0lbf\0lbj\0lbm\0lbo\0lbr\0lcp\0" - "lep\0lez\0lhm\0lhs\0lif\0lis\0lkh\0lki\0lmh\0lmn\0lo\0loy\0lpo\0" - "lrc\0lrk\0lrl\0lsa\0lsd\0lss\0luk\0luu\0luv\0luz\0lwl\0lwm\0lya\0" - "lzh\0mag\0mai\0man_GN\0mby\0mde\0mdf\0mdx\0mdy\0mfa\0mfi\0mgp\0" - "mhj\0mid\0mjl\0mjq\0mjr\0mjt\0mju\0mjv\0mjz\0mk\0mkb\0mke\0mki\0" - "mkm\0ml\0mlf\0mn\0mn_CN\0mni\0mnj\0mns\0mnw\0mpz\0mr\0mra\0mrd\0" - "mrj\0mro\0mrr\0ms_CC\0mtm\0mtr\0mud\0muk\0mut\0muv\0muz\0mvf\0" - "mvy\0mvz\0mwr\0mwt\0mww\0my\0mym\0myv\0myz\0mzn\0nan\0nao\0ncd\0" - "ncq\0ndf\0ne\0neg\0neh\0nei\0new\0ngt\0nio\0nit\0niv\0nli\0nlm\0" - "nlx\0nmm\0nnp\0nod\0noe\0nog\0noi\0non\0nos\0npb\0nqo\0nsd\0nsf\0" - "nsk\0nst\0nsv\0nty\0ntz\0nwc\0nwx\0nyl\0nyq\0oaa\0oac\0oar\0oav\0" - "obm\0obr\0odk\0oht\0oj\0ojs\0okm\0oko\0okz\0ola\0ole\0omk\0omp\0" - "omr\0oon\0or\0ort\0oru\0orv\0os\0osa\0osc\0osi\0ota\0otb\0otk\0" - "oty\0oui\0pa\0pa_PK\0pal\0paq\0pbt\0pcb\0pce\0pcf\0pcg\0pch\0" - "pci\0pcj\0peg\0peo\0pgd\0pgg\0pgl\0pgn\0phd\0phk\0phl\0phn\0pho\0" - "phr\0pht\0phv\0phw\0pi\0pka\0pkr\0plk\0pll\0pmh\0pnt\0ppa\0pra\0" + "aaf\0aao\0aat\0ab\0abh\0abl\0abv\0acm\0acq\0acw\0acx\0adf\0adx\0" + "ady\0ae\0aeb\0aec\0aee\0aeq\0afb\0agi\0agj\0agx\0ahg\0aho\0ahr\0" + "aib\0aij\0ain\0aio\0aiq\0ajp\0akk\0akv\0alk\0all\0alr\0alt\0alw\0" + "am\0ams\0amw\0ani\0anp\0anr\0anu\0aot\0apc\0apd\0aph\0aqc\0ar\0" + "arc\0arq\0ars\0ary\0arz\0as\0ase\0ask\0atn\0atv\0auj\0auz\0av\0" + "avd\0avl\0awa\0awn\0axm\0ayh\0ayl\0ayn\0ayp\0az_IQ\0az_IR\0az_RU\0" + "azb\0ba\0bal\0bap\0bax\0bbl\0bcq\0bdv\0bdz\0be\0bee\0bej\0bfb\0" + "bfq\0bft\0bfu\0bfw\0bfy\0bfz\0bg\0bgc\0bgd\0bgn\0bgp\0bgq\0bgw\0" + "bgx\0bha\0bhb\0bhd\0bhe\0bhh\0bhi\0bhj\0bhm\0bhn\0bho\0bht\0bhu\0" + "biy\0bjf\0bjj\0bjm\0blk\0blt\0bmj\0bn\0bns\0bo\0bph\0bpx\0bpy\0" + "bqi\0bra\0brb\0brd\0brh\0brk\0brv\0brx\0bsh\0bsk\0bsq\0bst\0btd\0" + "btm\0btv\0bua\0bwe\0bxm\0bxu\0byh\0byn\0byw\0bzi\0cbn\0ccp\0cde\0" + "cdh\0cdi\0cdj\0cdm\0cdo\0cdz\0ce\0cgk\0chg\0chm\0chr\0chx\0cih\0" + "cja\0cji\0cjm\0cjy\0ckb\0ckt\0clh\0clw\0cmg\0cna\0cnp\0cog\0cop\0" + "cpg\0cr\0crh\0crj\0crk\0crl\0crm\0csh\0csp\0csw\0ctd\0ctg\0ctn\0" + "ctt\0cu\0cuu\0cv\0czh\0czk\0daq\0dar\0dcc\0ddo\0def\0deh\0der\0" + "dhi\0dhn\0dho\0dhw\0dka\0dlg\0dmf\0dmk\0dml\0dng\0dnu\0dnv\0doi\0" + "dox\0dre\0drq\0drs\0dry\0dso\0dty\0dub\0duh\0dus\0dv\0dwk\0dwz\0" + "dz\0dzl\0ecr\0ecy\0egy\0eky\0el\0emg\0emu\0enf\0enh\0era\0esg\0" + "esh\0ett\0eve\0evn\0fa\0fay\0faz\0fia\0fmu\0fub\0gan\0gaq\0gas\0" + "gau\0gbj\0gbk\0gbl\0gbm\0gbz\0gdb\0gdo\0gdx\0gez\0ggg\0gha\0ghe\0" + "ghr\0ght\0gig\0gin\0gjk\0gju\0gld\0glh\0glk\0gmv\0gmy\0goe\0gof\0" + "gok\0gom\0gon\0got\0gra\0grc\0grt\0gru\0gu\0gvr\0gwc\0gwf\0gwt\0" + "gyo\0gzi\0ha_CM\0ha_SD\0hac\0hak\0har\0haz\0hbo\0hdy\0he\0hi\0" + "hii\0hit\0hkh\0hlb\0hlu\0hmd\0hmj\0hmq\0hnd\0hne\0hnj\0hnj_AU\0" + "hnj_CN\0hnj_FR\0hnj_GF\0hnj_LA\0hnj_MM\0hnj_SR\0hnj_TH\0hnj_VN\0" + "hno\0hoc\0hoh\0hoj\0how\0hoy\0hpo\0hrt\0hrz\0hsn\0hss\0htx\0hut\0" + "huy\0huz\0hy\0hyw\0ii\0imy\0inh\0int\0ior\0iru\0isk\0itk\0itl\0" + "iu\0iw\0ja\0jad\0jat\0jbe\0jbn\0jct\0jda\0jdg\0jdt\0jee\0jge\0" + "ji\0jje\0jkm\0jml\0jna\0jnd\0jnl\0jns\0jog\0jpa\0jpr\0jrb\0jrb_MA\0" + "jul\0jun\0juy\0jya\0jye\0ka\0kaa\0kap\0kaw\0kbd\0kbu\0kby\0kca\0" + "kdq\0kdt\0ket\0kex\0key\0kfa\0kfb\0kfc\0kfd\0kfe\0kfh\0kfi\0kfk\0" + "kfm\0kfp\0kfq\0kfr\0kfs\0kfx\0kfy\0kgj\0kgy\0khb\0khf\0khg\0khn\0" + "kht\0khv\0khw\0kif\0kim\0kip\0kjg\0kjh\0kjl\0kjo\0kjp\0kjt\0kk\0" + "kk_AF\0kk_CN\0kk_IR\0kk_MN\0kkf\0kkh\0kkt\0kle\0klj\0klr\0km\0" + "kmj\0kmz\0kn\0ko\0koi\0kok\0kpt\0kpy\0kqd\0kqy\0kra\0krc\0krk\0" + "krr\0kru\0krv\0ks\0ksu\0ksw\0ksz\0ktb\0ktl\0ktp\0ku_LB\0kuf\0" + "kum\0kv\0kva\0kvq\0kvt\0kvx\0kvy\0kxf\0kxk\0kxm\0kxp\0ky\0ky_CN\0" + "kyu\0kyv\0kyw\0lab\0lad\0lae\0lah\0lbc\0lbe\0lbf\0lbj\0lbm\0lbo\0" + "lbr\0lcp\0lep\0lez\0lhm\0lhs\0lif\0lis\0lkh\0lki\0lmh\0lmn\0lo\0" + "loy\0lpo\0lrc\0lrk\0lrl\0lsa\0lsd\0lss\0luk\0luu\0luv\0luz\0lwl\0" + "lwm\0lya\0lzh\0mag\0mai\0man_GN\0mby\0mde\0mdf\0mdx\0mdy\0mfa\0" + "mfi\0mgp\0mhj\0mid\0mjl\0mjq\0mjr\0mjt\0mju\0mjv\0mjz\0mk\0mkb\0" + "mke\0mki\0mkm\0ml\0mlf\0mn\0mn_CN\0mni\0mnj\0mns\0mnw\0mpz\0mr\0" + "mra\0mrd\0mrj\0mro\0mrr\0ms_CC\0mtm\0mtr\0mud\0muk\0mut\0muv\0" + "muz\0mvf\0mvy\0mvz\0mwr\0mwt\0mww\0my\0mym\0myv\0myz\0mzn\0nan\0" + "nao\0ncd\0ncq\0ndf\0ne\0neg\0neh\0nei\0new\0ngt\0nio\0nit\0niv\0" + "nli\0nlm\0nlx\0nmm\0nnp\0nod\0noe\0nog\0noi\0non\0nos\0npb\0nqo\0" + "nsd\0nsf\0nsk\0nst\0nsv\0nty\0ntz\0nwc\0nwx\0nyl\0nyq\0oaa\0oac\0" + "oar\0oav\0obm\0obr\0odk\0oht\0oj\0ojs\0okm\0oko\0okz\0ola\0ole\0" + "omk\0omp\0omr\0oon\0or\0ort\0oru\0orv\0os\0osa\0osc\0osi\0ota\0" + "otb\0otk\0oty\0pa\0pa_PK\0pal\0paq\0pbt\0pcb\0pce\0pcf\0pcg\0" + "pch\0pci\0pcj\0peg\0peo\0pgd\0pgg\0pgl\0pgn\0phd\0phk\0phl\0phn\0" + "pho\0phr\0pht\0phv\0phw\0pi\0pka\0pkr\0plk\0pll\0pmh\0pnt\0pra\0" "prc\0prd\0prp\0prt\0prx\0ps\0psh\0psi\0pst\0pum\0pwo\0pwr\0pww\0" "pyx\0qxq\0raa\0rab\0raf\0rah\0raj\0rav\0rbb\0rdb\0rei\0rhg\0rji\0" - "rjs\0rka\0rki\0rkt\0rmi\0rmt\0rmz\0rsk\0rtw\0ru\0rue\0rut\0rwr\0" - "ryu\0sa\0sah\0sam\0sat\0saz\0sbn\0sbu\0sck\0scl\0scp\0sct\0scu\0" - "scx\0sd\0sd_IN\0sdb\0sdf\0sdg\0sdh\0sds\0sel\0sfm\0sga\0sgh\0" - "sgj\0sgr\0sgt\0sgw\0sgy\0shd\0shi\0shm\0shn\0shu\0shv\0si\0sia\0" - "sip\0siy\0siz\0sjd\0sjp\0sjt\0skb\0skj\0skr\0slq\0smh\0smp\0smu\0" - "smy\0soa\0sog\0soi\0sou\0spt\0spv\0sqo\0sqq\0sqt\0sr\0srb\0srh\0" - "srx\0srz\0ssh\0sss\0sts\0stv\0sty\0suz\0sva\0swb\0swi\0swv\0syc\0" - "syl\0syn\0syr\0syw\0ta\0tab\0taj\0tbk\0tcn\0tco\0tcx\0tcy\0tda\0" - "tdb\0tdd\0tdg\0tdh\0te\0tes\0tg\0tg_PK\0tge\0tgf\0th\0the\0thf\0" - "thi\0thl\0thm\0thq\0thr\0ths\0ti\0tig\0tij\0tin\0tjl\0tjo\0tkb\0" - "tks\0tkt\0tmk\0tmr\0tnv\0tov\0tpu\0tra\0trg\0trm\0trw\0tsd\0tsf\0" - "tsj\0tt\0tth\0tto\0tts\0tvn\0twm\0txg\0txo\0tyr\0tyv\0ude\0udg\0" - "udi\0udm\0ug\0ug_KZ\0ug_MN\0uga\0ugh\0ugo\0uk\0uki\0ulc\0unr\0" - "unr_NP\0unx\0ur\0urk\0ush\0uum\0uz_AF\0uz_CN\0uzs\0vaa\0vaf\0" - "vah\0vai\0vas\0vav\0vay\0vgr\0vmd\0vmh\0wal\0wbk\0wbq\0wbr\0wlo\0" - "wme\0wne\0wni\0wsg\0wsv\0wtm\0wuu\0xal\0xan\0xas\0xco\0xcr\0xdq\0" - "xhe\0xhm\0xis\0xka\0xkc\0xkj\0xkp\0xlc\0xld\0xly\0xmf\0xmn\0xmr\0" - "xna\0xnr\0xpg\0xpi\0xpm\0xpr\0xrm\0xrn\0xsa\0xsr\0xss\0xub\0xuj\0" - "xve\0xvi\0xwo\0xzh\0yai\0ybh\0ybi\0ydg\0yea\0yej\0yeu\0ygp\0yhd\0" - "yi\0yig\0yih\0yiv\0ykg\0yna\0ynk\0yoi\0yoy\0yrk\0ysd\0ysn\0ysp\0" - "ysr\0ysy\0yud\0yue\0yue_CN\0yug\0yux\0ywq\0ywu\0zau\0zba\0zch\0" - "zdj\0zeh\0zen\0zgb\0zgh\0zgm\0zgn\0zh\0zh_AU\0zh_BN\0zh_GB\0zh_GF\0" - "zh_HK\0zh_ID\0zh_MO\0zh_PA\0zh_PF\0zh_PH\0zh_SR\0zh_TH\0zh_TW\0" - "zh_US\0zh_VN\0zhd\0zhx\0zkb\0zko\0zkt\0zkz\0zlj\0zln\0zlq\0zqe\0" - "zrp\0zum\0zyg\0zyn\0zzj\0"; + "rjs\0rka\0rki\0rkt\0rmi\0rmt\0rmz\0rom_BG\0rsk\0rtw\0ru\0rue\0" + "rut\0rwr\0ryu\0sa\0sah\0sam\0sat\0saz\0sbn\0sbu\0sck\0scl\0scl_IN\0" + "scp\0sct\0scu\0scx\0sd\0sd_IN\0sdb\0sdf\0sdg\0sdh\0sds\0sel\0" + "sfm\0sga\0sgh\0sgj\0sgr\0sgt\0sgw\0sgy\0shd\0shi\0shm\0shn\0shu\0" + "shv\0si\0sia\0sip\0siy\0siz\0sjd\0sjp\0sjt\0skb\0skj\0skr\0slq\0" + "smh\0smp\0smu\0smy\0soa\0sog\0soi\0sou\0spt\0spv\0sqo\0sqq\0sqt\0" + "sr\0srb\0srh\0srx\0srz\0ssh\0sss\0sts\0stv\0sty\0suz\0sva\0swb\0" + "swi\0swv\0syc\0syl\0syn\0syr\0syw\0ta\0tab\0taj\0tbk\0tcn\0tco\0" + "tcx\0tcy\0tda\0tdb\0tdd\0tdg\0tdh\0te\0tes\0tg\0tg_PK\0tge\0tgf\0" + "th\0the\0thf\0thi\0thl\0thm\0thq\0thr\0ths\0ti\0tig\0tij\0tin\0" + "tjl\0tjo\0tkb\0tks\0tkt\0tmk\0tmr\0tnv\0tov\0tpu\0tra\0trg\0trm\0" + "trw\0tsd\0tsj\0tt\0tth\0tto\0tts\0tvn\0twm\0txg\0txo\0tyr\0tyv\0" + "ude\0udg\0udi\0udm\0ug\0ug_KZ\0ug_MN\0uga\0ugh\0ugo\0uk\0uki\0" + "ulc\0unr\0unr_NP\0unx\0ur\0urk\0ush\0uum\0uz_AF\0uz_CN\0uzs\0" + "vaa\0vaf\0vah\0vai\0vas\0vav\0vay\0vgr\0vmd\0vmh\0wal\0wbk\0wbq\0" + "wbr\0wlo\0wme\0wne\0wni\0wsg\0wsv\0wtm\0wuu\0xal\0xan\0xas\0xco\0" + "xcr\0xdq\0xhe\0xhm\0xis\0xka\0xkc\0xkj\0xkp\0xlc\0xld\0xly\0xmf\0" + "xmn\0xmr\0xna\0xnr\0xpg\0xpi\0xpm\0xpr\0xrm\0xrn\0xsa\0xsr\0xss\0" + "xub\0xuj\0xve\0xvi\0xwo\0xzh\0yai\0ybh\0ybi\0ydg\0yea\0yej\0yeu\0" + "ygp\0yhd\0yi\0yig\0yih\0yiv\0ykg\0yna\0ynk\0yoi\0yoy\0yrk\0ysd\0" + "ysn\0ysp\0ysr\0ysy\0yud\0yue\0yue_CN\0yug\0yux\0ywq\0ywu\0zau\0" + "zba\0zch\0zdj\0zeh\0zen\0zgb\0zgh\0zgm\0zgn\0zh\0zh_AU\0zh_BN\0" + "zh_GB\0zh_GF\0zh_HK\0zh_ID\0zh_MO\0zh_PA\0zh_PF\0zh_PH\0zh_SR\0" + "zh_TH\0zh_TW\0zh_US\0zh_VN\0zhd\0zhx\0zkb\0zko\0zkt\0zkz\0zlj\0" + "zln\0zlq\0zqe\0zrp\0zum\0zyg\0zyn\0zzj\0"; const int32_t defaultScriptTable[] = { 0, 320, // aaf -> Mlym @@ -113,1033 +112,1022 @@ const int32_t defaultScriptTable[] = { 8, 150, // aat -> Grek 12, 100, // ab -> Cyrl 15, 10, // abh -> Arab - 19, 425, // abl -> Rjng - 23, 100, // abq -> Cyrl - 27, 10, // abv -> Arab - 31, 10, // acm -> Arab - 35, 10, // acq -> Arab - 39, 10, // acw -> Arab - 43, 10, // acx -> Arab - 47, 10, // adf -> Arab - 51, 540, // adp -> Tibt - 55, 540, // adx -> Tibt - 59, 100, // ady -> Cyrl - 63, 25, // ae -> Avst - 66, 10, // aeb -> Arab - 70, 10, // aec -> Arab - 74, 10, // aee -> Arab - 78, 10, // aeq -> Arab - 82, 10, // afb -> Arab - 86, 105, // agi -> Deva - 90, 120, // agj -> Ethi - 94, 100, // agx -> Cyrl - 98, 120, // ahg -> Ethi - 102, 5, // aho -> Ahom - 106, 105, // ahr -> Deva - 110, 10, // aib -> Arab - 114, 185, // aij -> Hebr - 118, 220, // ain -> Kana - 122, 345, // aio -> Mymr - 126, 10, // aiq -> Arab - 130, 10, // ajp -> Arab - 134, 10, // ajt -> Arab - 138, 575, // akk -> Xsux - 142, 100, // akv -> Cyrl - 146, 260, // alk -> Laoo - 150, 320, // all -> Mlym - 154, 100, // alr -> Cyrl - 158, 100, // alt -> Cyrl - 162, 120, // alw -> Ethi - 166, 120, // am -> Ethi - 169, 210, // ams -> Jpan - 173, 480, // amw -> Syrc - 177, 100, // ani -> Cyrl - 181, 105, // anp -> Deva - 185, 105, // anr -> Deva - 189, 120, // anu -> Ethi - 193, 45, // aot -> Beng - 197, 10, // apc -> Arab - 201, 10, // apd -> Arab - 205, 105, // aph -> Deva - 209, 100, // aqc -> Cyrl - 213, 10, // ar -> Arab - 216, 15, // arc -> Armi - 220, 10, // arq -> Arab - 224, 10, // ars -> Arab - 228, 10, // ary -> Arab - 232, 10, // arz -> Arab - 236, 45, // as -> Beng - 239, 455, // ase -> Sgnw - 243, 10, // ask -> Arab - 247, 10, // atn -> Arab - 251, 100, // atv -> Cyrl - 255, 10, // auj -> Arab - 259, 10, // auz -> Arab - 263, 100, // av -> Cyrl - 266, 10, // avd -> Arab - 270, 10, // avl -> Arab - 274, 105, // awa -> Deva - 278, 120, // awn -> Ethi - 282, 20, // axm -> Armn - 286, 10, // ayh -> Arab - 290, 10, // ayl -> Arab - 294, 10, // ayn -> Arab - 298, 10, // ayp -> Arab - 302, 10, // az_IQ -> Arab - 308, 10, // az_IR -> Arab - 314, 100, // az_RU -> Cyrl - 320, 10, // azb -> Arab - 324, 100, // ba -> Cyrl - 327, 10, // bal -> Arab - 331, 105, // bap -> Deva - 335, 30, // bax -> Bamu - 339, 125, // bbl -> Geor - 343, 120, // bcq -> Ethi - 347, 385, // bdv -> Orya - 351, 10, // bdz -> Arab - 355, 100, // be -> Cyrl - 358, 105, // bee -> Deva - 362, 10, // bej -> Arab - 366, 105, // bfb -> Deva - 370, 505, // bfq -> Taml - 374, 10, // bft -> Arab - 378, 540, // bfu -> Tibt - 382, 385, // bfw -> Orya - 386, 105, // bfy -> Deva - 390, 105, // bfz -> Deva - 394, 100, // bg -> Cyrl - 397, 105, // bgc -> Deva - 401, 105, // bgd -> Deva - 405, 10, // bgn -> Arab - 409, 10, // bgp -> Arab - 413, 105, // bgq -> Deva - 417, 105, // bgw -> Deva - 421, 150, // bgx -> Grek - 425, 105, // bha -> Deva - 429, 105, // bhb -> Deva - 433, 105, // bhd -> Deva - 437, 10, // bhe -> Arab - 441, 100, // bhh -> Cyrl - 445, 105, // bhi -> Deva - 449, 105, // bhj -> Deva - 453, 10, // bhm -> Arab - 457, 480, // bhn -> Syrc - 461, 105, // bho -> Deva - 465, 490, // bht -> Takr - 469, 105, // bhu -> Deva - 473, 105, // biy -> Deva - 477, 480, // bjf -> Syrc - 481, 120, // bji -> Ethi - 485, 105, // bjj -> Deva - 489, 10, // bjm -> Arab - 493, 345, // blk -> Mymr - 497, 515, // blt -> Tavt - 501, 105, // bmj -> Deva - 505, 45, // bn -> Beng - 508, 105, // bns -> Deva - 512, 540, // bo -> Tibt - 515, 100, // bph -> Cyrl - 519, 105, // bpx -> Deva - 523, 45, // bpy -> Beng - 527, 10, // bqi -> Arab - 531, 105, // bra -> Deva - 535, 235, // brb -> Khmr - 539, 105, // brd -> Deva - 543, 10, // brh -> Arab - 547, 10, // brk -> Arab - 551, 260, // brv -> Laoo - 555, 105, // brx -> Deva - 559, 10, // bsh -> Arab - 563, 10, // bsk -> Arab - 567, 35, // bsq -> Bass - 571, 120, // bst -> Ethi - 575, 40, // btd -> Batk - 579, 40, // btm -> Batk - 583, 105, // btv -> Deva - 587, 100, // bua -> Cyrl - 591, 345, // bwe -> Mymr - 595, 100, // bxm -> Cyrl - 599, 330, // bxu -> Mong - 603, 105, // byh -> Deva - 607, 120, // byn -> Ethi - 611, 105, // byw -> Deva - 615, 535, // bzi -> Thai - 619, 535, // cbn -> Thai - 623, 60, // ccp -> Cakm - 627, 520, // cde -> Telu - 631, 105, // cdh -> Deva - 635, 155, // cdi -> Gujr - 639, 105, // cdj -> Deva - 643, 105, // cdm -> Deva - 647, 175, // cdo -> Hans - 651, 45, // cdz -> Beng - 655, 100, // ce -> Cyrl - 658, 540, // cgk -> Tibt - 662, 10, // chg -> Arab - 666, 100, // chm -> Cyrl - 670, 80, // chr -> Cher - 674, 105, // chx -> Deva - 678, 105, // cih -> Deva - 682, 10, // cja -> Arab - 686, 100, // cji -> Cyrl - 690, 75, // cjm -> Cham - 694, 175, // cjy -> Hans - 698, 10, // ckb -> Arab - 702, 100, // ckt -> Cyrl - 706, 10, // clh -> Arab - 710, 100, // clw -> Cyrl - 714, 475, // cmg -> Soyo - 718, 540, // cna -> Tibt - 722, 175, // cnp -> Hans - 726, 535, // cog -> Thai - 730, 90, // cop -> Copt - 734, 150, // cpg -> Grek - 738, 65, // cr -> Cans - 741, 100, // crh -> Cyrl - 745, 65, // crj -> Cans - 749, 65, // crk -> Cans - 753, 65, // crl -> Cans - 757, 65, // crm -> Cans - 761, 345, // csh -> Mymr - 765, 175, // csp -> Hans - 769, 65, // csw -> Cans - 773, 400, // ctd -> Pauc - 777, 45, // ctg -> Beng - 781, 105, // ctn -> Deva - 785, 505, // ctt -> Taml - 789, 100, // cu -> Cyrl - 792, 255, // cuu -> Lana - 796, 100, // cv -> Cyrl - 799, 175, // czh -> Hans - 803, 185, // czk -> Hebr - 807, 105, // daq -> Deva - 811, 100, // dar -> Cyrl - 815, 10, // dcc -> Arab - 819, 100, // ddo -> Cyrl - 823, 10, // def -> Arab - 827, 10, // deh -> Arab - 831, 45, // der -> Beng - 835, 10, // dgl -> Arab - 839, 105, // dhi -> Deva - 843, 155, // dhn -> Gujr - 847, 105, // dho -> Deva - 851, 105, // dhw -> Deva - 855, 540, // dka -> Tibt - 859, 100, // dlg -> Cyrl - 863, 310, // dmf -> Medf - 867, 10, // dmk -> Arab - 871, 10, // dml -> Arab - 875, 100, // dng -> Cyrl - 879, 345, // dnu -> Mymr - 883, 345, // dnv -> Mymr - 887, 105, // doi -> Deva - 891, 120, // dox -> Ethi - 895, 540, // dre -> Tibt - 899, 330, // drh -> Mong - 903, 105, // drq -> Deva - 907, 120, // drs -> Ethi - 911, 105, // dry -> Deva - 915, 385, // dso -> Orya - 919, 105, // dty -> Deva - 923, 155, // dub -> Gujr - 927, 105, // duh -> Deva - 931, 105, // dus -> Deva - 935, 530, // dv -> Thaa - 938, 385, // dwk -> Orya - 942, 105, // dwz -> Deva - 946, 540, // dz -> Tibt - 949, 540, // dzl -> Tibt - 953, 150, // ecr -> Grek - 957, 95, // ecy -> Cprt - 961, 110, // egy -> Egyp - 965, 215, // eky -> Kali - 969, 150, // el -> Grek - 972, 105, // emg -> Deva - 976, 105, // emu -> Deva - 980, 100, // enf -> Cyrl - 984, 100, // enh -> Cyrl - 988, 505, // era -> Taml - 992, 135, // esg -> Gonm - 996, 10, // esh -> Arab - 1000, 200, // ett -> Ital - 1004, 100, // eve -> Cyrl - 1008, 100, // evn -> Cyrl - 1012, 10, // fa -> Arab - 1015, 10, // fay -> Arab - 1019, 10, // faz -> Arab - 1023, 10, // fia -> Arab - 1027, 105, // fmu -> Deva - 1031, 10, // fub -> Arab - 1035, 175, // gan -> Hans - 1039, 385, // gaq -> Orya - 1043, 155, // gas -> Gujr - 1047, 520, // gau -> Telu - 1051, 385, // gbj -> Orya - 1055, 105, // gbk -> Deva - 1059, 155, // gbl -> Gujr - 1063, 105, // gbm -> Deva - 1067, 10, // gbz -> Arab - 1071, 385, // gdb -> Orya - 1075, 100, // gdo -> Cyrl - 1079, 105, // gdx -> Deva - 1083, 120, // gez -> Ethi - 1087, 10, // ggg -> Arab - 1091, 105, // ggn -> Deva - 1095, 10, // gha -> Arab - 1099, 105, // ghe -> Deva - 1103, 10, // ghr -> Arab - 1107, 540, // ght -> Tibt - 1111, 10, // gig -> Arab - 1115, 100, // gin -> Cyrl - 1119, 10, // gjk -> Arab - 1123, 10, // gju -> Arab - 1127, 100, // gld -> Cyrl - 1131, 10, // glh -> Arab - 1135, 10, // glk -> Arab - 1139, 120, // gmv -> Ethi - 1143, 275, // gmy -> Linb - 1147, 540, // goe -> Tibt - 1151, 120, // gof -> Ethi - 1155, 105, // gok -> Deva - 1159, 105, // gom -> Deva - 1163, 520, // gon -> Telu - 1167, 140, // got -> Goth - 1171, 105, // gra -> Deva - 1175, 95, // grc -> Cprt - 1179, 45, // grt -> Beng - 1183, 120, // gru -> Ethi - 1187, 155, // gu -> Gujr - 1190, 105, // gvr -> Deva - 1194, 10, // gwc -> Arab - 1198, 10, // gwf -> Arab - 1202, 10, // gwt -> Arab - 1206, 105, // gyo -> Deva - 1210, 10, // gzi -> Arab - 1214, 10, // ha_CM -> Arab - 1220, 10, // ha_SD -> Arab - 1226, 10, // hac -> Arab - 1230, 175, // hak -> Hans - 1234, 120, // har -> Ethi - 1238, 10, // haz -> Arab - 1242, 185, // hbo -> Hebr - 1246, 120, // hdy -> Ethi - 1250, 185, // he -> Hebr - 1253, 105, // hi -> Deva - 1256, 490, // hii -> Takr - 1260, 575, // hit -> Xsux - 1264, 10, // hkh -> Arab - 1268, 105, // hlb -> Deva - 1272, 190, // hlu -> Hluw - 1276, 415, // hmd -> Plrd - 1280, 50, // hmj -> Bopo - 1284, 50, // hmq -> Bopo - 1288, 10, // hnd -> Arab - 1292, 105, // hne -> Deva - 1296, 195, // hnj -> Hmnp - 1300, 260, // hnj_AU -> Laoo - 1307, 260, // hnj_CN -> Laoo - 1314, 260, // hnj_FR -> Laoo - 1321, 260, // hnj_GF -> Laoo - 1328, 260, // hnj_LA -> Laoo - 1335, 260, // hnj_MM -> Laoo - 1342, 260, // hnj_SR -> Laoo - 1349, 260, // hnj_TH -> Laoo - 1356, 195, // hnj_US -> Hmnp - 1363, 260, // hnj_VN -> Laoo - 1370, 10, // hno -> Arab - 1374, 105, // hoc -> Deva - 1378, 10, // hoh -> Arab - 1382, 105, // hoj -> Deva - 1386, 170, // how -> Hani - 1390, 105, // hoy -> Deva - 1394, 345, // hpo -> Mymr - 1398, 480, // hrt -> Syrc - 1402, 10, // hrz -> Arab - 1406, 175, // hsn -> Hans - 1410, 10, // hss -> Arab - 1414, 575, // htx -> Xsux - 1418, 105, // hut -> Deva - 1422, 185, // huy -> Hebr - 1426, 100, // huz -> Cyrl - 1430, 20, // hy -> Armn - 1433, 20, // hyw -> Armn - 1437, 580, // ii -> Yiii - 1440, 285, // imy -> Lyci - 1444, 100, // inh -> Cyrl - 1448, 345, // int -> Mymr - 1452, 120, // ior -> Ethi - 1456, 505, // iru -> Taml - 1460, 10, // isk -> Arab - 1464, 185, // itk -> Hebr - 1468, 100, // itl -> Cyrl - 1472, 65, // iu -> Cans - 1475, 185, // iw -> Hebr - 1478, 210, // ja -> Jpan - 1481, 10, // jad -> Arab - 1485, 10, // jat -> Arab - 1489, 185, // jbe -> Hebr - 1493, 10, // jbn -> Arab - 1497, 100, // jct -> Cyrl - 1501, 540, // jda -> Tibt - 1505, 10, // jdg -> Arab - 1509, 100, // jdt -> Cyrl - 1513, 105, // jee -> Deva - 1517, 125, // jge -> Geor - 1521, 185, // ji -> Hebr - 1524, 165, // jje -> Hang - 1528, 345, // jkm -> Mymr - 1532, 105, // jml -> Deva - 1536, 490, // jna -> Takr - 1540, 10, // jnd -> Arab - 1544, 105, // jnl -> Deva - 1548, 105, // jns -> Deva - 1552, 10, // jog -> Arab - 1556, 185, // jpa -> Hebr - 1560, 185, // jpr -> Hebr - 1564, 105, // jul -> Deva - 1568, 385, // jun -> Orya - 1572, 385, // juy -> Orya - 1576, 540, // jya -> Tibt - 1580, 185, // jye -> Hebr - 1584, 125, // ka -> Geor - 1587, 100, // kaa -> Cyrl - 1591, 100, // kap -> Cyrl - 1595, 225, // kaw -> Kawi - 1599, 100, // kbd -> Cyrl - 1603, 10, // kbu -> Arab - 1607, 10, // kby -> Arab - 1611, 100, // kca -> Cyrl - 1615, 45, // kdq -> Beng - 1619, 535, // kdt -> Thai - 1623, 100, // ket -> Cyrl - 1627, 105, // kex -> Deva - 1631, 520, // key -> Telu - 1635, 245, // kfa -> Knda - 1639, 105, // kfb -> Deva - 1643, 520, // kfc -> Telu - 1647, 245, // kfd -> Knda - 1651, 505, // kfe -> Taml - 1655, 320, // kfh -> Mlym - 1659, 505, // kfi -> Taml - 1663, 105, // kfk -> Deva - 1667, 10, // kfm -> Arab - 1671, 105, // kfp -> Deva - 1675, 105, // kfq -> Deva - 1679, 105, // kfr -> Deva - 1683, 105, // kfs -> Deva - 1687, 105, // kfx -> Deva - 1691, 105, // kfy -> Deva - 1695, 105, // kgj -> Deva - 1699, 105, // kgy -> Deva - 1703, 500, // khb -> Talu - 1707, 535, // khf -> Thai - 1711, 540, // khg -> Tibt - 1715, 105, // khn -> Deva - 1719, 345, // kht -> Mymr - 1723, 100, // khv -> Cyrl - 1727, 10, // khw -> Arab - 1731, 105, // kif -> Deva - 1735, 100, // kim -> Cyrl - 1739, 105, // kip -> Deva - 1743, 260, // kjg -> Laoo - 1747, 100, // kjh -> Cyrl - 1751, 105, // kjl -> Deva - 1755, 105, // kjo -> Deva - 1759, 345, // kjp -> Mymr - 1763, 535, // kjt -> Thai - 1767, 100, // kk -> Cyrl - 1770, 10, // kk_AF -> Arab - 1776, 10, // kk_CN -> Arab - 1782, 10, // kk_IR -> Arab - 1788, 10, // kk_MN -> Arab - 1794, 540, // kkf -> Tibt - 1798, 255, // kkh -> Lana - 1802, 105, // kkt -> Deva - 1806, 105, // kle -> Deva - 1810, 10, // klj -> Arab - 1814, 105, // klr -> Deva - 1818, 235, // km -> Khmr - 1821, 105, // kmj -> Deva - 1825, 10, // kmz -> Arab - 1829, 245, // kn -> Knda - 1832, 250, // ko -> Kore - 1835, 100, // koi -> Cyrl - 1839, 105, // kok -> Deva - 1843, 100, // kpt -> Cyrl - 1847, 100, // kpy -> Cyrl - 1851, 480, // kqd -> Syrc - 1855, 120, // kqy -> Ethi - 1859, 105, // kra -> Deva - 1863, 100, // krc -> Cyrl - 1867, 100, // krk -> Cyrl - 1871, 235, // krr -> Khmr - 1875, 105, // kru -> Deva - 1879, 235, // krv -> Khmr - 1883, 10, // ks -> Arab - 1886, 345, // ksu -> Mymr - 1890, 345, // ksw -> Mymr - 1894, 105, // ksz -> Deva - 1898, 120, // ktb -> Ethi - 1902, 10, // ktl -> Arab - 1906, 415, // ktp -> Plrd - 1910, 10, // ku_LB -> Arab - 1916, 260, // kuf -> Laoo - 1920, 100, // kum -> Cyrl - 1924, 100, // kv -> Cyrl - 1927, 100, // kva -> Cyrl - 1931, 345, // kvq -> Mymr - 1935, 345, // kvt -> Mymr - 1939, 10, // kvx -> Arab - 1943, 215, // kvy -> Kali - 1947, 120, // kxc -> Ethi - 1951, 345, // kxf -> Mymr - 1955, 345, // kxk -> Mymr - 1959, 105, // kxl -> Deva - 1963, 535, // kxm -> Thai - 1967, 10, // kxp -> Arab - 1971, 385, // kxv -> Orya - 1975, 100, // ky -> Cyrl - 1978, 10, // ky_CN -> Arab - 1984, 215, // kyu -> Kali - 1988, 105, // kyv -> Deva - 1992, 105, // kyw -> Deva - 1996, 10, // kzh -> Arab - 2000, 270, // lab -> Lina - 2004, 185, // lad -> Hebr - 2008, 105, // lae -> Deva - 2012, 10, // lah -> Arab - 2016, 280, // lbc -> Lisu - 2020, 100, // lbe -> Cyrl - 2024, 105, // lbf -> Deva - 2028, 540, // lbj -> Tibt - 2032, 105, // lbm -> Deva - 2036, 260, // lbo -> Laoo - 2040, 105, // lbr -> Deva - 2044, 535, // lcp -> Thai - 2048, 265, // lep -> Lepc - 2052, 100, // lez -> Cyrl - 2056, 105, // lhm -> Deva - 2060, 480, // lhs -> Syrc - 2064, 105, // lif -> Deva - 2068, 280, // lis -> Lisu - 2072, 540, // lkh -> Tibt - 2076, 10, // lki -> Arab - 2080, 105, // lmh -> Deva - 2084, 520, // lmn -> Telu - 2088, 260, // lo -> Laoo - 2091, 105, // loy -> Deva - 2095, 415, // lpo -> Plrd - 2099, 10, // lrc -> Arab - 2103, 10, // lrk -> Arab - 2107, 10, // lrl -> Arab - 2111, 10, // lsa -> Arab - 2115, 185, // lsd -> Hebr - 2119, 10, // lss -> Arab - 2123, 540, // luk -> Tibt - 2127, 105, // luu -> Deva - 2131, 10, // luv -> Arab - 2135, 10, // luz -> Arab - 2139, 535, // lwl -> Thai - 2143, 535, // lwm -> Thai - 2147, 540, // lya -> Tibt - 2151, 175, // lzh -> Hans - 2155, 105, // mag -> Deva - 2159, 105, // mai -> Deva - 2163, 360, // man_GN -> Nkoo - 2170, 10, // mby -> Arab - 2174, 10, // mde -> Arab - 2178, 100, // mdf -> Cyrl - 2182, 120, // mdx -> Ethi - 2186, 120, // mdy -> Ethi - 2190, 10, // mfa -> Arab - 2194, 10, // mfi -> Arab - 2198, 105, // mgp -> Deva - 2202, 10, // mhj -> Arab - 2206, 295, // mid -> Mand - 2210, 105, // mjl -> Deva - 2214, 320, // mjq -> Mlym - 2218, 320, // mjr -> Mlym - 2222, 105, // mjt -> Deva - 2226, 520, // mju -> Telu - 2230, 320, // mjv -> Mlym - 2234, 105, // mjz -> Deva - 2238, 100, // mk -> Cyrl - 2241, 105, // mkb -> Deva - 2245, 105, // mke -> Deva - 2249, 10, // mki -> Arab - 2253, 535, // mkm -> Thai - 2257, 320, // ml -> Mlym - 2260, 535, // mlf -> Thai - 2264, 100, // mn -> Cyrl - 2267, 330, // mn_CN -> Mong - 2273, 45, // mni -> Beng - 2277, 10, // mnj -> Arab - 2281, 100, // mns -> Cyrl - 2285, 345, // mnw -> Mymr - 2289, 535, // mpz -> Thai - 2293, 105, // mr -> Deva - 2296, 535, // mra -> Thai - 2300, 105, // mrd -> Deva - 2304, 100, // mrj -> Cyrl - 2308, 335, // mro -> Mroo - 2312, 105, // mrr -> Deva - 2316, 10, // ms_CC -> Arab - 2322, 100, // mtm -> Cyrl - 2326, 105, // mtr -> Deva - 2330, 100, // mud -> Cyrl - 2334, 540, // muk -> Tibt - 2338, 105, // mut -> Deva - 2342, 505, // muv -> Taml - 2346, 120, // muz -> Ethi - 2350, 330, // mvf -> Mong - 2354, 10, // mvy -> Arab - 2358, 120, // mvz -> Ethi - 2362, 105, // mwr -> Deva - 2366, 345, // mwt -> Mymr - 2370, 195, // mww -> Hmnp - 2374, 345, // my -> Mymr - 2377, 120, // mym -> Ethi - 2381, 100, // myv -> Cyrl - 2385, 295, // myz -> Mand - 2389, 10, // mzn -> Arab - 2393, 175, // nan -> Hans - 2397, 105, // nao -> Deva - 2401, 105, // ncd -> Deva - 2405, 260, // ncq -> Laoo - 2409, 100, // ndf -> Cyrl - 2413, 105, // ne -> Deva - 2416, 100, // neg -> Cyrl - 2420, 540, // neh -> Tibt - 2424, 575, // nei -> Xsux - 2428, 105, // new -> Deva - 2432, 260, // ngt -> Laoo - 2436, 100, // nio -> Cyrl - 2440, 520, // nit -> Telu - 2444, 100, // niv -> Cyrl - 2448, 10, // nli -> Arab - 2452, 10, // nlm -> Arab - 2456, 105, // nlx -> Deva - 2460, 105, // nmm -> Deva - 2464, 565, // nnp -> Wcho - 2468, 255, // nod -> Lana - 2472, 105, // noe -> Deva - 2476, 100, // nog -> Cyrl - 2480, 105, // noi -> Deva - 2484, 435, // non -> Runr - 2488, 580, // nos -> Yiii - 2492, 540, // npb -> Tibt - 2496, 360, // nqo -> Nkoo - 2500, 580, // nsd -> Yiii - 2504, 580, // nsf -> Yiii - 2508, 65, // nsk -> Cans - 2512, 545, // nst -> Tnsa - 2516, 580, // nsv -> Yiii - 2520, 580, // nty -> Yiii - 2524, 10, // ntz -> Arab - 2528, 355, // nwc -> Newa - 2532, 105, // nwx -> Deva - 2536, 535, // nyl -> Thai - 2540, 10, // nyq -> Arab - 2544, 100, // oaa -> Cyrl - 2548, 100, // oac -> Cyrl - 2552, 480, // oar -> Syrc - 2556, 125, // oav -> Geor - 2560, 410, // obm -> Phnx - 2564, 345, // obr -> Mymr - 2568, 10, // odk -> Arab - 2572, 575, // oht -> Xsux - 2576, 65, // oj -> Cans - 2579, 65, // ojs -> Cans - 2583, 165, // okm -> Hang - 2587, 170, // oko -> Hani - 2591, 235, // okz -> Khmr - 2595, 105, // ola -> Deva - 2599, 540, // ole -> Tibt - 2603, 100, // omk -> Cyrl - 2607, 340, // omp -> Mtei - 2611, 325, // omr -> Modi - 2615, 105, // oon -> Deva - 2619, 385, // or -> Orya - 2622, 520, // ort -> Telu - 2626, 10, // oru -> Arab - 2630, 100, // orv -> Cyrl - 2634, 100, // os -> Cyrl - 2637, 390, // osa -> Osge - 2641, 200, // osc -> Ital - 2645, 205, // osi -> Java - 2649, 10, // ota -> Arab - 2653, 540, // otb -> Tibt - 2657, 380, // otk -> Orkh - 2661, 145, // oty -> Gran - 2665, 395, // oui -> Ougr - 2669, 160, // pa -> Guru - 2672, 10, // pa_PK -> Arab - 2678, 405, // pal -> Phli - 2682, 100, // paq -> Cyrl - 2686, 10, // pbt -> Arab - 2690, 235, // pcb -> Khmr - 2694, 345, // pce -> Mymr - 2698, 320, // pcf -> Mlym - 2702, 320, // pcg -> Mlym - 2706, 105, // pch -> Deva - 2710, 105, // pci -> Deva - 2714, 520, // pcj -> Telu - 2718, 385, // peg -> Orya - 2722, 570, // peo -> Xpeo - 2726, 230, // pgd -> Khar - 2730, 105, // pgg -> Deva - 2734, 370, // pgl -> Ogam - 2738, 200, // pgn -> Ital - 2742, 105, // phd -> Deva - 2746, 345, // phk -> Mymr - 2750, 10, // phl -> Arab - 2754, 410, // phn -> Phnx - 2758, 260, // pho -> Laoo - 2762, 10, // phr -> Arab - 2766, 535, // pht -> Thai - 2770, 10, // phv -> Arab - 2774, 105, // phw -> Deva - 2778, 460, // pi -> Sinh - 2781, 55, // pka -> Brah - 2785, 320, // pkr -> Mlym - 2789, 10, // plk -> Arab - 2793, 345, // pll -> Mymr - 2797, 55, // pmh -> Brah - 2801, 150, // pnt -> Grek - 2805, 105, // ppa -> Deva - 2809, 230, // pra -> Khar - 2813, 10, // prc -> Arab - 2817, 10, // prd -> Arab - 2821, 155, // prp -> Gujr - 2825, 535, // prt -> Thai - 2829, 10, // prx -> Arab - 2833, 10, // ps -> Arab - 2836, 10, // psh -> Arab - 2840, 10, // psi -> Arab - 2844, 10, // pst -> Arab - 2848, 105, // pum -> Deva - 2852, 345, // pwo -> Mymr - 2856, 105, // pwr -> Deva - 2860, 535, // pww -> Thai - 2864, 345, // pyx -> Mymr - 2868, 10, // qxq -> Arab - 2872, 105, // raa -> Deva - 2876, 105, // rab -> Deva - 2880, 105, // raf -> Deva - 2884, 45, // rah -> Beng - 2888, 105, // raj -> Deva - 2892, 105, // rav -> Deva - 2896, 345, // rbb -> Mymr - 2900, 10, // rdb -> Arab - 2904, 385, // rei -> Orya - 2908, 430, // rhg -> Rohg - 2912, 105, // rji -> Deva - 2916, 105, // rjs -> Deva - 2920, 235, // rka -> Khmr - 2924, 345, // rki -> Mymr - 2928, 45, // rkt -> Beng - 2932, 20, // rmi -> Armn - 2936, 10, // rmt -> Arab - 2940, 345, // rmz -> Mymr - 2944, 100, // rsk -> Cyrl - 2948, 105, // rtw -> Deva - 2952, 100, // ru -> Cyrl - 2955, 100, // rue -> Cyrl - 2959, 100, // rut -> Cyrl - 2963, 105, // rwr -> Deva - 2967, 220, // ryu -> Kana - 2971, 105, // sa -> Deva - 2974, 100, // sah -> Cyrl - 2978, 440, // sam -> Samr - 2982, 375, // sat -> Olck - 2986, 450, // saz -> Saur - 2990, 10, // sbn -> Arab - 2994, 540, // sbu -> Tibt - 2998, 105, // sck -> Deva - 3002, 10, // scl -> Arab - 3006, 105, // scp -> Deva - 3010, 260, // sct -> Laoo - 3014, 490, // scu -> Takr - 3018, 150, // scx -> Grek - 3022, 10, // sd -> Arab - 3025, 105, // sd_IN -> Deva - 3031, 10, // sdb -> Arab - 3035, 10, // sdf -> Arab - 3039, 10, // sdg -> Arab - 3043, 10, // sdh -> Arab - 3047, 10, // sds -> Arab - 3051, 100, // sel -> Cyrl - 3055, 415, // sfm -> Plrd - 3059, 370, // sga -> Ogam - 3063, 100, // sgh -> Cyrl - 3067, 105, // sgj -> Deva - 3071, 10, // sgr -> Arab - 3075, 540, // sgt -> Tibt - 3079, 120, // sgw -> Ethi - 3083, 10, // sgy -> Arab - 3087, 10, // shd -> Arab - 3091, 525, // shi -> Tfng - 3095, 10, // shm -> Arab - 3099, 345, // shn -> Mymr - 3103, 10, // shu -> Arab - 3107, 10, // shv -> Arab - 3111, 460, // si -> Sinh - 3114, 100, // sia -> Cyrl - 3118, 540, // sip -> Tibt - 3122, 10, // siy -> Arab - 3126, 10, // siz -> Arab - 3130, 100, // sjd -> Cyrl - 3134, 105, // sjp -> Deva - 3138, 100, // sjt -> Cyrl - 3142, 535, // skb -> Thai - 3146, 105, // skj -> Deva - 3150, 10, // skr -> Arab - 3154, 10, // slq -> Arab - 3158, 580, // smh -> Yiii - 3162, 440, // smp -> Samr - 3166, 235, // smu -> Khmr - 3170, 10, // smy -> Arab - 3174, 515, // soa -> Tavt - 3178, 465, // sog -> Sogd - 3182, 105, // soi -> Deva - 3186, 535, // sou -> Thai - 3190, 540, // spt -> Tibt - 3194, 385, // spv -> Orya - 3198, 10, // sqo -> Arab - 3202, 260, // sqq -> Laoo - 3206, 10, // sqt -> Arab - 3210, 100, // sr -> Cyrl - 3213, 470, // srb -> Sora - 3217, 10, // srh -> Arab - 3221, 105, // srx -> Deva - 3225, 10, // srz -> Arab - 3229, 10, // ssh -> Arab - 3233, 260, // sss -> Laoo - 3237, 10, // sts -> Arab - 3241, 120, // stv -> Ethi - 3245, 100, // sty -> Cyrl - 3249, 105, // suz -> Deva - 3253, 125, // sva -> Geor - 3257, 10, // swb -> Arab - 3261, 170, // swi -> Hani - 3265, 105, // swv -> Deva - 3269, 480, // syc -> Syrc - 3273, 45, // syl -> Beng - 3277, 480, // syn -> Syrc - 3281, 480, // syr -> Syrc - 3285, 105, // syw -> Deva - 3289, 505, // ta -> Taml - 3292, 100, // tab -> Cyrl - 3296, 105, // taj -> Deva - 3300, 485, // tbk -> Tagb - 3304, 540, // tcn -> Tibt - 3308, 345, // tco -> Mymr - 3312, 505, // tcx -> Taml - 3316, 245, // tcy -> Knda - 3320, 525, // tda -> Tfng - 3324, 105, // tdb -> Deva - 3328, 495, // tdd -> Tale - 3332, 105, // tdg -> Deva - 3336, 105, // tdh -> Deva - 3340, 520, // te -> Telu - 3343, 205, // tes -> Java - 3347, 100, // tg -> Cyrl - 3350, 10, // tg_PK -> Arab - 3356, 105, // tge -> Deva - 3360, 540, // tgf -> Tibt - 3364, 535, // th -> Thai - 3367, 105, // the -> Deva - 3371, 105, // thf -> Deva - 3375, 495, // thi -> Tale - 3379, 105, // thl -> Deva - 3383, 535, // thm -> Thai - 3387, 105, // thq -> Deva - 3391, 105, // thr -> Deva - 3395, 105, // ths -> Deva - 3399, 120, // ti -> Ethi - 3402, 120, // tig -> Ethi - 3406, 105, // tij -> Deva - 3410, 100, // tin -> Cyrl - 3414, 345, // tjl -> Mymr - 3418, 10, // tjo -> Arab - 3422, 105, // tkb -> Deva - 3426, 10, // tks -> Arab - 3430, 105, // tkt -> Deva - 3434, 105, // tmk -> Deva - 3438, 480, // tmr -> Syrc - 3442, 60, // tnv -> Cakm - 3446, 10, // tov -> Arab - 3450, 235, // tpu -> Khmr - 3454, 10, // tra -> Arab - 3458, 185, // trg -> Hebr - 3462, 10, // trm -> Arab - 3466, 10, // trw -> Arab - 3470, 150, // tsd -> Grek - 3474, 105, // tsf -> Deva - 3478, 540, // tsj -> Tibt - 3482, 100, // tt -> Cyrl - 3485, 260, // tth -> Laoo - 3489, 260, // tto -> Laoo - 3493, 535, // tts -> Thai - 3497, 345, // tvn -> Mymr - 3501, 105, // twm -> Deva - 3505, 510, // txg -> Tang - 3509, 550, // txo -> Toto - 3513, 515, // tyr -> Tavt - 3517, 100, // tyv -> Cyrl - 3521, 100, // ude -> Cyrl - 3525, 320, // udg -> Mlym - 3529, 0, // udi -> Aghb - 3533, 100, // udm -> Cyrl - 3537, 10, // ug -> Arab - 3540, 100, // ug_KZ -> Cyrl - 3546, 100, // ug_MN -> Cyrl - 3552, 555, // uga -> Ugar - 3556, 100, // ugh -> Cyrl - 3560, 535, // ugo -> Thai - 3564, 100, // uk -> Cyrl - 3567, 385, // uki -> Orya - 3571, 100, // ulc -> Cyrl - 3575, 45, // unr -> Beng - 3579, 105, // unr_NP -> Deva - 3586, 45, // unx -> Beng - 3590, 10, // ur -> Arab - 3593, 535, // urk -> Thai - 3597, 10, // ush -> Arab - 3601, 150, // uum -> Grek - 3605, 10, // uz_AF -> Arab - 3611, 100, // uz_CN -> Cyrl - 3617, 10, // uzs -> Arab - 3621, 505, // vaa -> Taml - 3625, 10, // vaf -> Arab - 3629, 105, // vah -> Deva - 3633, 560, // vai -> Vaii - 3637, 105, // vas -> Deva - 3641, 105, // vav -> Deva - 3645, 105, // vay -> Deva - 3649, 10, // vgr -> Arab - 3653, 245, // vmd -> Knda - 3657, 10, // vmh -> Arab - 3661, 120, // wal -> Ethi - 3665, 10, // wbk -> Arab - 3669, 520, // wbq -> Telu - 3673, 105, // wbr -> Deva - 3677, 10, // wlo -> Arab - 3681, 105, // wme -> Deva - 3685, 10, // wne -> Arab - 3689, 10, // wni -> Arab - 3693, 130, // wsg -> Gong - 3697, 10, // wsv -> Arab - 3701, 105, // wtm -> Deva - 3705, 175, // wuu -> Hans - 3709, 100, // xal -> Cyrl - 3713, 120, // xan -> Ethi - 3717, 100, // xas -> Cyrl - 3721, 85, // xco -> Chrs - 3725, 70, // xcr -> Cari - 3729, 100, // xdq -> Cyrl - 3733, 10, // xhe -> Arab - 3737, 235, // xhm -> Khmr - 3741, 385, // xis -> Orya - 3745, 10, // xka -> Arab - 3749, 10, // xkc -> Arab - 3753, 10, // xkj -> Arab - 3757, 10, // xkp -> Arab - 3761, 285, // xlc -> Lyci - 3765, 290, // xld -> Lydi - 3769, 115, // xly -> Elym - 3773, 125, // xmf -> Geor - 3777, 300, // xmn -> Mani - 3781, 315, // xmr -> Merc - 3785, 350, // xna -> Narb - 3789, 105, // xnr -> Deva - 3793, 150, // xpg -> Grek - 3797, 370, // xpi -> Ogam - 3801, 100, // xpm -> Cyrl - 3805, 420, // xpr -> Prti - 3809, 100, // xrm -> Cyrl - 3813, 100, // xrn -> Cyrl - 3817, 445, // xsa -> Sarb - 3821, 105, // xsr -> Deva - 3825, 100, // xss -> Cyrl - 3829, 505, // xub -> Taml - 3833, 505, // xuj -> Taml - 3837, 200, // xve -> Ital - 3841, 10, // xvi -> Arab - 3845, 100, // xwo -> Cyrl - 3849, 305, // xzh -> Marc - 3853, 100, // yai -> Cyrl - 3857, 105, // ybh -> Deva - 3861, 105, // ybi -> Deva - 3865, 10, // ydg -> Arab - 3869, 320, // yea -> Mlym - 3873, 150, // yej -> Grek - 3877, 520, // yeu -> Telu - 3881, 415, // ygp -> Plrd - 3885, 185, // yhd -> Hebr - 3889, 185, // yi -> Hebr - 3892, 580, // yig -> Yiii - 3896, 185, // yih -> Hebr - 3900, 580, // yiv -> Yiii - 3904, 100, // ykg -> Cyrl - 3908, 415, // yna -> Plrd - 3912, 100, // ynk -> Cyrl - 3916, 210, // yoi -> Jpan - 3920, 535, // yoy -> Thai - 3924, 100, // yrk -> Cyrl - 3928, 580, // ysd -> Yiii - 3932, 580, // ysn -> Yiii - 3936, 580, // ysp -> Yiii - 3940, 100, // ysr -> Cyrl - 3944, 415, // ysy -> Plrd - 3948, 185, // yud -> Hebr - 3952, 180, // yue -> Hant - 3956, 175, // yue_CN -> Hans - 3963, 100, // yug -> Cyrl - 3967, 100, // yux -> Cyrl - 3971, 415, // ywq -> Plrd - 3975, 415, // ywu -> Plrd - 3979, 540, // zau -> Tibt - 3983, 10, // zba -> Arab - 3987, 170, // zch -> Hani - 3991, 10, // zdj -> Arab - 3995, 170, // zeh -> Hani - 3999, 525, // zen -> Tfng - 4003, 170, // zgb -> Hani - 4007, 525, // zgh -> Tfng - 4011, 170, // zgm -> Hani - 4015, 170, // zgn -> Hani - 4019, 175, // zh -> Hans - 4022, 180, // zh_AU -> Hant - 4028, 180, // zh_BN -> Hant - 4034, 180, // zh_GB -> Hant - 4040, 180, // zh_GF -> Hant - 4046, 180, // zh_HK -> Hant - 4052, 180, // zh_ID -> Hant - 4058, 180, // zh_MO -> Hant - 4064, 180, // zh_PA -> Hant - 4070, 180, // zh_PF -> Hant - 4076, 180, // zh_PH -> Hant - 4082, 180, // zh_SR -> Hant - 4088, 180, // zh_TH -> Hant - 4094, 180, // zh_TW -> Hant - 4100, 180, // zh_US -> Hant - 4106, 180, // zh_VN -> Hant - 4112, 170, // zhd -> Hani - 4116, 365, // zhx -> Nshu - 4120, 100, // zkb -> Cyrl - 4124, 100, // zko -> Cyrl - 4128, 240, // zkt -> Kits - 4132, 100, // zkz -> Cyrl - 4136, 170, // zlj -> Hani - 4140, 170, // zln -> Hani - 4144, 170, // zlq -> Hani - 4148, 170, // zqe -> Hani - 4152, 185, // zrp -> Hebr - 4156, 10, // zum -> Arab - 4160, 170, // zyg -> Hani - 4164, 170, // zyn -> Hani - 4168, 170, // zzj -> Hani + 19, 420, // abl -> Rjng + 23, 10, // abv -> Arab + 27, 10, // acm -> Arab + 31, 10, // acq -> Arab + 35, 10, // acw -> Arab + 39, 10, // acx -> Arab + 43, 10, // adf -> Arab + 47, 535, // adx -> Tibt + 51, 100, // ady -> Cyrl + 55, 25, // ae -> Avst + 58, 10, // aeb -> Arab + 62, 10, // aec -> Arab + 66, 10, // aee -> Arab + 70, 10, // aeq -> Arab + 74, 10, // afb -> Arab + 78, 105, // agi -> Deva + 82, 120, // agj -> Ethi + 86, 100, // agx -> Cyrl + 90, 120, // ahg -> Ethi + 94, 5, // aho -> Ahom + 98, 105, // ahr -> Deva + 102, 10, // aib -> Arab + 106, 185, // aij -> Hebr + 110, 220, // ain -> Kana + 114, 345, // aio -> Mymr + 118, 10, // aiq -> Arab + 122, 10, // ajp -> Arab + 126, 570, // akk -> Xsux + 130, 100, // akv -> Cyrl + 134, 260, // alk -> Laoo + 138, 320, // all -> Mlym + 142, 100, // alr -> Cyrl + 146, 100, // alt -> Cyrl + 150, 120, // alw -> Ethi + 154, 120, // am -> Ethi + 157, 210, // ams -> Jpan + 161, 475, // amw -> Syrc + 165, 100, // ani -> Cyrl + 169, 105, // anp -> Deva + 173, 105, // anr -> Deva + 177, 120, // anu -> Ethi + 181, 45, // aot -> Beng + 185, 10, // apc -> Arab + 189, 10, // apd -> Arab + 193, 105, // aph -> Deva + 197, 100, // aqc -> Cyrl + 201, 10, // ar -> Arab + 204, 15, // arc -> Armi + 208, 10, // arq -> Arab + 212, 10, // ars -> Arab + 216, 10, // ary -> Arab + 220, 10, // arz -> Arab + 224, 45, // as -> Beng + 227, 450, // ase -> Sgnw + 231, 10, // ask -> Arab + 235, 10, // atn -> Arab + 239, 100, // atv -> Cyrl + 243, 10, // auj -> Arab + 247, 10, // auz -> Arab + 251, 100, // av -> Cyrl + 254, 10, // avd -> Arab + 258, 10, // avl -> Arab + 262, 105, // awa -> Deva + 266, 120, // awn -> Ethi + 270, 20, // axm -> Armn + 274, 10, // ayh -> Arab + 278, 10, // ayl -> Arab + 282, 10, // ayn -> Arab + 286, 10, // ayp -> Arab + 290, 10, // az_IQ -> Arab + 296, 10, // az_IR -> Arab + 302, 100, // az_RU -> Cyrl + 308, 10, // azb -> Arab + 312, 100, // ba -> Cyrl + 315, 10, // bal -> Arab + 319, 105, // bap -> Deva + 323, 30, // bax -> Bamu + 327, 125, // bbl -> Geor + 331, 120, // bcq -> Ethi + 335, 385, // bdv -> Orya + 339, 10, // bdz -> Arab + 343, 100, // be -> Cyrl + 346, 105, // bee -> Deva + 350, 10, // bej -> Arab + 354, 105, // bfb -> Deva + 358, 500, // bfq -> Taml + 362, 10, // bft -> Arab + 366, 535, // bfu -> Tibt + 370, 385, // bfw -> Orya + 374, 105, // bfy -> Deva + 378, 105, // bfz -> Deva + 382, 100, // bg -> Cyrl + 385, 105, // bgc -> Deva + 389, 105, // bgd -> Deva + 393, 10, // bgn -> Arab + 397, 10, // bgp -> Arab + 401, 105, // bgq -> Deva + 405, 105, // bgw -> Deva + 409, 150, // bgx -> Grek + 413, 105, // bha -> Deva + 417, 105, // bhb -> Deva + 421, 105, // bhd -> Deva + 425, 10, // bhe -> Arab + 429, 100, // bhh -> Cyrl + 433, 105, // bhi -> Deva + 437, 105, // bhj -> Deva + 441, 10, // bhm -> Arab + 445, 475, // bhn -> Syrc + 449, 105, // bho -> Deva + 453, 485, // bht -> Takr + 457, 105, // bhu -> Deva + 461, 105, // biy -> Deva + 465, 475, // bjf -> Syrc + 469, 105, // bjj -> Deva + 473, 10, // bjm -> Arab + 477, 345, // blk -> Mymr + 481, 510, // blt -> Tavt + 485, 105, // bmj -> Deva + 489, 45, // bn -> Beng + 492, 105, // bns -> Deva + 496, 535, // bo -> Tibt + 499, 100, // bph -> Cyrl + 503, 105, // bpx -> Deva + 507, 45, // bpy -> Beng + 511, 10, // bqi -> Arab + 515, 105, // bra -> Deva + 519, 235, // brb -> Khmr + 523, 105, // brd -> Deva + 527, 10, // brh -> Arab + 531, 10, // brk -> Arab + 535, 260, // brv -> Laoo + 539, 105, // brx -> Deva + 543, 10, // bsh -> Arab + 547, 10, // bsk -> Arab + 551, 35, // bsq -> Bass + 555, 120, // bst -> Ethi + 559, 40, // btd -> Batk + 563, 40, // btm -> Batk + 567, 105, // btv -> Deva + 571, 100, // bua -> Cyrl + 575, 345, // bwe -> Mymr + 579, 100, // bxm -> Cyrl + 583, 330, // bxu -> Mong + 587, 105, // byh -> Deva + 591, 120, // byn -> Ethi + 595, 105, // byw -> Deva + 599, 530, // bzi -> Thai + 603, 530, // cbn -> Thai + 607, 60, // ccp -> Cakm + 611, 515, // cde -> Telu + 615, 105, // cdh -> Deva + 619, 155, // cdi -> Gujr + 623, 105, // cdj -> Deva + 627, 105, // cdm -> Deva + 631, 175, // cdo -> Hans + 635, 45, // cdz -> Beng + 639, 100, // ce -> Cyrl + 642, 535, // cgk -> Tibt + 646, 10, // chg -> Arab + 650, 100, // chm -> Cyrl + 654, 80, // chr -> Cher + 658, 105, // chx -> Deva + 662, 105, // cih -> Deva + 666, 10, // cja -> Arab + 670, 100, // cji -> Cyrl + 674, 75, // cjm -> Cham + 678, 175, // cjy -> Hans + 682, 10, // ckb -> Arab + 686, 100, // ckt -> Cyrl + 690, 10, // clh -> Arab + 694, 100, // clw -> Cyrl + 698, 470, // cmg -> Soyo + 702, 535, // cna -> Tibt + 706, 175, // cnp -> Hans + 710, 530, // cog -> Thai + 714, 90, // cop -> Copt + 718, 150, // cpg -> Grek + 722, 65, // cr -> Cans + 725, 100, // crh -> Cyrl + 729, 65, // crj -> Cans + 733, 65, // crk -> Cans + 737, 65, // crl -> Cans + 741, 65, // crm -> Cans + 745, 345, // csh -> Mymr + 749, 175, // csp -> Hans + 753, 65, // csw -> Cans + 757, 395, // ctd -> Pauc + 761, 45, // ctg -> Beng + 765, 105, // ctn -> Deva + 769, 500, // ctt -> Taml + 773, 100, // cu -> Cyrl + 776, 255, // cuu -> Lana + 780, 100, // cv -> Cyrl + 783, 175, // czh -> Hans + 787, 185, // czk -> Hebr + 791, 105, // daq -> Deva + 795, 100, // dar -> Cyrl + 799, 10, // dcc -> Arab + 803, 100, // ddo -> Cyrl + 807, 10, // def -> Arab + 811, 10, // deh -> Arab + 815, 45, // der -> Beng + 819, 105, // dhi -> Deva + 823, 155, // dhn -> Gujr + 827, 105, // dho -> Deva + 831, 105, // dhw -> Deva + 835, 535, // dka -> Tibt + 839, 100, // dlg -> Cyrl + 843, 310, // dmf -> Medf + 847, 10, // dmk -> Arab + 851, 10, // dml -> Arab + 855, 100, // dng -> Cyrl + 859, 345, // dnu -> Mymr + 863, 345, // dnv -> Mymr + 867, 105, // doi -> Deva + 871, 120, // dox -> Ethi + 875, 535, // dre -> Tibt + 879, 105, // drq -> Deva + 883, 120, // drs -> Ethi + 887, 105, // dry -> Deva + 891, 385, // dso -> Orya + 895, 105, // dty -> Deva + 899, 155, // dub -> Gujr + 903, 105, // duh -> Deva + 907, 105, // dus -> Deva + 911, 525, // dv -> Thaa + 914, 385, // dwk -> Orya + 918, 105, // dwz -> Deva + 922, 535, // dz -> Tibt + 925, 535, // dzl -> Tibt + 929, 150, // ecr -> Grek + 933, 95, // ecy -> Cprt + 937, 110, // egy -> Egyp + 941, 215, // eky -> Kali + 945, 150, // el -> Grek + 948, 105, // emg -> Deva + 952, 105, // emu -> Deva + 956, 100, // enf -> Cyrl + 960, 100, // enh -> Cyrl + 964, 500, // era -> Taml + 968, 135, // esg -> Gonm + 972, 10, // esh -> Arab + 976, 200, // ett -> Ital + 980, 100, // eve -> Cyrl + 984, 100, // evn -> Cyrl + 988, 10, // fa -> Arab + 991, 10, // fay -> Arab + 995, 10, // faz -> Arab + 999, 10, // fia -> Arab + 1003, 105, // fmu -> Deva + 1007, 10, // fub -> Arab + 1011, 175, // gan -> Hans + 1015, 385, // gaq -> Orya + 1019, 155, // gas -> Gujr + 1023, 515, // gau -> Telu + 1027, 385, // gbj -> Orya + 1031, 105, // gbk -> Deva + 1035, 155, // gbl -> Gujr + 1039, 105, // gbm -> Deva + 1043, 10, // gbz -> Arab + 1047, 385, // gdb -> Orya + 1051, 100, // gdo -> Cyrl + 1055, 105, // gdx -> Deva + 1059, 120, // gez -> Ethi + 1063, 10, // ggg -> Arab + 1067, 10, // gha -> Arab + 1071, 105, // ghe -> Deva + 1075, 10, // ghr -> Arab + 1079, 535, // ght -> Tibt + 1083, 10, // gig -> Arab + 1087, 100, // gin -> Cyrl + 1091, 10, // gjk -> Arab + 1095, 10, // gju -> Arab + 1099, 100, // gld -> Cyrl + 1103, 10, // glh -> Arab + 1107, 10, // glk -> Arab + 1111, 120, // gmv -> Ethi + 1115, 275, // gmy -> Linb + 1119, 535, // goe -> Tibt + 1123, 120, // gof -> Ethi + 1127, 105, // gok -> Deva + 1131, 105, // gom -> Deva + 1135, 515, // gon -> Telu + 1139, 140, // got -> Goth + 1143, 105, // gra -> Deva + 1147, 95, // grc -> Cprt + 1151, 45, // grt -> Beng + 1155, 120, // gru -> Ethi + 1159, 155, // gu -> Gujr + 1162, 105, // gvr -> Deva + 1166, 10, // gwc -> Arab + 1170, 10, // gwf -> Arab + 1174, 10, // gwt -> Arab + 1178, 105, // gyo -> Deva + 1182, 10, // gzi -> Arab + 1186, 10, // ha_CM -> Arab + 1192, 10, // ha_SD -> Arab + 1198, 10, // hac -> Arab + 1202, 175, // hak -> Hans + 1206, 120, // har -> Ethi + 1210, 10, // haz -> Arab + 1214, 185, // hbo -> Hebr + 1218, 120, // hdy -> Ethi + 1222, 185, // he -> Hebr + 1225, 105, // hi -> Deva + 1228, 485, // hii -> Takr + 1232, 570, // hit -> Xsux + 1236, 10, // hkh -> Arab + 1240, 105, // hlb -> Deva + 1244, 190, // hlu -> Hluw + 1248, 410, // hmd -> Plrd + 1252, 50, // hmj -> Bopo + 1256, 50, // hmq -> Bopo + 1260, 10, // hnd -> Arab + 1264, 105, // hne -> Deva + 1268, 195, // hnj -> Hmnp + 1272, 260, // hnj_AU -> Laoo + 1279, 260, // hnj_CN -> Laoo + 1286, 260, // hnj_FR -> Laoo + 1293, 260, // hnj_GF -> Laoo + 1300, 260, // hnj_LA -> Laoo + 1307, 260, // hnj_MM -> Laoo + 1314, 260, // hnj_SR -> Laoo + 1321, 260, // hnj_TH -> Laoo + 1328, 260, // hnj_VN -> Laoo + 1335, 10, // hno -> Arab + 1339, 105, // hoc -> Deva + 1343, 10, // hoh -> Arab + 1347, 105, // hoj -> Deva + 1351, 170, // how -> Hani + 1355, 105, // hoy -> Deva + 1359, 345, // hpo -> Mymr + 1363, 475, // hrt -> Syrc + 1367, 10, // hrz -> Arab + 1371, 175, // hsn -> Hans + 1375, 10, // hss -> Arab + 1379, 570, // htx -> Xsux + 1383, 105, // hut -> Deva + 1387, 185, // huy -> Hebr + 1391, 100, // huz -> Cyrl + 1395, 20, // hy -> Armn + 1398, 20, // hyw -> Armn + 1402, 575, // ii -> Yiii + 1405, 285, // imy -> Lyci + 1409, 100, // inh -> Cyrl + 1413, 345, // int -> Mymr + 1417, 120, // ior -> Ethi + 1421, 500, // iru -> Taml + 1425, 10, // isk -> Arab + 1429, 185, // itk -> Hebr + 1433, 100, // itl -> Cyrl + 1437, 65, // iu -> Cans + 1440, 185, // iw -> Hebr + 1443, 210, // ja -> Jpan + 1446, 10, // jad -> Arab + 1450, 10, // jat -> Arab + 1454, 185, // jbe -> Hebr + 1458, 10, // jbn -> Arab + 1462, 100, // jct -> Cyrl + 1466, 535, // jda -> Tibt + 1470, 10, // jdg -> Arab + 1474, 100, // jdt -> Cyrl + 1478, 105, // jee -> Deva + 1482, 125, // jge -> Geor + 1486, 185, // ji -> Hebr + 1489, 165, // jje -> Hang + 1493, 345, // jkm -> Mymr + 1497, 105, // jml -> Deva + 1501, 485, // jna -> Takr + 1505, 10, // jnd -> Arab + 1509, 105, // jnl -> Deva + 1513, 105, // jns -> Deva + 1517, 10, // jog -> Arab + 1521, 185, // jpa -> Hebr + 1525, 185, // jpr -> Hebr + 1529, 185, // jrb -> Hebr + 1533, 10, // jrb_MA -> Arab + 1540, 105, // jul -> Deva + 1544, 385, // jun -> Orya + 1548, 385, // juy -> Orya + 1552, 535, // jya -> Tibt + 1556, 185, // jye -> Hebr + 1560, 125, // ka -> Geor + 1563, 100, // kaa -> Cyrl + 1567, 100, // kap -> Cyrl + 1571, 225, // kaw -> Kawi + 1575, 100, // kbd -> Cyrl + 1579, 10, // kbu -> Arab + 1583, 10, // kby -> Arab + 1587, 100, // kca -> Cyrl + 1591, 45, // kdq -> Beng + 1595, 530, // kdt -> Thai + 1599, 100, // ket -> Cyrl + 1603, 105, // kex -> Deva + 1607, 515, // key -> Telu + 1611, 245, // kfa -> Knda + 1615, 105, // kfb -> Deva + 1619, 515, // kfc -> Telu + 1623, 245, // kfd -> Knda + 1627, 500, // kfe -> Taml + 1631, 320, // kfh -> Mlym + 1635, 500, // kfi -> Taml + 1639, 105, // kfk -> Deva + 1643, 10, // kfm -> Arab + 1647, 105, // kfp -> Deva + 1651, 105, // kfq -> Deva + 1655, 105, // kfr -> Deva + 1659, 105, // kfs -> Deva + 1663, 105, // kfx -> Deva + 1667, 105, // kfy -> Deva + 1671, 105, // kgj -> Deva + 1675, 105, // kgy -> Deva + 1679, 495, // khb -> Talu + 1683, 530, // khf -> Thai + 1687, 535, // khg -> Tibt + 1691, 105, // khn -> Deva + 1695, 345, // kht -> Mymr + 1699, 100, // khv -> Cyrl + 1703, 10, // khw -> Arab + 1707, 105, // kif -> Deva + 1711, 100, // kim -> Cyrl + 1715, 105, // kip -> Deva + 1719, 260, // kjg -> Laoo + 1723, 100, // kjh -> Cyrl + 1727, 105, // kjl -> Deva + 1731, 105, // kjo -> Deva + 1735, 345, // kjp -> Mymr + 1739, 530, // kjt -> Thai + 1743, 100, // kk -> Cyrl + 1746, 10, // kk_AF -> Arab + 1752, 10, // kk_CN -> Arab + 1758, 10, // kk_IR -> Arab + 1764, 10, // kk_MN -> Arab + 1770, 535, // kkf -> Tibt + 1774, 255, // kkh -> Lana + 1778, 105, // kkt -> Deva + 1782, 105, // kle -> Deva + 1786, 10, // klj -> Arab + 1790, 105, // klr -> Deva + 1794, 235, // km -> Khmr + 1797, 105, // kmj -> Deva + 1801, 10, // kmz -> Arab + 1805, 245, // kn -> Knda + 1808, 250, // ko -> Kore + 1811, 100, // koi -> Cyrl + 1815, 105, // kok -> Deva + 1819, 100, // kpt -> Cyrl + 1823, 100, // kpy -> Cyrl + 1827, 475, // kqd -> Syrc + 1831, 120, // kqy -> Ethi + 1835, 105, // kra -> Deva + 1839, 100, // krc -> Cyrl + 1843, 100, // krk -> Cyrl + 1847, 235, // krr -> Khmr + 1851, 105, // kru -> Deva + 1855, 235, // krv -> Khmr + 1859, 10, // ks -> Arab + 1862, 345, // ksu -> Mymr + 1866, 345, // ksw -> Mymr + 1870, 105, // ksz -> Deva + 1874, 120, // ktb -> Ethi + 1878, 10, // ktl -> Arab + 1882, 410, // ktp -> Plrd + 1886, 10, // ku_LB -> Arab + 1892, 260, // kuf -> Laoo + 1896, 100, // kum -> Cyrl + 1900, 100, // kv -> Cyrl + 1903, 100, // kva -> Cyrl + 1907, 345, // kvq -> Mymr + 1911, 345, // kvt -> Mymr + 1915, 10, // kvx -> Arab + 1919, 215, // kvy -> Kali + 1923, 345, // kxf -> Mymr + 1927, 345, // kxk -> Mymr + 1931, 530, // kxm -> Thai + 1935, 10, // kxp -> Arab + 1939, 100, // ky -> Cyrl + 1942, 10, // ky_CN -> Arab + 1948, 215, // kyu -> Kali + 1952, 105, // kyv -> Deva + 1956, 105, // kyw -> Deva + 1960, 270, // lab -> Lina + 1964, 185, // lad -> Hebr + 1968, 105, // lae -> Deva + 1972, 10, // lah -> Arab + 1976, 280, // lbc -> Lisu + 1980, 100, // lbe -> Cyrl + 1984, 105, // lbf -> Deva + 1988, 535, // lbj -> Tibt + 1992, 105, // lbm -> Deva + 1996, 260, // lbo -> Laoo + 2000, 105, // lbr -> Deva + 2004, 530, // lcp -> Thai + 2008, 265, // lep -> Lepc + 2012, 100, // lez -> Cyrl + 2016, 105, // lhm -> Deva + 2020, 475, // lhs -> Syrc + 2024, 105, // lif -> Deva + 2028, 280, // lis -> Lisu + 2032, 535, // lkh -> Tibt + 2036, 10, // lki -> Arab + 2040, 105, // lmh -> Deva + 2044, 515, // lmn -> Telu + 2048, 260, // lo -> Laoo + 2051, 105, // loy -> Deva + 2055, 410, // lpo -> Plrd + 2059, 10, // lrc -> Arab + 2063, 10, // lrk -> Arab + 2067, 10, // lrl -> Arab + 2071, 10, // lsa -> Arab + 2075, 185, // lsd -> Hebr + 2079, 10, // lss -> Arab + 2083, 535, // luk -> Tibt + 2087, 105, // luu -> Deva + 2091, 10, // luv -> Arab + 2095, 10, // luz -> Arab + 2099, 530, // lwl -> Thai + 2103, 530, // lwm -> Thai + 2107, 535, // lya -> Tibt + 2111, 175, // lzh -> Hans + 2115, 105, // mag -> Deva + 2119, 105, // mai -> Deva + 2123, 360, // man_GN -> Nkoo + 2130, 10, // mby -> Arab + 2134, 10, // mde -> Arab + 2138, 100, // mdf -> Cyrl + 2142, 120, // mdx -> Ethi + 2146, 120, // mdy -> Ethi + 2150, 10, // mfa -> Arab + 2154, 10, // mfi -> Arab + 2158, 105, // mgp -> Deva + 2162, 10, // mhj -> Arab + 2166, 295, // mid -> Mand + 2170, 105, // mjl -> Deva + 2174, 320, // mjq -> Mlym + 2178, 320, // mjr -> Mlym + 2182, 105, // mjt -> Deva + 2186, 515, // mju -> Telu + 2190, 320, // mjv -> Mlym + 2194, 105, // mjz -> Deva + 2198, 100, // mk -> Cyrl + 2201, 105, // mkb -> Deva + 2205, 105, // mke -> Deva + 2209, 10, // mki -> Arab + 2213, 530, // mkm -> Thai + 2217, 320, // ml -> Mlym + 2220, 530, // mlf -> Thai + 2224, 100, // mn -> Cyrl + 2227, 330, // mn_CN -> Mong + 2233, 45, // mni -> Beng + 2237, 10, // mnj -> Arab + 2241, 100, // mns -> Cyrl + 2245, 345, // mnw -> Mymr + 2249, 530, // mpz -> Thai + 2253, 105, // mr -> Deva + 2256, 530, // mra -> Thai + 2260, 105, // mrd -> Deva + 2264, 100, // mrj -> Cyrl + 2268, 335, // mro -> Mroo + 2272, 105, // mrr -> Deva + 2276, 10, // ms_CC -> Arab + 2282, 100, // mtm -> Cyrl + 2286, 105, // mtr -> Deva + 2290, 100, // mud -> Cyrl + 2294, 535, // muk -> Tibt + 2298, 105, // mut -> Deva + 2302, 500, // muv -> Taml + 2306, 120, // muz -> Ethi + 2310, 330, // mvf -> Mong + 2314, 10, // mvy -> Arab + 2318, 120, // mvz -> Ethi + 2322, 105, // mwr -> Deva + 2326, 345, // mwt -> Mymr + 2330, 195, // mww -> Hmnp + 2334, 345, // my -> Mymr + 2337, 120, // mym -> Ethi + 2341, 100, // myv -> Cyrl + 2345, 295, // myz -> Mand + 2349, 10, // mzn -> Arab + 2353, 175, // nan -> Hans + 2357, 105, // nao -> Deva + 2361, 105, // ncd -> Deva + 2365, 260, // ncq -> Laoo + 2369, 100, // ndf -> Cyrl + 2373, 105, // ne -> Deva + 2376, 100, // neg -> Cyrl + 2380, 535, // neh -> Tibt + 2384, 570, // nei -> Xsux + 2388, 105, // new -> Deva + 2392, 260, // ngt -> Laoo + 2396, 100, // nio -> Cyrl + 2400, 515, // nit -> Telu + 2404, 100, // niv -> Cyrl + 2408, 10, // nli -> Arab + 2412, 10, // nlm -> Arab + 2416, 105, // nlx -> Deva + 2420, 105, // nmm -> Deva + 2424, 560, // nnp -> Wcho + 2428, 255, // nod -> Lana + 2432, 105, // noe -> Deva + 2436, 100, // nog -> Cyrl + 2440, 105, // noi -> Deva + 2444, 430, // non -> Runr + 2448, 575, // nos -> Yiii + 2452, 535, // npb -> Tibt + 2456, 360, // nqo -> Nkoo + 2460, 575, // nsd -> Yiii + 2464, 575, // nsf -> Yiii + 2468, 65, // nsk -> Cans + 2472, 540, // nst -> Tnsa + 2476, 575, // nsv -> Yiii + 2480, 575, // nty -> Yiii + 2484, 10, // ntz -> Arab + 2488, 355, // nwc -> Newa + 2492, 105, // nwx -> Deva + 2496, 530, // nyl -> Thai + 2500, 10, // nyq -> Arab + 2504, 100, // oaa -> Cyrl + 2508, 100, // oac -> Cyrl + 2512, 475, // oar -> Syrc + 2516, 125, // oav -> Geor + 2520, 405, // obm -> Phnx + 2524, 345, // obr -> Mymr + 2528, 10, // odk -> Arab + 2532, 570, // oht -> Xsux + 2536, 65, // oj -> Cans + 2539, 65, // ojs -> Cans + 2543, 165, // okm -> Hang + 2547, 170, // oko -> Hani + 2551, 235, // okz -> Khmr + 2555, 105, // ola -> Deva + 2559, 535, // ole -> Tibt + 2563, 100, // omk -> Cyrl + 2567, 340, // omp -> Mtei + 2571, 325, // omr -> Modi + 2575, 105, // oon -> Deva + 2579, 385, // or -> Orya + 2582, 515, // ort -> Telu + 2586, 10, // oru -> Arab + 2590, 100, // orv -> Cyrl + 2594, 100, // os -> Cyrl + 2597, 390, // osa -> Osge + 2601, 200, // osc -> Ital + 2605, 205, // osi -> Java + 2609, 10, // ota -> Arab + 2613, 535, // otb -> Tibt + 2617, 380, // otk -> Orkh + 2621, 145, // oty -> Gran + 2625, 160, // pa -> Guru + 2628, 10, // pa_PK -> Arab + 2634, 400, // pal -> Phli + 2638, 100, // paq -> Cyrl + 2642, 10, // pbt -> Arab + 2646, 235, // pcb -> Khmr + 2650, 345, // pce -> Mymr + 2654, 320, // pcf -> Mlym + 2658, 320, // pcg -> Mlym + 2662, 105, // pch -> Deva + 2666, 105, // pci -> Deva + 2670, 515, // pcj -> Telu + 2674, 385, // peg -> Orya + 2678, 565, // peo -> Xpeo + 2682, 230, // pgd -> Khar + 2686, 105, // pgg -> Deva + 2690, 370, // pgl -> Ogam + 2694, 200, // pgn -> Ital + 2698, 105, // phd -> Deva + 2702, 345, // phk -> Mymr + 2706, 10, // phl -> Arab + 2710, 405, // phn -> Phnx + 2714, 260, // pho -> Laoo + 2718, 10, // phr -> Arab + 2722, 530, // pht -> Thai + 2726, 10, // phv -> Arab + 2730, 105, // phw -> Deva + 2734, 455, // pi -> Sinh + 2737, 55, // pka -> Brah + 2741, 320, // pkr -> Mlym + 2745, 10, // plk -> Arab + 2749, 345, // pll -> Mymr + 2753, 55, // pmh -> Brah + 2757, 150, // pnt -> Grek + 2761, 230, // pra -> Khar + 2765, 10, // prc -> Arab + 2769, 10, // prd -> Arab + 2773, 155, // prp -> Gujr + 2777, 530, // prt -> Thai + 2781, 10, // prx -> Arab + 2785, 10, // ps -> Arab + 2788, 10, // psh -> Arab + 2792, 10, // psi -> Arab + 2796, 10, // pst -> Arab + 2800, 105, // pum -> Deva + 2804, 345, // pwo -> Mymr + 2808, 105, // pwr -> Deva + 2812, 530, // pww -> Thai + 2816, 345, // pyx -> Mymr + 2820, 10, // qxq -> Arab + 2824, 105, // raa -> Deva + 2828, 105, // rab -> Deva + 2832, 105, // raf -> Deva + 2836, 45, // rah -> Beng + 2840, 105, // raj -> Deva + 2844, 105, // rav -> Deva + 2848, 345, // rbb -> Mymr + 2852, 10, // rdb -> Arab + 2856, 385, // rei -> Orya + 2860, 425, // rhg -> Rohg + 2864, 105, // rji -> Deva + 2868, 105, // rjs -> Deva + 2872, 235, // rka -> Khmr + 2876, 345, // rki -> Mymr + 2880, 45, // rkt -> Beng + 2884, 20, // rmi -> Armn + 2888, 10, // rmt -> Arab + 2892, 345, // rmz -> Mymr + 2896, 100, // rom_BG -> Cyrl + 2903, 100, // rsk -> Cyrl + 2907, 105, // rtw -> Deva + 2911, 100, // ru -> Cyrl + 2914, 100, // rue -> Cyrl + 2918, 100, // rut -> Cyrl + 2922, 105, // rwr -> Deva + 2926, 220, // ryu -> Kana + 2930, 105, // sa -> Deva + 2933, 100, // sah -> Cyrl + 2937, 435, // sam -> Samr + 2941, 375, // sat -> Olck + 2945, 445, // saz -> Saur + 2949, 10, // sbn -> Arab + 2953, 535, // sbu -> Tibt + 2957, 105, // sck -> Deva + 2961, 10, // scl -> Arab + 2965, 10, // scl_IN -> Arab + 2972, 105, // scp -> Deva + 2976, 260, // sct -> Laoo + 2980, 485, // scu -> Takr + 2984, 150, // scx -> Grek + 2988, 10, // sd -> Arab + 2991, 105, // sd_IN -> Deva + 2997, 10, // sdb -> Arab + 3001, 10, // sdf -> Arab + 3005, 10, // sdg -> Arab + 3009, 10, // sdh -> Arab + 3013, 10, // sds -> Arab + 3017, 100, // sel -> Cyrl + 3021, 410, // sfm -> Plrd + 3025, 370, // sga -> Ogam + 3029, 100, // sgh -> Cyrl + 3033, 105, // sgj -> Deva + 3037, 10, // sgr -> Arab + 3041, 535, // sgt -> Tibt + 3045, 120, // sgw -> Ethi + 3049, 10, // sgy -> Arab + 3053, 10, // shd -> Arab + 3057, 520, // shi -> Tfng + 3061, 10, // shm -> Arab + 3065, 345, // shn -> Mymr + 3069, 10, // shu -> Arab + 3073, 10, // shv -> Arab + 3077, 455, // si -> Sinh + 3080, 100, // sia -> Cyrl + 3084, 535, // sip -> Tibt + 3088, 10, // siy -> Arab + 3092, 10, // siz -> Arab + 3096, 100, // sjd -> Cyrl + 3100, 105, // sjp -> Deva + 3104, 100, // sjt -> Cyrl + 3108, 530, // skb -> Thai + 3112, 105, // skj -> Deva + 3116, 10, // skr -> Arab + 3120, 10, // slq -> Arab + 3124, 575, // smh -> Yiii + 3128, 435, // smp -> Samr + 3132, 235, // smu -> Khmr + 3136, 10, // smy -> Arab + 3140, 510, // soa -> Tavt + 3144, 460, // sog -> Sogd + 3148, 105, // soi -> Deva + 3152, 530, // sou -> Thai + 3156, 535, // spt -> Tibt + 3160, 385, // spv -> Orya + 3164, 10, // sqo -> Arab + 3168, 260, // sqq -> Laoo + 3172, 10, // sqt -> Arab + 3176, 100, // sr -> Cyrl + 3179, 465, // srb -> Sora + 3183, 10, // srh -> Arab + 3187, 105, // srx -> Deva + 3191, 10, // srz -> Arab + 3195, 10, // ssh -> Arab + 3199, 260, // sss -> Laoo + 3203, 10, // sts -> Arab + 3207, 120, // stv -> Ethi + 3211, 100, // sty -> Cyrl + 3215, 105, // suz -> Deva + 3219, 125, // sva -> Geor + 3223, 10, // swb -> Arab + 3227, 170, // swi -> Hani + 3231, 105, // swv -> Deva + 3235, 475, // syc -> Syrc + 3239, 45, // syl -> Beng + 3243, 475, // syn -> Syrc + 3247, 475, // syr -> Syrc + 3251, 105, // syw -> Deva + 3255, 500, // ta -> Taml + 3258, 100, // tab -> Cyrl + 3262, 105, // taj -> Deva + 3266, 480, // tbk -> Tagb + 3270, 535, // tcn -> Tibt + 3274, 345, // tco -> Mymr + 3278, 500, // tcx -> Taml + 3282, 245, // tcy -> Knda + 3286, 520, // tda -> Tfng + 3290, 105, // tdb -> Deva + 3294, 490, // tdd -> Tale + 3298, 105, // tdg -> Deva + 3302, 105, // tdh -> Deva + 3306, 515, // te -> Telu + 3309, 205, // tes -> Java + 3313, 100, // tg -> Cyrl + 3316, 10, // tg_PK -> Arab + 3322, 105, // tge -> Deva + 3326, 535, // tgf -> Tibt + 3330, 530, // th -> Thai + 3333, 105, // the -> Deva + 3337, 105, // thf -> Deva + 3341, 490, // thi -> Tale + 3345, 105, // thl -> Deva + 3349, 530, // thm -> Thai + 3353, 105, // thq -> Deva + 3357, 105, // thr -> Deva + 3361, 105, // ths -> Deva + 3365, 120, // ti -> Ethi + 3368, 120, // tig -> Ethi + 3372, 105, // tij -> Deva + 3376, 100, // tin -> Cyrl + 3380, 345, // tjl -> Mymr + 3384, 10, // tjo -> Arab + 3388, 105, // tkb -> Deva + 3392, 10, // tks -> Arab + 3396, 105, // tkt -> Deva + 3400, 105, // tmk -> Deva + 3404, 475, // tmr -> Syrc + 3408, 60, // tnv -> Cakm + 3412, 10, // tov -> Arab + 3416, 235, // tpu -> Khmr + 3420, 10, // tra -> Arab + 3424, 185, // trg -> Hebr + 3428, 10, // trm -> Arab + 3432, 10, // trw -> Arab + 3436, 150, // tsd -> Grek + 3440, 535, // tsj -> Tibt + 3444, 100, // tt -> Cyrl + 3447, 260, // tth -> Laoo + 3451, 260, // tto -> Laoo + 3455, 530, // tts -> Thai + 3459, 345, // tvn -> Mymr + 3463, 105, // twm -> Deva + 3467, 505, // txg -> Tang + 3471, 545, // txo -> Toto + 3475, 510, // tyr -> Tavt + 3479, 100, // tyv -> Cyrl + 3483, 100, // ude -> Cyrl + 3487, 320, // udg -> Mlym + 3491, 0, // udi -> Aghb + 3495, 100, // udm -> Cyrl + 3499, 10, // ug -> Arab + 3502, 100, // ug_KZ -> Cyrl + 3508, 100, // ug_MN -> Cyrl + 3514, 550, // uga -> Ugar + 3518, 100, // ugh -> Cyrl + 3522, 530, // ugo -> Thai + 3526, 100, // uk -> Cyrl + 3529, 385, // uki -> Orya + 3533, 100, // ulc -> Cyrl + 3537, 45, // unr -> Beng + 3541, 105, // unr_NP -> Deva + 3548, 45, // unx -> Beng + 3552, 10, // ur -> Arab + 3555, 530, // urk -> Thai + 3559, 10, // ush -> Arab + 3563, 150, // uum -> Grek + 3567, 10, // uz_AF -> Arab + 3573, 100, // uz_CN -> Cyrl + 3579, 10, // uzs -> Arab + 3583, 500, // vaa -> Taml + 3587, 10, // vaf -> Arab + 3591, 105, // vah -> Deva + 3595, 555, // vai -> Vaii + 3599, 105, // vas -> Deva + 3603, 105, // vav -> Deva + 3607, 105, // vay -> Deva + 3611, 10, // vgr -> Arab + 3615, 245, // vmd -> Knda + 3619, 10, // vmh -> Arab + 3623, 120, // wal -> Ethi + 3627, 10, // wbk -> Arab + 3631, 515, // wbq -> Telu + 3635, 105, // wbr -> Deva + 3639, 10, // wlo -> Arab + 3643, 105, // wme -> Deva + 3647, 10, // wne -> Arab + 3651, 10, // wni -> Arab + 3655, 130, // wsg -> Gong + 3659, 10, // wsv -> Arab + 3663, 105, // wtm -> Deva + 3667, 175, // wuu -> Hans + 3671, 100, // xal -> Cyrl + 3675, 120, // xan -> Ethi + 3679, 100, // xas -> Cyrl + 3683, 85, // xco -> Chrs + 3687, 70, // xcr -> Cari + 3691, 100, // xdq -> Cyrl + 3695, 10, // xhe -> Arab + 3699, 235, // xhm -> Khmr + 3703, 385, // xis -> Orya + 3707, 10, // xka -> Arab + 3711, 10, // xkc -> Arab + 3715, 10, // xkj -> Arab + 3719, 10, // xkp -> Arab + 3723, 285, // xlc -> Lyci + 3727, 290, // xld -> Lydi + 3731, 115, // xly -> Elym + 3735, 125, // xmf -> Geor + 3739, 300, // xmn -> Mani + 3743, 315, // xmr -> Merc + 3747, 350, // xna -> Narb + 3751, 105, // xnr -> Deva + 3755, 150, // xpg -> Grek + 3759, 370, // xpi -> Ogam + 3763, 100, // xpm -> Cyrl + 3767, 415, // xpr -> Prti + 3771, 100, // xrm -> Cyrl + 3775, 100, // xrn -> Cyrl + 3779, 440, // xsa -> Sarb + 3783, 105, // xsr -> Deva + 3787, 100, // xss -> Cyrl + 3791, 500, // xub -> Taml + 3795, 500, // xuj -> Taml + 3799, 200, // xve -> Ital + 3803, 10, // xvi -> Arab + 3807, 100, // xwo -> Cyrl + 3811, 305, // xzh -> Marc + 3815, 100, // yai -> Cyrl + 3819, 105, // ybh -> Deva + 3823, 105, // ybi -> Deva + 3827, 10, // ydg -> Arab + 3831, 320, // yea -> Mlym + 3835, 150, // yej -> Grek + 3839, 515, // yeu -> Telu + 3843, 410, // ygp -> Plrd + 3847, 185, // yhd -> Hebr + 3851, 185, // yi -> Hebr + 3854, 575, // yig -> Yiii + 3858, 185, // yih -> Hebr + 3862, 575, // yiv -> Yiii + 3866, 100, // ykg -> Cyrl + 3870, 410, // yna -> Plrd + 3874, 100, // ynk -> Cyrl + 3878, 210, // yoi -> Jpan + 3882, 530, // yoy -> Thai + 3886, 100, // yrk -> Cyrl + 3890, 575, // ysd -> Yiii + 3894, 575, // ysn -> Yiii + 3898, 575, // ysp -> Yiii + 3902, 100, // ysr -> Cyrl + 3906, 410, // ysy -> Plrd + 3910, 185, // yud -> Hebr + 3914, 180, // yue -> Hant + 3918, 175, // yue_CN -> Hans + 3925, 100, // yug -> Cyrl + 3929, 100, // yux -> Cyrl + 3933, 410, // ywq -> Plrd + 3937, 410, // ywu -> Plrd + 3941, 535, // zau -> Tibt + 3945, 10, // zba -> Arab + 3949, 170, // zch -> Hani + 3953, 10, // zdj -> Arab + 3957, 170, // zeh -> Hani + 3961, 520, // zen -> Tfng + 3965, 170, // zgb -> Hani + 3969, 520, // zgh -> Tfng + 3973, 170, // zgm -> Hani + 3977, 170, // zgn -> Hani + 3981, 175, // zh -> Hans + 3984, 180, // zh_AU -> Hant + 3990, 180, // zh_BN -> Hant + 3996, 180, // zh_GB -> Hant + 4002, 180, // zh_GF -> Hant + 4008, 180, // zh_HK -> Hant + 4014, 180, // zh_ID -> Hant + 4020, 180, // zh_MO -> Hant + 4026, 180, // zh_PA -> Hant + 4032, 180, // zh_PF -> Hant + 4038, 180, // zh_PH -> Hant + 4044, 180, // zh_SR -> Hant + 4050, 180, // zh_TH -> Hant + 4056, 180, // zh_TW -> Hant + 4062, 180, // zh_US -> Hant + 4068, 180, // zh_VN -> Hant + 4074, 170, // zhd -> Hani + 4078, 365, // zhx -> Nshu + 4082, 100, // zkb -> Cyrl + 4086, 100, // zko -> Cyrl + 4090, 240, // zkt -> Kits + 4094, 100, // zkz -> Cyrl + 4098, 170, // zlj -> Hani + 4102, 170, // zln -> Hani + 4106, 170, // zlq -> Hani + 4110, 170, // zqe -> Hani + 4114, 185, // zrp -> Hebr + 4118, 10, // zum -> Arab + 4122, 170, // zyg -> Hani + 4126, 170, // zyn -> Hani + 4130, 170, // zzj -> Hani }; //====================================================================== @@ -1150,35 +1138,36 @@ const char parentLocaleChars[] = "en_AU\0en_BB\0en_BE\0en_BM\0en_BS\0en_BW\0en_BZ\0en_CC\0en_CH\0" "en_CK\0en_CM\0en_CX\0en_CY\0en_DE\0en_DG\0en_DK\0en_DM\0en_Dsrt\0" "en_ER\0en_FI\0en_FJ\0en_FK\0en_FM\0en_GB\0en_GD\0en_GG\0en_GH\0" - "en_GI\0en_GM\0en_GY\0en_HK\0en_IE\0en_IL\0en_IM\0en_IN\0en_IO\0" - "en_JE\0en_JM\0en_KE\0en_KI\0en_KN\0en_KY\0en_LC\0en_LR\0en_LS\0" - "en_MG\0en_MO\0en_MS\0en_MT\0en_MU\0en_MV\0en_MW\0en_MY\0en_NA\0" - "en_NF\0en_NG\0en_NL\0en_NR\0en_NU\0en_NZ\0en_PG\0en_PK\0en_PN\0" - "en_PW\0en_RW\0en_SB\0en_SC\0en_SD\0en_SE\0en_SG\0en_SH\0en_SI\0" - "en_SL\0en_SS\0en_SX\0en_SZ\0en_Shaw\0en_TC\0en_TK\0en_TO\0en_TT\0" - "en_TV\0en_TZ\0en_UG\0en_VC\0en_VG\0en_VU\0en_WS\0en_ZA\0en_ZM\0" - "en_ZW\0es_419\0es_AR\0es_BO\0es_BR\0es_BZ\0es_CL\0es_CO\0es_CR\0" - "es_CU\0es_DO\0es_EC\0es_GT\0es_HN\0es_MX\0es_NI\0es_PA\0es_PE\0" - "es_PR\0es_PY\0es_SV\0es_US\0es_UY\0es_VE\0ff_Adlm\0ff_Arab\0fr_HT\0" - "ha_Arab\0hi_Latn\0ht\0iu_Latn\0kk_Arab\0ks_Deva\0ku_Arab\0ky_Arab\0" - "ky_Latn\0ml_Arab\0mn_Mong\0mni_Mtei\0ms_Arab\0nb\0nn\0no\0no_NO\0" - "pa_Arab\0pt_AO\0pt_CH\0pt_CV\0pt_FR\0pt_GQ\0pt_GW\0pt_LU\0pt_MO\0" - "pt_MZ\0pt_PT\0pt_ST\0pt_TL\0root\0sat_Deva\0sd_Deva\0sd_Khoj\0" - "sd_Sind\0shi_Latn\0so_Arab\0sr_Latn\0sw_Arab\0tg_Arab\0ug_Cyrl\0" - "uz_Arab\0uz_Cyrl\0vai_Latn\0wo_Arab\0yo_Arab\0yue_Hans\0zh_Hant\0" - "zh_Hant_HK\0zh_Hant_MO\0"; + "en_GI\0en_GM\0en_GY\0en_HK\0en_ID\0en_IE\0en_IL\0en_IM\0en_IN\0" + "en_IO\0en_JE\0en_JM\0en_KE\0en_KI\0en_KN\0en_KY\0en_LC\0en_LR\0" + "en_LS\0en_MG\0en_MO\0en_MS\0en_MT\0en_MU\0en_MV\0en_MW\0en_MY\0" + "en_NA\0en_NF\0en_NG\0en_NL\0en_NR\0en_NU\0en_NZ\0en_PG\0en_PK\0" + "en_PN\0en_PW\0en_RW\0en_SB\0en_SC\0en_SD\0en_SE\0en_SG\0en_SH\0" + "en_SI\0en_SL\0en_SS\0en_SX\0en_SZ\0en_Shaw\0en_TC\0en_TK\0en_TO\0" + "en_TT\0en_TV\0en_TZ\0en_UG\0en_VC\0en_VG\0en_VU\0en_WS\0en_ZA\0" + "en_ZM\0en_ZW\0es_419\0es_AR\0es_BO\0es_BR\0es_BZ\0es_CL\0es_CO\0" + "es_CR\0es_CU\0es_DO\0es_EC\0es_GT\0es_HN\0es_JP\0es_MX\0es_NI\0" + "es_PA\0es_PE\0es_PR\0es_PY\0es_SV\0es_US\0es_UY\0es_VE\0ff_Adlm\0" + "ff_Arab\0fr_HT\0ha_Arab\0hi_Latn\0ht\0iu_Latn\0kk_Arab\0ks_Deva\0" + "ku_Arab\0kxv_Deva\0kxv_Orya\0kxv_Telu\0ky_Arab\0ky_Latn\0ml_Arab\0" + "mn_Mong\0mni_Mtei\0ms_Arab\0nb\0nn\0no\0no_NO\0pa_Arab\0pt_AO\0" + "pt_CH\0pt_CV\0pt_FR\0pt_GQ\0pt_GW\0pt_LU\0pt_MO\0pt_MZ\0pt_PT\0" + "pt_ST\0pt_TL\0root\0sat_Deva\0sd_Deva\0sd_Khoj\0sd_Sind\0shi_Latn\0" + "so_Arab\0sr_Latn\0sw_Arab\0tg_Arab\0ug_Cyrl\0uz_Arab\0uz_Cyrl\0" + "vai_Latn\0wo_Arab\0yo_Arab\0yue_Hans\0zh_Hant\0zh_Hant_HK\0zh_Hant_MO\0" + ""; const int32_t parentLocaleTable[] = { - 0, 1023, // az_Arab -> root - 8, 1023, // az_Cyrl -> root - 16, 1023, // bal_Latn -> root - 25, 1023, // blt_Latn -> root - 34, 1023, // bm_Nkoo -> root - 42, 1023, // bs_Cyrl -> root - 50, 1023, // byn_Latn -> root - 59, 1023, // cu_Glag -> root - 67, 1023, // dje_Arab -> root - 76, 1023, // dyo_Arab -> root + 0, 1062, // az_Arab -> root + 8, 1062, // az_Cyrl -> root + 16, 1062, // bal_Latn -> root + 25, 1062, // blt_Latn -> root + 34, 1062, // bm_Nkoo -> root + 42, 1062, // bs_Cyrl -> root + 50, 1062, // byn_Latn -> root + 59, 1062, // cu_Glag -> root + 67, 1062, // dje_Arab -> root + 76, 1062, // dyo_Arab -> root 92, 85, // en_150 -> en_001 99, 85, // en_AG -> en_001 105, 85, // en_AI -> en_001 @@ -1200,7 +1189,7 @@ const int32_t parentLocaleTable[] = { 201, 85, // en_DG -> en_001 207, 92, // en_DK -> en_150 213, 85, // en_DM -> en_001 - 219, 1023, // en_Dsrt -> root + 219, 1062, // en_Dsrt -> root 227, 85, // en_ER -> en_001 233, 92, // en_FI -> en_150 239, 85, // en_FJ -> en_001 @@ -1214,136 +1203,141 @@ const int32_t parentLocaleTable[] = { 287, 85, // en_GM -> en_001 293, 85, // en_GY -> en_001 299, 85, // en_HK -> en_001 - 305, 85, // en_IE -> en_001 - 311, 85, // en_IL -> en_001 - 317, 85, // en_IM -> en_001 - 323, 85, // en_IN -> en_001 - 329, 85, // en_IO -> en_001 - 335, 85, // en_JE -> en_001 - 341, 85, // en_JM -> en_001 - 347, 85, // en_KE -> en_001 - 353, 85, // en_KI -> en_001 - 359, 85, // en_KN -> en_001 - 365, 85, // en_KY -> en_001 - 371, 85, // en_LC -> en_001 - 377, 85, // en_LR -> en_001 - 383, 85, // en_LS -> en_001 - 389, 85, // en_MG -> en_001 - 395, 85, // en_MO -> en_001 - 401, 85, // en_MS -> en_001 - 407, 85, // en_MT -> en_001 - 413, 85, // en_MU -> en_001 - 419, 85, // en_MV -> en_001 - 425, 85, // en_MW -> en_001 - 431, 85, // en_MY -> en_001 - 437, 85, // en_NA -> en_001 - 443, 85, // en_NF -> en_001 - 449, 85, // en_NG -> en_001 - 455, 92, // en_NL -> en_150 - 461, 85, // en_NR -> en_001 - 467, 85, // en_NU -> en_001 - 473, 85, // en_NZ -> en_001 - 479, 85, // en_PG -> en_001 - 485, 85, // en_PK -> en_001 - 491, 85, // en_PN -> en_001 - 497, 85, // en_PW -> en_001 - 503, 85, // en_RW -> en_001 - 509, 85, // en_SB -> en_001 - 515, 85, // en_SC -> en_001 - 521, 85, // en_SD -> en_001 - 527, 92, // en_SE -> en_150 - 533, 85, // en_SG -> en_001 - 539, 85, // en_SH -> en_001 - 545, 92, // en_SI -> en_150 - 551, 85, // en_SL -> en_001 - 557, 85, // en_SS -> en_001 - 563, 85, // en_SX -> en_001 - 569, 85, // en_SZ -> en_001 - 575, 1023, // en_Shaw -> root - 583, 85, // en_TC -> en_001 - 589, 85, // en_TK -> en_001 - 595, 85, // en_TO -> en_001 - 601, 85, // en_TT -> en_001 - 607, 85, // en_TV -> en_001 - 613, 85, // en_TZ -> en_001 - 619, 85, // en_UG -> en_001 - 625, 85, // en_VC -> en_001 - 631, 85, // en_VG -> en_001 - 637, 85, // en_VU -> en_001 - 643, 85, // en_WS -> en_001 - 649, 85, // en_ZA -> en_001 - 655, 85, // en_ZM -> en_001 - 661, 85, // en_ZW -> en_001 - 674, 667, // es_AR -> es_419 - 680, 667, // es_BO -> es_419 - 686, 667, // es_BR -> es_419 - 692, 667, // es_BZ -> es_419 - 698, 667, // es_CL -> es_419 - 704, 667, // es_CO -> es_419 - 710, 667, // es_CR -> es_419 - 716, 667, // es_CU -> es_419 - 722, 667, // es_DO -> es_419 - 728, 667, // es_EC -> es_419 - 734, 667, // es_GT -> es_419 - 740, 667, // es_HN -> es_419 - 746, 667, // es_MX -> es_419 - 752, 667, // es_NI -> es_419 - 758, 667, // es_PA -> es_419 - 764, 667, // es_PE -> es_419 - 770, 667, // es_PR -> es_419 - 776, 667, // es_PY -> es_419 - 782, 667, // es_SV -> es_419 - 788, 667, // es_US -> es_419 - 794, 667, // es_UY -> es_419 - 800, 667, // es_VE -> es_419 - 806, 1023, // ff_Adlm -> root - 814, 1023, // ff_Arab -> root - 828, 1023, // ha_Arab -> root - 836, 323, // hi_Latn -> en_IN - 844, 822, // ht -> fr_HT - 847, 1023, // iu_Latn -> root - 855, 1023, // kk_Arab -> root - 863, 1023, // ks_Deva -> root - 871, 1023, // ku_Arab -> root - 879, 1023, // ky_Arab -> root - 887, 1023, // ky_Latn -> root - 895, 1023, // ml_Arab -> root - 903, 1023, // mn_Mong -> root - 911, 1023, // mni_Mtei -> root - 920, 1023, // ms_Arab -> root - 928, 934, // nb -> no - 931, 934, // nn -> no - 937, 934, // no_NO -> no - 943, 1023, // pa_Arab -> root - 951, 1005, // pt_AO -> pt_PT - 957, 1005, // pt_CH -> pt_PT - 963, 1005, // pt_CV -> pt_PT - 969, 1005, // pt_FR -> pt_PT - 975, 1005, // pt_GQ -> pt_PT - 981, 1005, // pt_GW -> pt_PT - 987, 1005, // pt_LU -> pt_PT - 993, 1005, // pt_MO -> pt_PT - 999, 1005, // pt_MZ -> pt_PT - 1011, 1005, // pt_ST -> pt_PT - 1017, 1005, // pt_TL -> pt_PT - 1028, 1023, // sat_Deva -> root - 1037, 1023, // sd_Deva -> root - 1045, 1023, // sd_Khoj -> root - 1053, 1023, // sd_Sind -> root - 1061, 1023, // shi_Latn -> root - 1070, 1023, // so_Arab -> root - 1078, 1023, // sr_Latn -> root - 1086, 1023, // sw_Arab -> root - 1094, 1023, // tg_Arab -> root - 1102, 1023, // ug_Cyrl -> root - 1110, 1023, // uz_Arab -> root - 1118, 1023, // uz_Cyrl -> root - 1126, 1023, // vai_Latn -> root - 1135, 1023, // wo_Arab -> root - 1143, 1023, // yo_Arab -> root - 1151, 1023, // yue_Hans -> root - 1160, 1023, // zh_Hant -> root - 1179, 1168, // zh_Hant_MO -> zh_Hant_HK + 305, 85, // en_ID -> en_001 + 311, 85, // en_IE -> en_001 + 317, 85, // en_IL -> en_001 + 323, 85, // en_IM -> en_001 + 329, 85, // en_IN -> en_001 + 335, 85, // en_IO -> en_001 + 341, 85, // en_JE -> en_001 + 347, 85, // en_JM -> en_001 + 353, 85, // en_KE -> en_001 + 359, 85, // en_KI -> en_001 + 365, 85, // en_KN -> en_001 + 371, 85, // en_KY -> en_001 + 377, 85, // en_LC -> en_001 + 383, 85, // en_LR -> en_001 + 389, 85, // en_LS -> en_001 + 395, 85, // en_MG -> en_001 + 401, 85, // en_MO -> en_001 + 407, 85, // en_MS -> en_001 + 413, 85, // en_MT -> en_001 + 419, 85, // en_MU -> en_001 + 425, 85, // en_MV -> en_001 + 431, 85, // en_MW -> en_001 + 437, 85, // en_MY -> en_001 + 443, 85, // en_NA -> en_001 + 449, 85, // en_NF -> en_001 + 455, 85, // en_NG -> en_001 + 461, 92, // en_NL -> en_150 + 467, 85, // en_NR -> en_001 + 473, 85, // en_NU -> en_001 + 479, 85, // en_NZ -> en_001 + 485, 85, // en_PG -> en_001 + 491, 85, // en_PK -> en_001 + 497, 85, // en_PN -> en_001 + 503, 85, // en_PW -> en_001 + 509, 85, // en_RW -> en_001 + 515, 85, // en_SB -> en_001 + 521, 85, // en_SC -> en_001 + 527, 85, // en_SD -> en_001 + 533, 92, // en_SE -> en_150 + 539, 85, // en_SG -> en_001 + 545, 85, // en_SH -> en_001 + 551, 92, // en_SI -> en_150 + 557, 85, // en_SL -> en_001 + 563, 85, // en_SS -> en_001 + 569, 85, // en_SX -> en_001 + 575, 85, // en_SZ -> en_001 + 581, 1062, // en_Shaw -> root + 589, 85, // en_TC -> en_001 + 595, 85, // en_TK -> en_001 + 601, 85, // en_TO -> en_001 + 607, 85, // en_TT -> en_001 + 613, 85, // en_TV -> en_001 + 619, 85, // en_TZ -> en_001 + 625, 85, // en_UG -> en_001 + 631, 85, // en_VC -> en_001 + 637, 85, // en_VG -> en_001 + 643, 85, // en_VU -> en_001 + 649, 85, // en_WS -> en_001 + 655, 85, // en_ZA -> en_001 + 661, 85, // en_ZM -> en_001 + 667, 85, // en_ZW -> en_001 + 680, 673, // es_AR -> es_419 + 686, 673, // es_BO -> es_419 + 692, 673, // es_BR -> es_419 + 698, 673, // es_BZ -> es_419 + 704, 673, // es_CL -> es_419 + 710, 673, // es_CO -> es_419 + 716, 673, // es_CR -> es_419 + 722, 673, // es_CU -> es_419 + 728, 673, // es_DO -> es_419 + 734, 673, // es_EC -> es_419 + 740, 673, // es_GT -> es_419 + 746, 673, // es_HN -> es_419 + 752, 673, // es_JP -> es_419 + 758, 673, // es_MX -> es_419 + 764, 673, // es_NI -> es_419 + 770, 673, // es_PA -> es_419 + 776, 673, // es_PE -> es_419 + 782, 673, // es_PR -> es_419 + 788, 673, // es_PY -> es_419 + 794, 673, // es_SV -> es_419 + 800, 673, // es_US -> es_419 + 806, 673, // es_UY -> es_419 + 812, 673, // es_VE -> es_419 + 818, 1062, // ff_Adlm -> root + 826, 1062, // ff_Arab -> root + 840, 1062, // ha_Arab -> root + 848, 329, // hi_Latn -> en_IN + 856, 834, // ht -> fr_HT + 859, 1062, // iu_Latn -> root + 867, 1062, // kk_Arab -> root + 875, 1062, // ks_Deva -> root + 883, 1062, // ku_Arab -> root + 891, 1062, // kxv_Deva -> root + 900, 1062, // kxv_Orya -> root + 909, 1062, // kxv_Telu -> root + 918, 1062, // ky_Arab -> root + 926, 1062, // ky_Latn -> root + 934, 1062, // ml_Arab -> root + 942, 1062, // mn_Mong -> root + 950, 1062, // mni_Mtei -> root + 959, 1062, // ms_Arab -> root + 967, 973, // nb -> no + 970, 973, // nn -> no + 976, 973, // no_NO -> no + 982, 1062, // pa_Arab -> root + 990, 1044, // pt_AO -> pt_PT + 996, 1044, // pt_CH -> pt_PT + 1002, 1044, // pt_CV -> pt_PT + 1008, 1044, // pt_FR -> pt_PT + 1014, 1044, // pt_GQ -> pt_PT + 1020, 1044, // pt_GW -> pt_PT + 1026, 1044, // pt_LU -> pt_PT + 1032, 1044, // pt_MO -> pt_PT + 1038, 1044, // pt_MZ -> pt_PT + 1050, 1044, // pt_ST -> pt_PT + 1056, 1044, // pt_TL -> pt_PT + 1067, 1062, // sat_Deva -> root + 1076, 1062, // sd_Deva -> root + 1084, 1062, // sd_Khoj -> root + 1092, 1062, // sd_Sind -> root + 1100, 1062, // shi_Latn -> root + 1109, 1062, // so_Arab -> root + 1117, 1062, // sr_Latn -> root + 1125, 1062, // sw_Arab -> root + 1133, 1062, // tg_Arab -> root + 1141, 1062, // ug_Cyrl -> root + 1149, 1062, // uz_Arab -> root + 1157, 1062, // uz_Cyrl -> root + 1165, 1062, // vai_Latn -> root + 1174, 1062, // wo_Arab -> root + 1182, 1062, // yo_Arab -> root + 1190, 1062, // yue_Hans -> root + 1199, 1062, // zh_Hant -> root + 1218, 1207, // zh_Hant_MO -> zh_Hant_HK }; diff --git a/thirdparty/icu4c/common/localematcher.cpp b/thirdparty/icu4c/common/localematcher.cpp index 5f8c703df7..6fc578af11 100644 --- a/thirdparty/icu4c/common/localematcher.cpp +++ b/thirdparty/icu4c/common/localematcher.cpp @@ -307,7 +307,7 @@ LSR getMaximalLsrOrUnd(const XLikelySubtags &likelySubtags, const Locale &locale if (U_FAILURE(errorCode) || locale.isBogus() || *locale.getName() == 0 /* "und" */) { return UND_LSR; } else { - return likelySubtags.makeMaximizedLsrFrom(locale, errorCode); + return likelySubtags.makeMaximizedLsrFrom(locale, false, errorCode); } } diff --git a/thirdparty/icu4c/common/locid.cpp b/thirdparty/icu4c/common/locid.cpp index 70a794ae07..64ff63f361 100644 --- a/thirdparty/icu4c/common/locid.cpp +++ b/thirdparty/icu4c/common/locid.cpp @@ -563,7 +563,7 @@ private: LocalMemory<int32_t>& replacementIndexes, int32_t &length, void (*checkType)(const char* type), - void (*checkReplacement)(const UnicodeString& replacement), + void (*checkReplacement)(const UChar* replacement), UErrorCode &status); // Read the languageAlias data from alias to @@ -700,7 +700,7 @@ AliasDataBuilder::readAlias( LocalMemory<int32_t>& replacementIndexes, int32_t &length, void (*checkType)(const char* type), - void (*checkReplacement)(const UnicodeString& replacement), + void (*checkReplacement)(const UChar* replacement), UErrorCode &status) { if (U_FAILURE(status)) { return; @@ -720,8 +720,8 @@ AliasDataBuilder::readAlias( LocalUResourceBundlePointer res( ures_getNextResource(alias, nullptr, &status)); const char* aliasFrom = ures_getKey(res.getAlias()); - UnicodeString aliasTo = - ures_getUnicodeStringByKey(res.getAlias(), "replacement", &status); + const UChar* aliasTo = + ures_getStringByKey(res.getAlias(), "replacement", nullptr, &status); if (U_FAILURE(status)) return; checkType(aliasFrom); @@ -766,7 +766,7 @@ AliasDataBuilder::readLanguageAlias( #else [](const char*) {}, #endif - [](const UnicodeString&) {}, status); + [](const UChar*) {}, status); } /** @@ -790,12 +790,12 @@ AliasDataBuilder::readScriptAlias( [](const char* type) { U_ASSERT(uprv_strlen(type) == 4); }, - [](const UnicodeString& replacement) { - U_ASSERT(replacement.length() == 4); + [](const UChar* replacement) { + U_ASSERT(u_strlen(replacement) == 4); }, #else [](const char*) {}, - [](const UnicodeString&) { }, + [](const UChar*) { }, #endif status); } @@ -824,7 +824,7 @@ AliasDataBuilder::readTerritoryAlias( #else [](const char*) {}, #endif - [](const UnicodeString&) { }, + [](const UChar*) { }, status); } @@ -851,15 +851,16 @@ AliasDataBuilder::readVariantAlias( U_ASSERT(uprv_strlen(type) != 4 || (type[0] >= '0' && type[0] <= '9')); }, - [](const UnicodeString& replacement) { - U_ASSERT(replacement.length() >= 4 && replacement.length() <= 8); - U_ASSERT(replacement.length() != 4 || - (replacement.charAt(0) >= u'0' && - replacement.charAt(0) <= u'9')); + [](const UChar* replacement) { + int32_t len = u_strlen(replacement); + U_ASSERT(len >= 4 && len <= 8); + U_ASSERT(len != 4 || + (*replacement >= u'0' && + *replacement <= u'9')); }, #else [](const char*) {}, - [](const UnicodeString&) { }, + [](const UChar*) { }, #endif status); } @@ -888,7 +889,7 @@ AliasDataBuilder::readSubdivisionAlias( #else [](const char*) {}, #endif - [](const UnicodeString&) { }, + [](const UChar*) { }, status); } @@ -1066,7 +1067,13 @@ class AliasReplacer { public: AliasReplacer(UErrorCode status) : language(nullptr), script(nullptr), region(nullptr), - extensions(nullptr), variants(status), + extensions(nullptr), + // store value in variants only once + variants(nullptr, + ([](UElement e1, UElement e2) -> UBool { + return 0==uprv_strcmp((const char*)e1.pointer, + (const char*)e2.pointer);}), + status), data(nullptr) { } ~AliasReplacer() { @@ -1652,10 +1659,16 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status while ((end = uprv_strchr(start, SEP_CHAR)) != nullptr && U_SUCCESS(status)) { *end = NULL_CHAR; // null terminate inside variantsBuff - variants.addElement(start, status); + // do not add "" or duplicate data to variants + if (*start && !variants.contains(start)) { + variants.addElement(start, status); + } start = end + 1; } - variants.addElement(start, status); + // do not add "" or duplicate data to variants + if (*start && !variants.contains(start)) { + variants.addElement(start, status); + } } if (U_FAILURE(status)) { return false; } @@ -2079,6 +2092,10 @@ Locale::addLikelySubtags(UErrorCode& status) { void Locale::minimizeSubtags(UErrorCode& status) { + Locale::minimizeSubtags(false, status); +} +void +Locale::minimizeSubtags(bool favorScript, UErrorCode& status) { if (U_FAILURE(status)) { return; } @@ -2086,7 +2103,7 @@ Locale::minimizeSubtags(UErrorCode& status) { CharString minimizedLocaleID; { CharStringByteSink sink(&minimizedLocaleID); - ulocimp_minimizeSubtags(fullName, sink, &status); + ulocimp_minimizeSubtags(fullName, sink, favorScript, &status); } if (U_FAILURE(status)) { @@ -2402,8 +2419,9 @@ Locale::getLocaleCache() } class KeywordEnumeration : public StringEnumeration { -private: +protected: char *keywords; +private: char *current; int32_t length; UnicodeString currUSKey; @@ -2510,6 +2528,17 @@ public: if (resultLength != nullptr) *resultLength = 0; return nullptr; } + virtual int32_t count(UErrorCode &/*status*/) const override { + char *kw = keywords; + int32_t result = 0; + while(*kw) { + if (uloc_toUnicodeLocaleKey(kw) != nullptr) { + result++; + } + kw += uprv_strlen(kw)+1; + } + return result; + } }; // Out-of-line virtual destructor to serve as the "key function". diff --git a/thirdparty/icu4c/common/loclikely.cpp b/thirdparty/icu4c/common/loclikely.cpp index d2a05c6364..eedfb8149e 100644 --- a/thirdparty/icu4c/common/loclikely.cpp +++ b/thirdparty/icu4c/common/loclikely.cpp @@ -31,83 +31,11 @@ #include "charstr.h" #include "cmemory.h" #include "cstring.h" +#include "loclikelysubtags.h" #include "ulocimp.h" #include "ustr_imp.h" /** - * These are the canonical strings for unknown languages, scripts and regions. - **/ -static const char* const unknownLanguage = "und"; -static const char* const unknownScript = "Zzzz"; -static const char* const unknownRegion = "ZZ"; - -/** - * This function looks for the localeID in the likelySubtags resource. - * - * @param localeID The tag to find. - * @param buffer A buffer to hold the matching entry - * @param bufferLength The length of the output buffer - * @return A pointer to "buffer" if found, or a null pointer if not. - */ -static const char* U_CALLCONV -findLikelySubtags(const char* localeID, - char* buffer, - int32_t bufferLength, - UErrorCode* err) { - const char* result = nullptr; - - if (!U_FAILURE(*err)) { - int32_t resLen = 0; - const char16_t* s = nullptr; - UErrorCode tmpErr = U_ZERO_ERROR; - icu::LocalUResourceBundlePointer subtags(ures_openDirect(nullptr, "likelySubtags", &tmpErr)); - if (U_SUCCESS(tmpErr)) { - icu::CharString und; - if (localeID != nullptr) { - if (*localeID == '\0') { - localeID = unknownLanguage; - } else if (*localeID == '_') { - und.append(unknownLanguage, *err); - und.append(localeID, *err); - if (U_FAILURE(*err)) { - return nullptr; - } - localeID = und.data(); - } - } - s = ures_getStringByKey(subtags.getAlias(), localeID, &resLen, &tmpErr); - - if (U_FAILURE(tmpErr)) { - /* - * If a resource is missing, it's not really an error, it's - * just that we don't have any data for that particular locale ID. - */ - if (tmpErr != U_MISSING_RESOURCE_ERROR) { - *err = tmpErr; - } - } - else if (resLen >= bufferLength) { - /* The buffer should never overflow. */ - *err = U_INTERNAL_PROGRAM_ERROR; - } - else { - u_UCharsToChars(s, buffer, resLen + 1); - if (resLen >= 3 && - uprv_strnicmp(buffer, unknownLanguage, 3) == 0 && - (resLen == 3 || buffer[3] == '_')) { - uprv_memmove(buffer, buffer + 3, resLen - 3 + 1); - } - result = buffer; - } - } else { - *err = tmpErr; - } - } - - return result; -} - -/** * Append a tag to a buffer, adding the separator if necessary. The buffer * must be large enough to contain the resulting tag plus any separator * necessary. The tag must not be a zero-length string. @@ -361,57 +289,6 @@ error: } /** - * Create a tag string from the supplied parameters. The lang, script and region - * parameters may be nullptr pointers. If they are, their corresponding length parameters - * must be less than or equal to 0. If the lang parameter is an empty string, the - * default value for an unknown language is written to the output buffer. - * - * If the length of the new string exceeds the capacity of the output buffer, - * the function copies as many bytes to the output buffer as it can, and returns - * the error U_BUFFER_OVERFLOW_ERROR. - * - * If an illegal argument is provided, the function returns the error - * U_ILLEGAL_ARGUMENT_ERROR. - * - * @param lang The language tag to use. - * @param langLength The length of the language tag. - * @param script The script tag to use. - * @param scriptLength The length of the script tag. - * @param region The region tag to use. - * @param regionLength The length of the region tag. - * @param trailing Any trailing data to append to the new tag. - * @param trailingLength The length of the trailing data. - * @param sink The output sink receiving the tag string. - * @param err A pointer to a UErrorCode for error reporting. - **/ -static void U_CALLCONV -createTagString( - const char* lang, - int32_t langLength, - const char* script, - int32_t scriptLength, - const char* region, - int32_t regionLength, - const char* trailing, - int32_t trailingLength, - icu::ByteSink& sink, - UErrorCode* err) -{ - createTagStringWithAlternates( - lang, - langLength, - script, - scriptLength, - region, - regionLength, - trailing, - trailingLength, - nullptr, - sink, - err); -} - -/** * Parse the language, script, and region subtags from a tag string, and copy the * results into the corresponding output parameters. The buffers are null-terminated, * unless overflow occurs. @@ -494,13 +371,6 @@ parseTagString( *scriptLength = subtagLength; if (*scriptLength > 0) { - if (uprv_strnicmp(script, unknownScript, *scriptLength) == 0) { - /** - * If the script part is the "unknown" script, then don't return it. - **/ - *scriptLength = 0; - } - /* * Move past any separator. */ @@ -517,14 +387,7 @@ parseTagString( *regionLength = subtagLength; - if (*regionLength > 0) { - if (uprv_strnicmp(region, unknownRegion, *regionLength) == 0) { - /** - * If the region part is the "unknown" region, then don't return it. - **/ - *regionLength = 0; - } - } else if (*position != 0 && *position != '@') { + if (*regionLength <= 0 && *position != 0 && *position != '@') { /* back up over consumed trailing separator */ --position; } @@ -546,264 +409,6 @@ error: goto exit; } -static UBool U_CALLCONV -createLikelySubtagsString( - const char* lang, - int32_t langLength, - const char* script, - int32_t scriptLength, - const char* region, - int32_t regionLength, - const char* variants, - int32_t variantsLength, - icu::ByteSink& sink, - UErrorCode* err) { - /** - * ULOC_FULLNAME_CAPACITY will provide enough capacity - * that we can build a string that contains the language, - * script and region code without worrying about overrunning - * the user-supplied buffer. - **/ - char likelySubtagsBuffer[ULOC_FULLNAME_CAPACITY]; - - if(U_FAILURE(*err)) { - goto error; - } - - /** - * Try the language with the script and region first. - **/ - if (scriptLength > 0 && regionLength > 0) { - - const char* likelySubtags = nullptr; - - icu::CharString tagBuffer; - { - icu::CharStringByteSink sink(&tagBuffer); - createTagString( - lang, - langLength, - script, - scriptLength, - region, - regionLength, - nullptr, - 0, - sink, - err); - } - if(U_FAILURE(*err)) { - goto error; - } - - likelySubtags = - findLikelySubtags( - tagBuffer.data(), - likelySubtagsBuffer, - sizeof(likelySubtagsBuffer), - err); - if(U_FAILURE(*err)) { - goto error; - } - - if (likelySubtags != nullptr) { - /* Always use the language tag from the - maximal string, since it may be more - specific than the one provided. */ - createTagStringWithAlternates( - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - variants, - variantsLength, - likelySubtags, - sink, - err); - return true; - } - } - - /** - * Try the language with just the script. - **/ - if (scriptLength > 0) { - - const char* likelySubtags = nullptr; - - icu::CharString tagBuffer; - { - icu::CharStringByteSink sink(&tagBuffer); - createTagString( - lang, - langLength, - script, - scriptLength, - nullptr, - 0, - nullptr, - 0, - sink, - err); - } - if(U_FAILURE(*err)) { - goto error; - } - - likelySubtags = - findLikelySubtags( - tagBuffer.data(), - likelySubtagsBuffer, - sizeof(likelySubtagsBuffer), - err); - if(U_FAILURE(*err)) { - goto error; - } - - if (likelySubtags != nullptr) { - /* Always use the language tag from the - maximal string, since it may be more - specific than the one provided. */ - createTagStringWithAlternates( - nullptr, - 0, - nullptr, - 0, - region, - regionLength, - variants, - variantsLength, - likelySubtags, - sink, - err); - return true; - } - } - - /** - * Try the language with just the region. - **/ - if (regionLength > 0) { - - const char* likelySubtags = nullptr; - - icu::CharString tagBuffer; - { - icu::CharStringByteSink sink(&tagBuffer); - createTagString( - lang, - langLength, - nullptr, - 0, - region, - regionLength, - nullptr, - 0, - sink, - err); - } - if(U_FAILURE(*err)) { - goto error; - } - - likelySubtags = - findLikelySubtags( - tagBuffer.data(), - likelySubtagsBuffer, - sizeof(likelySubtagsBuffer), - err); - if(U_FAILURE(*err)) { - goto error; - } - - if (likelySubtags != nullptr) { - /* Always use the language tag from the - maximal string, since it may be more - specific than the one provided. */ - createTagStringWithAlternates( - nullptr, - 0, - script, - scriptLength, - nullptr, - 0, - variants, - variantsLength, - likelySubtags, - sink, - err); - return true; - } - } - - /** - * Finally, try just the language. - **/ - { - const char* likelySubtags = nullptr; - - icu::CharString tagBuffer; - { - icu::CharStringByteSink sink(&tagBuffer); - createTagString( - lang, - langLength, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - sink, - err); - } - if(U_FAILURE(*err)) { - goto error; - } - - likelySubtags = - findLikelySubtags( - tagBuffer.data(), - likelySubtagsBuffer, - sizeof(likelySubtagsBuffer), - err); - if(U_FAILURE(*err)) { - goto error; - } - - if (likelySubtags != nullptr) { - /* Always use the language tag from the - maximal string, since it may be more - specific than the one provided. */ - createTagStringWithAlternates( - nullptr, - 0, - script, - scriptLength, - region, - regionLength, - variants, - variantsLength, - likelySubtags, - sink, - err); - return true; - } - } - - return false; - -error: - - if (!U_FAILURE(*err)) { - *err = U_ILLEGAL_ARGUMENT_ERROR; - } - - return false; -} - #define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) UPRV_BLOCK_MACRO_BEGIN { \ int32_t count = 0; \ int32_t i; \ @@ -836,7 +441,6 @@ _uloc_addLikelySubtags(const char* localeID, const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; - UBool success = false; if(U_FAILURE(*err)) { goto error; @@ -862,6 +466,9 @@ _uloc_addLikelySubtags(const char* localeID, goto error; } + if (langLength > 3) { + goto error; + } /* Find the length of the trailing portion. */ while (_isIDSeparator(localeID[trailingIndex])) { @@ -871,30 +478,42 @@ _uloc_addLikelySubtags(const char* localeID, trailingLength = (int32_t)uprv_strlen(trailing); CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); - - success = - createLikelySubtagsString( - lang, - langLength, - script, - scriptLength, - region, - regionLength, + { + const icu::XLikelySubtags* likelySubtags = icu::XLikelySubtags::getSingleton(*err); + if(U_FAILURE(*err)) { + goto error; + } + // We need to keep l on the stack because lsr may point into internal + // memory of l. + icu::Locale l = icu::Locale::createFromName(localeID); + if (l.isBogus()) { + goto error; + } + icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(l, true, *err); + if(U_FAILURE(*err)) { + goto error; + } + const char* language = lsr.language; + if (uprv_strcmp(language, "und") == 0) { + language = ""; + } + createTagStringWithAlternates( + language, + (int32_t)uprv_strlen(language), + lsr.script, + (int32_t)uprv_strlen(lsr.script), + lsr.region, + (int32_t)uprv_strlen(lsr.region), trailing, trailingLength, + nullptr, sink, err); - - if (!success) { - const int32_t localIDLength = (int32_t)uprv_strlen(localeID); - - /* - * If we get here, we need to return localeID. - */ - sink.Append(localeID, localIDLength); + if(U_FAILURE(*err)) { + goto error; + } } - - return success; + return true; error: @@ -913,6 +532,7 @@ static UBool _ulocimp_addLikelySubtags(const char*, icu::ByteSink&, UErrorCode*) static void _uloc_minimizeSubtags(const char* localeID, icu::ByteSink& sink, + bool favorScript, UErrorCode* err) { icu::CharString maximizedTagBuffer; @@ -925,7 +545,6 @@ _uloc_minimizeSubtags(const char* localeID, const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; - UBool successGetMax = false; if(U_FAILURE(*err)) { goto error; @@ -964,213 +583,38 @@ _uloc_minimizeSubtags(const char* localeID, CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); { - icu::CharString base; - { - icu::CharStringByteSink baseSink(&base); - createTagString( - lang, - langLength, - script, - scriptLength, - region, - regionLength, - nullptr, - 0, - baseSink, - err); - } - - /** - * First, we need to first get the maximization - * from AddLikelySubtags. - **/ - { - icu::CharStringByteSink maxSink(&maximizedTagBuffer); - successGetMax = _ulocimp_addLikelySubtags(base.data(), maxSink, err); - } - } - - if(U_FAILURE(*err)) { - goto error; - } - - if (!successGetMax) { - /** - * If we got here, return the locale ID parameter unchanged. - **/ - const int32_t localeIDLength = (int32_t)uprv_strlen(localeID); - sink.Append(localeID, localeIDLength); - return; - } - - // In the following, the lang, script, region are referring to those in - // the maximizedTagBuffer, not the one in the localeID. - langLength = sizeof(lang); - scriptLength = sizeof(script); - regionLength = sizeof(region); - parseTagString( - maximizedTagBuffer.data(), - lang, - &langLength, - script, - &scriptLength, - region, - ®ionLength, - err); - if(U_FAILURE(*err)) { - goto error; - } - - /** - * Start first with just the language. - **/ - { - icu::CharString tagBuffer; - { - icu::CharStringByteSink tagSink(&tagBuffer); - createLikelySubtagsString( - lang, - langLength, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, - tagSink, - err); - } - + const icu::XLikelySubtags* likelySubtags = icu::XLikelySubtags::getSingleton(*err); if(U_FAILURE(*err)) { goto error; } - else if (!tagBuffer.isEmpty() && - uprv_strnicmp( - maximizedTagBuffer.data(), - tagBuffer.data(), - tagBuffer.length()) == 0) { - - createTagString( - lang, - langLength, - nullptr, - 0, - nullptr, - 0, - trailing, - trailingLength, - sink, - err); - return; - } - } - - /** - * Next, try the language and region. - **/ - if (regionLength > 0) { - - icu::CharString tagBuffer; - { - icu::CharStringByteSink tagSink(&tagBuffer); - createLikelySubtagsString( - lang, - langLength, - nullptr, - 0, - region, - regionLength, - nullptr, - 0, - tagSink, - err); - } - + icu::LSR lsr = likelySubtags->minimizeSubtags( + {lang, langLength}, + {script, scriptLength}, + {region, regionLength}, + favorScript, + *err); if(U_FAILURE(*err)) { goto error; } - else if (!tagBuffer.isEmpty() && - uprv_strnicmp( - maximizedTagBuffer.data(), - tagBuffer.data(), - tagBuffer.length()) == 0) { - - createTagString( - lang, - langLength, - nullptr, - 0, - region, - regionLength, - trailing, - trailingLength, - sink, - err); - return; - } - } - - /** - * Finally, try the language and script. This is our last chance, - * since trying with all three subtags would only yield the - * maximal version that we already have. - **/ - if (scriptLength > 0) { - icu::CharString tagBuffer; - { - icu::CharStringByteSink tagSink(&tagBuffer); - createLikelySubtagsString( - lang, - langLength, - script, - scriptLength, - nullptr, - 0, - nullptr, - 0, - tagSink, - err); - } - + const char* language = lsr.language; + if (uprv_strcmp(language, "und") == 0) { + language = ""; + } + createTagStringWithAlternates( + language, + (int32_t)uprv_strlen(language), + lsr.script, + (int32_t)uprv_strlen(lsr.script), + lsr.region, + (int32_t)uprv_strlen(lsr.region), + trailing, + trailingLength, + nullptr, + sink, + err); if(U_FAILURE(*err)) { goto error; } - else if (!tagBuffer.isEmpty() && - uprv_strnicmp( - maximizedTagBuffer.data(), - tagBuffer.data(), - tagBuffer.length()) == 0) { - - createTagString( - lang, - langLength, - script, - scriptLength, - nullptr, - 0, - trailing, - trailingLength, - sink, - err); - return; - } - } - - { - /** - * If we got here, return the max + trail. - **/ - createTagString( - lang, - langLength, - script, - scriptLength, - region, - regionLength, - trailing, - trailingLength, - sink, - err); return; } @@ -1181,31 +625,6 @@ error: } } -static int32_t -do_canonicalize(const char* localeID, - char* buffer, - int32_t bufferCapacity, - UErrorCode* err) -{ - int32_t canonicalizedSize = uloc_canonicalize( - localeID, - buffer, - bufferCapacity, - err); - - if (*err == U_STRING_NOT_TERMINATED_WARNING || - *err == U_BUFFER_OVERFLOW_ERROR) { - return canonicalizedSize; - } - else if (U_FAILURE(*err)) { - - return -1; - } - else { - return canonicalizedSize; - } -} - U_CAPI int32_t U_EXPORT2 uloc_addLikelySubtags(const char* localeID, char* maximizedLocaleID, @@ -1239,14 +658,13 @@ static UBool _ulocimp_addLikelySubtags(const char* localeID, icu::ByteSink& sink, UErrorCode* status) { - PreflightingLocaleIDBuffer localeBuffer; - do { - localeBuffer.requestedCapacity = do_canonicalize(localeID, localeBuffer.getBuffer(), - localeBuffer.getCapacity(), status); - } while (localeBuffer.needToTryAgain(status)); - + icu::CharString localeBuffer; + { + icu::CharStringByteSink localeSink(&localeBuffer); + ulocimp_canonicalize(localeID, localeSink, status); + } if (U_SUCCESS(*status)) { - return _uloc_addLikelySubtags(localeBuffer.getBuffer(), sink, status); + return _uloc_addLikelySubtags(localeBuffer.data(), sink, status); } else { return false; } @@ -1271,7 +689,7 @@ uloc_minimizeSubtags(const char* localeID, icu::CheckedArrayByteSink sink( minimizedLocaleID, minimizedLocaleIDCapacity); - ulocimp_minimizeSubtags(localeID, sink, status); + ulocimp_minimizeSubtags(localeID, sink, false, status); int32_t reslen = sink.NumberOfBytesAppended(); if (U_FAILURE(*status)) { @@ -1291,14 +709,14 @@ uloc_minimizeSubtags(const char* localeID, U_CAPI void U_EXPORT2 ulocimp_minimizeSubtags(const char* localeID, icu::ByteSink& sink, + bool favorScript, UErrorCode* status) { - PreflightingLocaleIDBuffer localeBuffer; - do { - localeBuffer.requestedCapacity = do_canonicalize(localeID, localeBuffer.getBuffer(), - localeBuffer.getCapacity(), status); - } while (localeBuffer.needToTryAgain(status)); - - _uloc_minimizeSubtags(localeBuffer.getBuffer(), sink, status); + icu::CharString localeBuffer; + { + icu::CharStringByteSink localeSink(&localeBuffer); + ulocimp_canonicalize(localeID, localeSink, status); + } + _uloc_minimizeSubtags(localeBuffer.data(), sink, favorScript, status); } // Pairs of (language subtag, + or -) for finding out fast if common languages @@ -1374,16 +792,26 @@ ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion, UErrorCode rgStatus = U_ZERO_ERROR; // First check for rg keyword value - int32_t rgLen = uloc_getKeywordValue(localeID, "rg", rgBuf, ULOC_RG_BUFLEN, &rgStatus); - if (U_FAILURE(rgStatus) || rgLen != 6) { + icu::CharString rg; + { + icu::CharStringByteSink sink(&rg); + ulocimp_getKeywordValue(localeID, "rg", sink, &rgStatus); + } + int32_t rgLen = rg.length(); + if (U_FAILURE(rgStatus) || rgLen < 3 || rgLen > 7) { rgLen = 0; } else { - // rgBuf guaranteed to be zero terminated here, with text len 6 - char *rgPtr = rgBuf; - for (; *rgPtr!= 0; rgPtr++) { - *rgPtr = uprv_toupper(*rgPtr); + // chop off the subdivision code (which will generally be "zzzz" anyway) + const char* const data = rg.data(); + if (uprv_isASCIILetter(data[0])) { + rgLen = 2; + rgBuf[0] = uprv_toupper(data[0]); + rgBuf[1] = uprv_toupper(data[1]); + } else { + // assume three-digit region code + rgLen = 3; + uprv_memcpy(rgBuf, data, rgLen); } - rgLen = (uprv_strcmp(rgBuf+2, "ZZZZ") == 0)? 2: 0; } if (rgLen == 0) { diff --git a/thirdparty/icu4c/common/loclikelysubtags.cpp b/thirdparty/icu4c/common/loclikelysubtags.cpp index e913c66a35..c2a7011b50 100644 --- a/thirdparty/icu4c/common/loclikelysubtags.cpp +++ b/thirdparty/icu4c/common/loclikelysubtags.cpp @@ -11,6 +11,7 @@ #include "unicode/locid.h" #include "unicode/uobject.h" #include "unicode/ures.h" +#include "unicode/uscript.h" #include "charstr.h" #include "cstring.h" #include "loclikelysubtags.h" @@ -23,6 +24,7 @@ #include "uniquecharstr.h" #include "uresdata.h" #include "uresimp.h" +#include "uvector.h" U_NAMESPACE_BEGIN @@ -81,11 +83,18 @@ struct XLikelySubtagsData { // Read all strings in the resource bundle and convert them to invariant char *. LocalMemory<int32_t> languageIndexes, regionIndexes, lsrSubtagIndexes; int32_t languagesLength = 0, regionsLength = 0, lsrSubtagsLength = 0; + ResourceArray m49Array; + if (likelyTable.findValue("m49", value)) { + m49Array = value.getArray(errorCode); + } else { + errorCode = U_MISSING_RESOURCE_ERROR; + return; + } if (!readStrings(likelyTable, "languageAliases", value, languageIndexes, languagesLength, errorCode) || !readStrings(likelyTable, "regionAliases", value, regionIndexes, regionsLength, errorCode) || - !readStrings(likelyTable, "lsrs", value, + !readLSREncodedStrings(likelyTable, "lsrnum", value, m49Array, lsrSubtagIndexes,lsrSubtagsLength, errorCode)) { return; } @@ -136,7 +145,7 @@ struct XLikelySubtagsData { if (!readStrings(matchTable, "partitions", value, partitionIndexes, partitionsLength, errorCode) || - !readStrings(matchTable, "paradigms", value, + !readLSREncodedStrings(matchTable, "paradigmnum", value, m49Array, paradigmSubtagIndexes, paradigmSubtagsLength, errorCode)) { return; } @@ -233,10 +242,96 @@ private: return false; } for (int i = 0; i < length; ++i) { - stringArray.getValue(i, value); // returns true because i < length - rawIndexes[i] = strings.add(value.getUnicodeString(errorCode), errorCode); + if (stringArray.getValue(i, value)) { // returns true because i < length + int32_t strLength = 0; + rawIndexes[i] = strings.add(value.getString(strLength, errorCode), errorCode); + if (U_FAILURE(errorCode)) { return false; } + } + } + } + return true; + } + UnicodeString toLanguage(int encoded) { + if (encoded == 0) { + return UNICODE_STRING_SIMPLE(""); + } + if (encoded == 1) { + return UNICODE_STRING_SIMPLE("skip"); + } + encoded &= 0x00ffffff; + encoded %= 27*27*27; + char lang[3]; + lang[0] = 'a' + ((encoded % 27) - 1); + lang[1] = 'a' + (((encoded / 27 ) % 27) - 1); + if (encoded / (27 * 27) == 0) { + return UnicodeString(lang, 2, US_INV); + } + lang[2] = 'a' + ((encoded / (27 * 27)) - 1); + return UnicodeString(lang, 3, US_INV); + } + UnicodeString toScript(int encoded) { + if (encoded == 0) { + return UNICODE_STRING_SIMPLE(""); + } + if (encoded == 1) { + return UNICODE_STRING_SIMPLE("script"); + } + encoded = (encoded >> 24) & 0x000000ff; + const char* script = uscript_getShortName(static_cast<UScriptCode>(encoded)); + if (script == nullptr) { + return UNICODE_STRING_SIMPLE(""); + } + U_ASSERT(uprv_strlen(script) == 4); + return UnicodeString(script, 4, US_INV); + } + UnicodeString m49IndexToCode(const ResourceArray &m49Array, ResourceValue &value, int index, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { + return UNICODE_STRING_SIMPLE(""); + } + if (m49Array.getValue(index, value)) { + return value.getUnicodeString(errorCode); + } + // "m49" does not include the index. + errorCode = U_MISSING_RESOURCE_ERROR; + return UNICODE_STRING_SIMPLE(""); + } + + UnicodeString toRegion(const ResourceArray& m49Array, ResourceValue &value, int encoded, UErrorCode &errorCode) { + if (encoded == 0 || encoded == 1) { + return UNICODE_STRING_SIMPLE(""); + } + encoded &= 0x00ffffff; + encoded /= 27 * 27 * 27; + encoded %= 27 * 27; + if (encoded < 27) { + // Selected M49 code index, find the code from "m49" resource. + return m49IndexToCode(m49Array, value, encoded, errorCode); + } + char region[2]; + region[0] = 'A' + ((encoded % 27) - 1); + region[1] = 'A' + (((encoded / 27) % 27) - 1); + return UnicodeString(region, 2, US_INV); + } + + bool readLSREncodedStrings(const ResourceTable &table, const char* key, ResourceValue &value, const ResourceArray& m49Array, + LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) { + if (table.findValue(key, value)) { + const int32_t* vectors = value.getIntVector(length, errorCode); + if (U_FAILURE(errorCode)) { return false; } + if (length == 0) { return true; } + int32_t *rawIndexes = indexes.allocateInsteadAndCopy(length * 3); + if (rawIndexes == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return false; + } + for (int i = 0; i < length; ++i) { + rawIndexes[i*3] = strings.addByValue(toLanguage(vectors[i]), errorCode); + rawIndexes[i*3+1] = strings.addByValue(toScript(vectors[i]), errorCode); + rawIndexes[i*3+2] = strings.addByValue( + toRegion(m49Array, value, vectors[i], errorCode), errorCode); if (U_FAILURE(errorCode)) { return false; } } + length *= 3; } return true; } @@ -245,15 +340,52 @@ private: namespace { XLikelySubtags *gLikelySubtags = nullptr; +UVector *gMacroregions = nullptr; UInitOnce gInitOnce {}; UBool U_CALLCONV cleanup() { delete gLikelySubtags; gLikelySubtags = nullptr; + delete gMacroregions; + gMacroregions = nullptr; gInitOnce.reset(); return true; } +static const char16_t RANGE_MARKER = 0x7E; /* '~' */ +UVector* loadMacroregions(UErrorCode &status) { + LocalPointer<UVector> newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); + + LocalUResourceBundlePointer supplementalData(ures_openDirect(nullptr,"supplementalData",&status)); + LocalUResourceBundlePointer idValidity(ures_getByKey(supplementalData.getAlias(),"idValidity",nullptr,&status)); + LocalUResourceBundlePointer regionList(ures_getByKey(idValidity.getAlias(),"region",nullptr,&status)); + LocalUResourceBundlePointer regionMacro(ures_getByKey(regionList.getAlias(),"macroregion",nullptr,&status)); + + if (U_FAILURE(status)) { + return nullptr; + } + + while (U_SUCCESS(status) && ures_hasNext(regionMacro.getAlias())) { + UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),nullptr,&status); + int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); + char16_t buf[6]; + regionName.extract(buf,6,status); + if ( rangeMarkerLocation > 0 ) { + char16_t endRange = regionName.charAt(rangeMarkerLocation+1); + buf[rangeMarkerLocation] = 0; + while ( buf[rangeMarkerLocation-1] <= endRange && U_SUCCESS(status)) { + LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status); + newMacroRegions->adoptElement(newRegion.orphan(),status); + buf[rangeMarkerLocation-1]++; + } + } else { + LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status); + newMacroRegions->adoptElement(newRegion.orphan(),status); + } + } + return newMacroRegions.orphan(); +} + } // namespace void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) { @@ -263,10 +395,14 @@ void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) { data.load(errorCode); if (U_FAILURE(errorCode)) { return; } gLikelySubtags = new XLikelySubtags(data); - if (gLikelySubtags == nullptr) { + gMacroregions = loadMacroregions(errorCode); + if (U_FAILURE(errorCode) || gLikelySubtags == nullptr || gMacroregions == nullptr) { + delete gLikelySubtags; + delete gMacroregions; errorCode = U_MEMORY_ALLOCATION_ERROR; return; } + ucln_common_registerCleanup(UCLN_COMMON_LIKELY_SUBTAGS, cleanup); } @@ -317,15 +453,32 @@ XLikelySubtags::~XLikelySubtags() { delete[] lsrs; } -LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const { +LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const { + if (locale.isBogus()) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return LSR("", "", "", LSR::EXPLICIT_LSR); + } const char *name = locale.getName(); if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=") // Private use language tag x-subtag-subtag... which CLDR changes to // und-x-subtag-subtag... return LSR(name, "", "", LSR::EXPLICIT_LSR); } - return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), - locale.getVariant(), errorCode); + LSR max = makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), + locale.getVariant(), returnInputIfUnmatch, errorCode); + + if (uprv_strlen(max.language) == 0 && + uprv_strlen(max.script) == 0 && + uprv_strlen(max.region) == 0) { + // No match. ICU API mandate us to + // If the provided ULocale instance is already in the maximal form, or + // there is no data available available for maximization, it will be + // returned. + return LSR(locale.getLanguage(), locale.getScript(), locale.getCountry(), LSR::EXPLICIT_LSR, errorCode); + } + return max; } namespace { @@ -338,7 +491,9 @@ const char *getCanonical(const CharStringMap &aliases, const char *alias) { } // namespace LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, const char *region, - const char *variant, UErrorCode &errorCode) const { + const char *variant, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const { // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK. // They should match only themselves, // not other locales with what looks like the same language and script subtags. @@ -378,64 +533,91 @@ LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, c language = getCanonical(languageAliases, language); // (We have no script mappings.) region = getCanonical(regionAliases, region); - return maximize(language, script, region); + return maximize(language, script, region, returnInputIfUnmatch, errorCode); } -LSR XLikelySubtags::maximize(const char *language, const char *script, const char *region) const { - if (uprv_strcmp(language, "und") == 0) { +LSR XLikelySubtags::maximize(const char *language, const char *script, const char *region, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const { + return maximize({language, (int32_t)uprv_strlen(language)}, + {script, (int32_t)uprv_strlen(script)}, + {region, (int32_t)uprv_strlen(region)}, + returnInputIfUnmatch, + errorCode); +} + +bool XLikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) const { + // In Java, we use Region class. In C++, since Region is under i18n, + // we read the same data used by Region into gMacroregions avoid dependency + // from common to i18n/region.cpp + if (U_FAILURE(errorCode)) { return false; } + umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode); + if (U_FAILURE(errorCode)) { return false; } + UnicodeString str(UnicodeString::fromUTF8(region)); + return gMacroregions->contains((void *)&str); +} + +LSR XLikelySubtags::maximize(StringPiece language, StringPiece script, StringPiece region, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { + return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode); + } + if (language.compare("und") == 0) { language = ""; } - if (uprv_strcmp(script, "Zzzz") == 0) { + if (script.compare("Zzzz") == 0) { script = ""; } - if (uprv_strcmp(region, "ZZ") == 0) { + if (region.compare("ZZ") == 0) { region = ""; } - if (*script != 0 && *region != 0 && *language != 0) { - return LSR(language, script, region, LSR::EXPLICIT_LSR); // already maximized + if (!script.empty() && !region.empty() && !language.empty()) { + return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode); // already maximized } + bool retainLanguage = false; + bool retainScript = false; + bool retainRegion = false; - uint32_t retainOldMask = 0; BytesTrie iter(trie); uint64_t state; int32_t value; // Small optimization: Array lookup for first language letter. int32_t c0; - if (0 <= (c0 = uprv_lowerOrdinal(language[0])) && c0 <= 25 && - language[1] != 0 && // language.length() >= 2 + if (0 <= (c0 = uprv_lowerOrdinal(language.data()[0])) && c0 <= 25 && + language.length() >= 2 && (state = trieFirstLetterStates[c0]) != 0) { value = trieNext(iter.resetToState64(state), language, 1); } else { value = trieNext(iter, language, 0); } + bool matchLanguage = (value >= 0); + bool matchScript = false; if (value >= 0) { - if (*language != 0) { - retainOldMask |= 4; - } + retainLanguage = !language.empty(); state = iter.getState64(); } else { - retainOldMask |= 4; + retainLanguage = true; iter.resetToState64(trieUndState); // "und" ("*") state = 0; } + if (value >= 0 && !script.empty()) { + matchScript = true; + } if (value > 0) { // Intermediate or final value from just language. if (value == SKIP_SCRIPT) { value = 0; } - if (*script != 0) { - retainOldMask |= 2; - } + retainScript = !script.empty(); } else { value = trieNext(iter, script, 0); if (value >= 0) { - if (*script != 0) { - retainOldMask |= 2; - } + retainScript = !script.empty(); state = iter.getState64(); } else { - retainOldMask |= 2; + retainScript = true; if (state == 0) { iter.resetToState64(trieUndZzzzState); // "und-Zzzz" ("**") } else { @@ -447,19 +629,19 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha } } + bool matchRegion = false; if (value > 0) { // Final value from just language or language+script. - if (*region != 0) { - retainOldMask |= 1; - } + retainRegion = !region.empty(); } else { value = trieNext(iter, region, 0); if (value >= 0) { - if (*region != 0) { - retainOldMask |= 1; + if (!region.empty() && !isMacroregion(region, errorCode)) { + retainRegion = true; + matchRegion = true; } } else { - retainOldMask |= 1; + retainRegion = true; if (state == 0) { value = defaultLsrIndex; } else { @@ -470,28 +652,33 @@ LSR XLikelySubtags::maximize(const char *language, const char *script, const cha } } U_ASSERT(value < lsrsLength); - const LSR &result = lsrs[value]; + const LSR &matched = lsrs[value]; - if (*language == 0) { - language = "und"; + if (returnInputIfUnmatch && + (!(matchLanguage || matchScript || (matchRegion && language.empty())))) { + return LSR("", "", "", LSR::EXPLICIT_LSR, errorCode); // no matching. + } + if (language.empty()) { + language = StringPiece("und"); } - if (retainOldMask == 0) { + if (!(retainLanguage || retainScript || retainRegion)) { // Quickly return a copy of the lookup-result LSR // without new allocation of the subtags. - return LSR(result.language, result.script, result.region, result.flags); + return LSR(matched.language, matched.script, matched.region, matched.flags); } - if ((retainOldMask & 4) == 0) { - language = result.language; + if (!retainLanguage) { + language = matched.language; } - if ((retainOldMask & 2) == 0) { - script = result.script; + if (!retainScript) { + script = matched.script; } - if ((retainOldMask & 1) == 0) { - region = result.region; + if (!retainRegion) { + region = matched.region; } + int32_t retainMask = (retainLanguage ? 4 : 0) + (retainScript ? 2 : 0) + (retainRegion ? 1 : 0); // retainOldMask flags = LSR explicit-subtag flags - return LSR(language, script, region, retainOldMask); + return LSR(language, script, region, retainMask, errorCode); } int32_t XLikelySubtags::compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const { @@ -627,57 +814,97 @@ int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) { default: return -1; } } +int32_t XLikelySubtags::trieNext(BytesTrie &iter, StringPiece s, int32_t i) { + UStringTrieResult result; + uint8_t c; + if (s.length() == i) { + result = iter.next(u'*'); + } else { + c = s.data()[i]; + for (;;) { + c = uprv_invCharToAscii(c); + // EBCDIC: If s[i] is not an invariant character, + // then c is now 0 and will simply not match anything, which is harmless. + if (i+1 != s.length()) { + if (!USTRINGTRIE_HAS_NEXT(iter.next(c))) { + return -1; + } + c = s.data()[++i]; + } else { + // last character of this subtag + result = iter.next(c | 0x80); + break; + } + } + } + switch (result) { + case USTRINGTRIE_NO_MATCH: return -1; + case USTRINGTRIE_NO_VALUE: return 0; + case USTRINGTRIE_INTERMEDIATE_VALUE: + U_ASSERT(iter.getValue() == SKIP_SCRIPT); + return SKIP_SCRIPT; + case USTRINGTRIE_FINAL_VALUE: return iter.getValue(); + default: return -1; + } +} -// TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code -// in loclikely.cpp to this new code, including activating this -// minimizeSubtags() function. The LocaleMatcher does not minimize. -#if 0 -LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn, - const char *regionIn, ULocale.Minimize fieldToFavor, +LSR XLikelySubtags::minimizeSubtags(StringPiece language, StringPiece script, + StringPiece region, + bool favorScript, UErrorCode &errorCode) const { - LSR result = maximize(languageIn, scriptIn, regionIn); - - // We could try just a series of checks, like: - // LSR result2 = addLikelySubtags(languageIn, "", ""); - // if result.equals(result2) return result2; - // However, we can optimize 2 of the cases: - // (languageIn, "", "") - // (languageIn, "", regionIn) - - // value00 = lookup(result.language, "", "") - BytesTrie iter = new BytesTrie(trie); - int value = trieNext(iter, result.language, 0); - U_ASSERT(value >= 0); - if (value == 0) { - value = trieNext(iter, "", 0); - U_ASSERT(value >= 0); - if (value == 0) { - value = trieNext(iter, "", 0); - } - } - U_ASSERT(value > 0); - LSR value00 = lsrs[value]; - boolean favorRegionOk = false; - if (result.script.equals(value00.script)) { //script is default - if (result.region.equals(value00.region)) { - return new LSR(result.language, "", "", LSR.DONT_CARE_FLAGS); - } else if (fieldToFavor == ULocale.Minimize.FAVOR_REGION) { - return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); - } else { - favorRegionOk = true; + LSR max = maximize(language, script, region, true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + // If no match, return it. + if (uprv_strlen(max.language) == 0 && + uprv_strlen(max.script) == 0 && + uprv_strlen(max.region) == 0) { + // No match. ICU API mandate us to + // "If this Locale is already in the minimal form, or not valid, or + // there is no data available for minimization, the Locale will be + // unchanged." + return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode); + } + // try language + LSR test = maximize(max.language, "", "", true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + if (test.isEquivalentTo(max)) { + return LSR(max.language, "", "", LSR::DONT_CARE_FLAGS, errorCode); + } + + if (!favorScript) { + // favor Region + // try language and region + test = maximize(max.language, "", max.region, true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + if (test.isEquivalentTo(max)) { + return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode); } } - - // The last case is not as easy to optimize. - // Maybe do later, but for now use the straightforward code. - LSR result2 = maximize(languageIn, scriptIn, ""); - if (result2.equals(result)) { - return new LSR(result.language, result.script, "", LSR.DONT_CARE_FLAGS); - } else if (favorRegionOk) { - return new LSR(result.language, "", result.region, LSR.DONT_CARE_FLAGS); + // try language and script + test = maximize(max.language, max.script, "", true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + if (test.isEquivalentTo(max)) { + return LSR(max.language, max.script, "", LSR::DONT_CARE_FLAGS, errorCode); + } + if (favorScript) { + // try language and region + test = maximize(max.language, "", max.region, true, errorCode); + if (U_FAILURE(errorCode)) { + return max; + } + if (test.isEquivalentTo(max)) { + return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode); + } } - return result; + return LSR(max.language, max.script, max.region, LSR::DONT_CARE_FLAGS, errorCode); } -#endif U_NAMESPACE_END diff --git a/thirdparty/icu4c/common/loclikelysubtags.h b/thirdparty/icu4c/common/loclikelysubtags.h index 14a01a5eac..ebd9c15306 100644 --- a/thirdparty/icu4c/common/loclikelysubtags.h +++ b/thirdparty/icu4c/common/loclikelysubtags.h @@ -11,6 +11,7 @@ #include "unicode/utypes.h" #include "unicode/bytestrie.h" #include "unicode/locid.h" +#include "unicode/stringpiece.h" #include "unicode/uobject.h" #include "unicode/ures.h" #include "charstrmap.h" @@ -47,7 +48,9 @@ public: static const XLikelySubtags *getSingleton(UErrorCode &errorCode); // VisibleForTesting - LSR makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const; + LSR makeMaximizedLsrFrom(const Locale &locale, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const; /** * Tests whether lsr is "more likely" than other. @@ -61,13 +64,9 @@ public: */ int32_t compareLikely(const LSR &lsr, const LSR &other, int32_t likelyInfo) const; - // TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code - // in loclikely.cpp to this new code, including activating this - // minimizeSubtags() function. The LocaleMatcher does not minimize. -#if 0 - LSR minimizeSubtags(const char *languageIn, const char *scriptIn, const char *regionIn, - ULocale.Minimize fieldToFavor, UErrorCode &errorCode) const; -#endif + LSR minimizeSubtags(StringPiece language, StringPiece script, StringPiece region, + bool favorScript, + UErrorCode &errorCode) const; // visible for LocaleDistance const LocaleDistanceData &getDistanceData() const { return distanceData; } @@ -80,16 +79,25 @@ private: static void initLikelySubtags(UErrorCode &errorCode); LSR makeMaximizedLsr(const char *language, const char *script, const char *region, - const char *variant, UErrorCode &errorCode) const; + const char *variant, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const; /** * Raw access to addLikelySubtags. Input must be in canonical format, eg "en", not "eng" or "EN". */ - LSR maximize(const char *language, const char *script, const char *region) const; + LSR maximize(const char *language, const char *script, const char *region, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const; + LSR maximize(StringPiece language, StringPiece script, StringPiece region, + bool returnInputIfUnmatch, + UErrorCode &errorCode) const; int32_t getLikelyIndex(const char *language, const char *script) const; + bool isMacroregion(StringPiece& region, UErrorCode &errorCode) const; static int32_t trieNext(BytesTrie &iter, const char *s, int32_t i); + static int32_t trieNext(BytesTrie &iter, StringPiece s, int32_t i); UResourceBundle *langInfoBundle; // We could store the strings by value, except that if there were few enough strings, diff --git a/thirdparty/icu4c/common/locmap.cpp b/thirdparty/icu4c/common/locmap.cpp index 7a0e90e8bd..e41cfd1027 100644 --- a/thirdparty/icu4c/common/locmap.cpp +++ b/thirdparty/icu4c/common/locmap.cpp @@ -1170,7 +1170,7 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status) // conversion functionality when available. #if U_PLATFORM_HAS_WIN32_API && UCONFIG_USE_WINDOWS_LCID_MAPPING_API int32_t len; - char baseName[ULOC_FULLNAME_CAPACITY] = {}; + icu::CharString baseName; const char * mylocaleID = localeID; // Check any for keywords. @@ -1189,19 +1189,23 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status) else { // If the locale ID contains keywords other than collation, just use the base name. - len = uloc_getBaseName(localeID, baseName, UPRV_LENGTHOF(baseName) - 1, status); - - if (U_SUCCESS(*status) && len > 0) { - baseName[len] = 0; - mylocaleID = baseName; + icu::CharStringByteSink sink(&baseName); + ulocimp_getBaseName(localeID, sink, status); + } + if (U_SUCCESS(*status) && !baseName.isEmpty()) + { + mylocaleID = baseName.data(); } } } - char asciiBCP47Tag[LOCALE_NAME_MAX_LENGTH] = {}; // this will change it from de_DE@collation=phonebook to de-DE-u-co-phonebk form - (void)uloc_toLanguageTag(mylocaleID, asciiBCP47Tag, UPRV_LENGTHOF(asciiBCP47Tag), false, status); + icu::CharString asciiBCP47Tag; + { + icu::CharStringByteSink sink(&asciiBCP47Tag); + ulocimp_toLanguageTag(mylocaleID, sink, false, status); + } if (U_SUCCESS(*status)) { diff --git a/thirdparty/icu4c/common/locresdata.cpp b/thirdparty/icu4c/common/locresdata.cpp index 7a0969dff5..c9d1cdddde 100644 --- a/thirdparty/icu4c/common/locresdata.cpp +++ b/thirdparty/icu4c/common/locresdata.cpp @@ -24,6 +24,8 @@ #include "unicode/putil.h" #include "unicode/uloc.h" #include "unicode/ures.h" +#include "bytesinkutil.h" +#include "charstr.h" #include "cstring.h" #include "ulocimp.h" #include "uresimp.h" @@ -156,16 +158,18 @@ _uloc_getOrientationHelper(const char* localeId, ULayoutType result = ULOC_LAYOUT_UNKNOWN; if (!U_FAILURE(*status)) { - int32_t length = 0; - char localeBuffer[ULOC_FULLNAME_CAPACITY]; - - uloc_canonicalize(localeId, localeBuffer, sizeof(localeBuffer), status); + icu::CharString localeBuffer; + { + icu::CharStringByteSink sink(&localeBuffer); + ulocimp_canonicalize(localeId, sink, status); + } if (!U_FAILURE(*status)) { + int32_t length = 0; const char16_t* const value = uloc_getTableStringWithFallback( nullptr, - localeBuffer, + localeBuffer.data(), "layout", nullptr, key, diff --git a/thirdparty/icu4c/common/lsr.cpp b/thirdparty/icu4c/common/lsr.cpp index 39eb46df27..bd231ecdb5 100644 --- a/thirdparty/icu4c/common/lsr.cpp +++ b/thirdparty/icu4c/common/lsr.cpp @@ -31,6 +31,26 @@ LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t } } +LSR::LSR(StringPiece lang, StringPiece scr, StringPiece r, int32_t f, + UErrorCode &errorCode) : + language(nullptr), script(nullptr), region(nullptr), + regionIndex(indexForRegion(r.data())), flags(f) { + if (U_SUCCESS(errorCode)) { + CharString data; + data.append(lang, errorCode).append('\0', errorCode); + int32_t scriptOffset = data.length(); + data.append(scr, errorCode).append('\0', errorCode); + int32_t regionOffset = data.length(); + data.append(r, errorCode); + owned = data.cloneData(errorCode); + if (U_SUCCESS(errorCode)) { + language = owned; + script = owned + scriptOffset; + region = owned + regionOffset; + } + } +} + LSR::LSR(LSR &&other) noexcept : language(other.language), script(other.script), region(other.region), owned(other.owned), regionIndex(other.regionIndex), flags(other.flags), diff --git a/thirdparty/icu4c/common/lsr.h b/thirdparty/icu4c/common/lsr.h index a2f7c8bb15..313286e93d 100644 --- a/thirdparty/icu4c/common/lsr.h +++ b/thirdparty/icu4c/common/lsr.h @@ -7,6 +7,7 @@ #ifndef __LSR_H__ #define __LSR_H__ +#include "unicode/stringpiece.h" #include "unicode/utypes.h" #include "unicode/uobject.h" #include "cstring.h" @@ -45,6 +46,8 @@ struct LSR final : public UMemory { */ LSR(char prefix, const char *lang, const char *scr, const char *r, int32_t f, UErrorCode &errorCode); + LSR(StringPiece lang, StringPiece scr, StringPiece r, int32_t f, + UErrorCode &errorCode); LSR(LSR &&other) noexcept; LSR(const LSR &other) = delete; inline ~LSR() { diff --git a/thirdparty/icu4c/common/norm2_nfc_data.h b/thirdparty/icu4c/common/norm2_nfc_data.h index ebe3e6ba90..3dada06c57 100644 --- a/thirdparty/icu4c/common/norm2_nfc_data.h +++ b/thirdparty/icu4c/common/norm2_nfc_data.h @@ -10,7 +10,7 @@ #ifdef INCLUDED_FROM_NORMALIZER2_CPP static const UVersionInfo norm2_nfc_data_formatVersion={4,0,0,0}; -static const UVersionInfo norm2_nfc_data_dataVersion={0xf,0,0,0}; +static const UVersionInfo norm2_nfc_data_dataVersion={0xf,1,0,0}; static const int32_t norm2_nfc_data_indexes[Normalizer2Impl::IX_COUNT]={ 0x50,0x4cb8,0x8920,0x8a20,0x8a20,0x8a20,0x8a20,0x8a20,0xc0,0x300,0xae2,0x29e0,0x3c66,0xfc00,0x1288,0x3b9c, diff --git a/thirdparty/icu4c/common/norm2allmodes.h b/thirdparty/icu4c/common/norm2allmodes.h index 6347fba9cb..a2cfc89c1a 100644 --- a/thirdparty/icu4c/common/norm2allmodes.h +++ b/thirdparty/icu4c/common/norm2allmodes.h @@ -391,6 +391,7 @@ struct Norm2AllModes : public UMemory { static const Norm2AllModes *getNFCInstance(UErrorCode &errorCode); static const Norm2AllModes *getNFKCInstance(UErrorCode &errorCode); static const Norm2AllModes *getNFKC_CFInstance(UErrorCode &errorCode); + static const Norm2AllModes *getNFKC_SCFInstance(UErrorCode &errorCode); Normalizer2Impl *impl; ComposeNormalizer2 comp; diff --git a/thirdparty/icu4c/common/normalizer2impl.h b/thirdparty/icu4c/common/normalizer2impl.h index 2cca33d349..f5ede24fc2 100644 --- a/thirdparty/icu4c/common/normalizer2impl.h +++ b/thirdparty/icu4c/common/normalizer2impl.h @@ -789,7 +789,8 @@ unorm_getFCD16(UChar32 c); * * Normalizer2 .nrm data files provide data for the Unicode Normalization algorithms. * ICU ships with data files for standard Unicode Normalization Forms - * NFC and NFD (nfc.nrm), NFKC and NFKD (nfkc.nrm) and NFKC_Casefold (nfkc_cf.nrm). + * NFC and NFD (nfc.nrm), NFKC and NFKD (nfkc.nrm), + * NFKC_Casefold (nfkc_cf.nrm) and NFKC_Simple_Casefold (nfkc_scf.nrm). * Custom (application-specific) data can be built into additional .nrm files * with the gennorm2 build tool. * ICU ships with one such file, uts46.nrm, for the implementation of UTS #46. diff --git a/thirdparty/icu4c/common/propname_data.h b/thirdparty/icu4c/common/propname_data.h index 1e247874b6..7bdbe8ec43 100644 --- a/thirdparty/icu4c/common/propname_data.h +++ b/thirdparty/icu4c/common/propname_data.h @@ -11,101 +11,102 @@ U_NAMESPACE_BEGIN -const int32_t PropNameData::indexes[8]={0x20,0x1660,0x5294,0xacd0,0xacd0,0xacd0,0x31,0}; +const int32_t PropNameData::indexes[8]={0x20,0x1690,0x5337,0xae61,0xae61,0xae61,0x31,0}; -const int32_t PropNameData::valueMaps[1424]={ -6,0,0x48,0,0xf1,0x368,0xf1,0x37e,0xf1,0x393,0xf1,0x3a9,0xf1,0x3b4,0xf1,0x3d5, -0xf1,0x3e5,0xf1,0x3f4,0xf1,0x402,0xf1,0x426,0xf1,0x43d,0xf1,0x455,0xf1,0x46c,0xf1,0x47b, -0xf1,0x48a,0xf1,0x49b,0xf1,0x4a9,0xf1,0x4bb,0xf1,0x4d5,0xf1,0x4f0,0xf1,0x505,0xf1,0x522, -0xf1,0x533,0xf1,0x53e,0xf1,0x55d,0xf1,0x573,0xf1,0x584,0xf1,0x594,0xf1,0x5af,0xf1,0x5c8, -0xf1,0x5d9,0xf1,0x5f3,0xf1,0x606,0xf1,0x616,0xf1,0x630,0xf1,0x649,0xf1,0x660,0xf1,0x674, -0xf1,0x68a,0xf1,0x69e,0xf1,0x6b4,0xf1,0x6ce,0xf1,0x6e6,0xf1,0x702,0xf1,0x70a,0xf1,0x712, -0xf1,0x71a,0xf1,0x722,0xf1,0x72b,0xf1,0x738,0xf1,0x74b,0xf1,0x768,0xf1,0x785,0xf1,0x7a2, -0xf1,0x7c0,0xf1,0x7de,0xf1,0x802,0xf1,0x80f,0xf1,0x829,0xf1,0x83e,0xf1,0x859,0xf1,0x870, -0xf1,0x887,0xf1,0x8a9,0xf1,0x8c8,0xf1,0x8e1,0xf1,0x90e,0xf1,0x947,0xf1,0x978,0xf1,0x9a7, -0xf1,0x9d6,0xf1,0x1000,0x1019,0x9eb,0x16d,0xc0b,0x188,0x3279,0xf7,0x3298,0x2d4,0x33d6,0x2ea,0x3430, -0x2f4,0x368d,0x316,0x3fb8,0x382,0x4028,0x38c,0x42c2,0x3bb,0x4300,0x3c3,0x4e45,0x48f,0x4ec3,0x499,0x4ee8, -0x49f,0x4f02,0x4a5,0x4f23,0x4ac,0x4f3d,0xf7,0x4f62,0xf7,0x4f88,0x4b3,0x5032,0x4c9,0x50ab,0x4dc,0x515d, -0x4f7,0x5194,0x4fe,0x5374,0x512,0x57f4,0x53a,0x2000,0x2001,0x5853,0x542,0x3000,0x3001,0x58df,0,0x4000, -0x400e,0x58f1,0,0x58fa,0,0x5914,0,0x5925,0,0x5936,0,0x594c,0,0x5955,0,0x5972, -0,0x5990,0,0x59ae,0,0x59cc,0,0x59e2,0,0x59f6,0,0x5a0c,0,0x7000,0x7001,0x5a25, -0,0x844,0x12,0,1,0x12,0x20,0x862,0x4a,0,1,6,7,8,9,0xa, -0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, -0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x54,0x5b,0x67,0x6b,0x76,0x7a, -0x81,0x82,0x84,0x85,0xc8,0xca,0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8, -0xe9,0xea,0xf0,0x2e,0x40,0x4c,0x5e,0x68,0x79,0x84,0x91,0x9e,0xab,0xb8,0xc5,0xd2, -0xdf,0xec,0xf9,0x106,0x113,0x120,0x12d,0x13a,0x147,0x154,0x161,0x16e,0x17b,0x188,0x195,0x1a2, -0x1af,0x1bc,0x1c9,0x1d6,0x1e3,0x1f0,0x1fd,0x20c,0x21b,0x22a,0x239,0x248,0x257,0x266,0x275,0x28f, -0x2a3,0x2b7,0x2d2,0x2e1,0x2ea,0x2fa,0x302,0x30b,0x31a,0x323,0x333,0x344,0x355,0xa03,1,0, -0x17,0x9fa,0xa0b,0xa1c,0xa30,0xa47,0xa5f,0xa71,0xa86,0xa9d,0xab2,0xac2,0xad4,0xaf1,0xb0d,0xb1f, -0xb3c,0xb58,0xb74,0xb89,0xb9e,0xbb8,0xbd3,0xbee,0xba5,1,0,0x148,0xc16,0xc23,0xc36,0xc5e, -0xc7c,0xc9a,0xcb2,0xcdd,0xd07,0xd1f,0xd32,0xd45,0xd54,0xd63,0xd72,0xd81,0xd98,0xda9,0xdbc,0xdcf, -0xddc,0xde9,0xdf8,0xe09,0xe1e,0xe2f,0xe3a,0xe43,0xe54,0xe65,0xe78,0xe8a,0xe9d,0xeb0,0xeef,0xefc, -0xf09,0xf16,0xf2b,0xf5b,0xf75,0xf96,0xfc1,0xfe4,0x1042,0x1069,0x1084,0x1093,0x10ba,0x10e2,0x1105,0x1128, -0x1152,0x116b,0x118a,0x11ad,0x11d1,0x11e4,0x11fe,0x1228,0x1240,0x1268,0x1291,0x12a4,0x12b7,0x12ca,0x12f1,0x1300, -0x1320,0x134e,0x136c,0x139a,0x13b6,0x13d1,0x13ea,0x1403,0x1424,0x1454,0x1473,0x1495,0x14c9,0x14f6,0x153b,0x155c, -0x1586,0x15a7,0x15d0,0x15e3,0x1616,0x162d,0x163c,0x164d,0x1678,0x168f,0x16c0,0x16ee,0x1731,0x173c,0x1775,0x1786, -0x1797,0x17a4,0x17b7,0x17f1,0x1815,0x1839,0x1873,0x18ab,0x18d6,0x18ee,0x191a,0x1946,0x1953,0x1962,0x197f,0x19a1, -0x19cf,0x19ef,0x1a16,0x1a3d,0x1a5c,0x1a6f,0x1a80,0x1a91,0x1ab6,0x1adb,0x1b02,0x1b36,0x1b63,0x1b81,0x1b94,0x1bad, -0x1be6,0x1bf5,0x1c15,0x1c37,0x1c59,0x1c70,0x1c87,0x1cb4,0x1ccd,0x1ce6,0x1d17,0x1d41,0x1d5c,0x1d6f,0x1d8e,0x1d97, -0x1daa,0x1dc8,0x1de6,0x1df9,0x1e10,0x1e25,0x1e5a,0x1e7e,0x1e93,0x1ea2,0x1eb5,0x1ed9,0x1ee2,0x1f06,0x1f1d,0x1f30, -0x1f3f,0x1f4a,0x1f6b,0x1f83,0x1f92,0x1fa1,0x1fb0,0x1fc7,0x1fdc,0x1ff1,0x202a,0x203d,0x2059,0x2064,0x2071,0x209f, -0x20c3,0x20e6,0x20f9,0x211b,0x212e,0x2149,0x216c,0x218f,0x21b4,0x21c5,0x21f4,0x2221,0x2238,0x2253,0x2262,0x228d, -0x22c5,0x22ff,0x232d,0x233e,0x234b,0x236f,0x237e,0x239a,0x23b4,0x23d1,0x2409,0x241e,0x244b,0x246a,0x2498,0x24b8, -0x24ec,0x24fb,0x2525,0x2548,0x2573,0x257e,0x258f,0x25aa,0x25ce,0x25db,0x25f0,0x2617,0x2642,0x2679,0x268c,0x269d, -0x26cd,0x26de,0x26ed,0x2702,0x2720,0x2733,0x2746,0x275d,0x277a,0x2785,0x278e,0x27b0,0x27c5,0x27ea,0x2801,0x282a, -0x2845,0x285a,0x2873,0x2894,0x28c9,0x28da,0x290b,0x292f,0x2940,0x2959,0x2964,0x2991,0x29b3,0x29e1,0x2a14,0x2a23, -0x2a34,0x2a51,0x2a93,0x2aba,0x2ac7,0x2adc,0x2b00,0x2b26,0x2b5f,0x2b70,0x2b94,0x2b9f,0x2bac,0x2bbb,0x2be0,0x2c0e, -0x2c2a,0x2c47,0x2c54,0x2c65,0x2c83,0x2ca6,0x2cc3,0x2cd0,0x2cf0,0x2d0d,0x2d2e,0x2d57,0x2d68,0x2d87,0x2da0,0x2db9, -0x2dca,0x2e13,0x2e24,0x2e3d,0x2e6c,0x2e99,0x2ebe,0x2f00,0x2f1c,0x2f2b,0x2f42,0x2f70,0x2f89,0x2fb2,0x2fcc,0x3007, -0x3025,0x3034,0x3054,0x306f,0x3093,0x30af,0x30cd,0x30eb,0x3102,0x3111,0x311c,0x3159,0x316c,0x3196,0x31b6,0x31e4, -0x3208,0x3230,0x3255,0x3260,0x1fa9,1,0,0x12,0x32af,0x32bf,0x32d2,0x32e2,0x32f2,0x3301,0x3311,0x3323, -0x3336,0x3348,0x3358,0x3368,0x3377,0x3386,0x3396,0x33a3,0x33b2,0x33c6,0x2067,1,0,6,0x33eb,0x33f6, -0x3403,0x3410,0x341d,0x3428,0x20ab,1,0,0x1e,0x3445,0x3454,0x3469,0x347e,0x3493,0x34a7,0x34b8,0x34cc, -0x34df,0x34f0,0x3509,0x351b,0x352c,0x3540,0x3553,0x356b,0x357d,0x3588,0x3598,0x35a6,0x35bb,0x35d0,0x35e6,0x3600, -0x3616,0x3626,0x363a,0x364e,0x365f,0x3677,0x22d6,1,0,0x68,0x369f,0x36c2,0x36cb,0x36d8,0x36e3,0x36ec, -0x36f7,0x3700,0x3719,0x371e,0x3727,0x3744,0x374d,0x375a,0x3763,0x3787,0x378e,0x3797,0x37aa,0x37b5,0x37be,0x37c9, -0x37e2,0x37eb,0x37fa,0x3805,0x380e,0x3819,0x3822,0x3829,0x3832,0x383d,0x3846,0x385f,0x3868,0x3875,0x3880,0x3891, -0x389c,0x38b1,0x38c8,0x38d1,0x38da,0x38f3,0x38fe,0x3907,0x3910,0x3927,0x3944,0x394f,0x3960,0x396b,0x3972,0x397f, -0x398c,0x39b9,0x39ce,0x39d7,0x39f2,0x3a15,0x3a36,0x3a57,0x3a7c,0x3aa3,0x3ac4,0x3ae7,0x3b08,0x3b2f,0x3b50,0x3b75, -0x3b94,0x3bb3,0x3bd2,0x3bef,0x3c10,0x3c31,0x3c54,0x3c79,0x3c98,0x3cb7,0x3cd8,0x3cff,0x3d24,0x3d43,0x3d64,0x3d87, -0x3da2,0x3dbb,0x3dd6,0x3def,0x3e0c,0x3e27,0x3e44,0x3e63,0x3e80,0x3e9d,0x3ebc,0x3ed9,0x3ef4,0x3f11,0x3f2e,0x3f61, -0x3f88,0x3f9b,0x2639,1,0,6,0x3fc9,0x3fd8,0x3fe8,0x3ff8,0x4008,0x4019,0x2697,1,0,0x2b, -0x4037,0x4043,0x4051,0x4060,0x406f,0x407f,0x4090,0x40a4,0x40b9,0x40cf,0x40e2,0x40f6,0x4106,0x410f,0x411a,0x412a, -0x4146,0x4158,0x4166,0x4175,0x4181,0x4196,0x41aa,0x41bd,0x41cb,0x41df,0x41ed,0x41f7,0x4209,0x4215,0x4223,0x4233, -0x423a,0x4241,0x4248,0x424f,0x4256,0x426c,0x428d,0x870,0x429f,0x42aa,0x42b9,0x28f0,1,0,4,0x42d3, -0x42de,0x42ea,0x42f4,0x2916,1,0,0xc8,0x430b,0x4318,0x432d,0x433a,0x4349,0x4357,0x4366,0x4375,0x4387, -0x4396,0x43a4,0x43b5,0x43c4,0x43d3,0x43e0,0x43ec,0x43fb,0x440a,0x4414,0x4421,0x442e,0x443d,0x444b,0x445a,0x4466, -0x4470,0x447c,0x448c,0x449c,0x44aa,0x44b6,0x44c7,0x44d3,0x44df,0x44ed,0x44fa,0x4506,0x4513,0xe2f,0x4520,0x452e, -0x4548,0x4551,0x455f,0x456d,0x4579,0x4588,0x4596,0x45a4,0x45b0,0x45bf,0x45cd,0x45db,0x45e8,0x45f7,0x4612,0x4621, -0x4632,0x4643,0x4656,0x4668,0x4677,0x4689,0x4698,0x46a4,0x46af,0x1f3f,0x46bc,0x46c7,0x46d2,0x46dd,0x46e8,0x4703, -0x470e,0x4719,0x4724,0x4737,0x474b,0x4756,0x4765,0x4774,0x477f,0x478a,0x4797,0x47a6,0x47b4,0x47bf,0x47da,0x47e4, -0x47f5,0x4806,0x4815,0x4826,0x4831,0x483c,0x4847,0x4852,0x485d,0x4868,0x4873,0x487d,0x4888,0x4898,0x48a3,0x48b1, -0x48be,0x48c9,0x48d8,0x48e5,0x48f2,0x4901,0x490e,0x491f,0x4931,0x4941,0x494c,0x495f,0x4976,0x4984,0x4991,0x499c, -0x49a9,0x49ba,0x49d6,0x49ec,0x49f7,0x4a14,0x4a24,0x4a33,0x4a3e,0x4a49,0x2059,0x4a55,0x4a60,0x4a78,0x4a88,0x4a97, -0x4aa5,0x4ab3,0x4abe,0x4ac9,0x4add,0x4af4,0x4b0c,0x4b1c,0x4b2c,0x4b3c,0x4b4e,0x4b59,0x4b64,0x4b6e,0x4b7a,0x4b88, -0x4b9b,0x4ba7,0x4bb4,0x4bbf,0x4bdb,0x4be8,0x4bf6,0x4c0f,0x2959,0x4c1e,0x277a,0x4c2b,0x4c39,0x4c4b,0x4c59,0x4c65, -0x4c75,0x2b94,0x4c83,0x4c8f,0x4c9a,0x4ca5,0x4cb0,0x4cc4,0x4cd2,0x4ce9,0x4cf5,0x4d09,0x4d17,0x4d29,0x4d3f,0x4d4d, -0x4d5f,0x4d6d,0x4d8a,0x4d9c,0x4da9,0x4dba,0x4dcc,0x4de6,0x4df3,0x4e06,0x4e17,0x3111,0x4e24,0x3255,0x4e33,0x3370, -1,0,6,0x4e5f,0x4e72,0x4e82,0x4e90,0x4ea1,0x4eb1,0x33cc,0x12,0,1,0x4edb,0x4ee1,0x33d9, -0x12,0,1,0x4edb,0x4ee1,0x33e6,1,0,3,0x4edb,0x4ee1,0x4f1a,0x33fc,1,0,3, -0x4edb,0x4ee1,0x4f1a,0x3412,1,0,0x12,0x4fa4,0x4fae,0x4fba,0x4fc1,0x4fcc,0x4fd1,0x4fd8,0x4fdf,0x4fe8, -0x4fed,0x4ff2,0x5002,0x870,0x429f,0x500e,0x42aa,0x501e,0x42b9,0x34bb,1,0,0xf,0x4fa4,0x5045,0x504f, -0x5059,0x5064,0x4175,0x506e,0x507a,0x5082,0x5089,0x5093,0x4fba,0x4fc1,0x4fd1,0x509d,0x3542,1,0,0x17, -0x4fa4,0x50ba,0x5059,0x50c6,0x50d3,0x50e1,0x4175,0x50ec,0x4fba,0x50fd,0x4fd1,0x510c,0x511a,0x870,0x428d,0x5126, -0x5137,0x429f,0x500e,0x42aa,0x501e,0x42b9,0x5148,0x365f,1,0,3,0x517b,0x5183,0x518b,0x3678,1, -0,0x10,0x51b4,0x51bb,0x51ca,0x51eb,0x520e,0x5219,0x5238,0x524f,0x525c,0x5265,0x5284,0x52b7,0x52d2,0x5301, -0x531e,0x5343,0x3711,1,0,0x24,0x5392,0x539f,0x53b2,0x53bf,0x53ec,0x5411,0x5426,0x5445,0x5466,0x5493, -0x54cc,0x54ef,0x5512,0x553f,0x5574,0x559b,0x55c4,0x55fb,0x562a,0x564b,0x5670,0x567f,0x56a2,0x56b9,0x56c6,0x56d5, -0x56f2,0x570b,0x572e,0x5753,0x576c,0x5781,0x5790,0x57a1,0x57ae,0x57cf,0x38e1,1,0,4,0x580d,0x5818, -0x5830,0x5848,0x391d,0x36,1,2,4,8,0xe,0x10,0x20,0x3e,0x40,0x80,0x100,0x1c0, -0x200,0x400,0x800,0xe00,0x1000,0x2000,0x4000,0x7000,0x8000,0x10000,0x20000,0x40000,0x78001,0x80000,0x100000,0x200000, -0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000,0xf000000,0x10000000,0x20000000,0x30f80000,0x3445,0x3454,0x3469,0x347e,0x5881,0x3493, -0x34a7,0x5877,0x34b8,0x34cc,0x34df,0x5892,0x34f0,0x3509,0x351b,0x58a9,0x352c,0x3540,0x3553,0x58d2,0x356b,0x357d, -0x3588,0x3598,0x586e,0x35a6,0x35bb,0x35d0,0x35e6,0x3600,0x3616,0x3626,0x363a,0x364e,0x58c8,0x365f,0x3677,0x58b3 +const int32_t PropNameData::valueMaps[1436]={ +6,0,0x4b,0,0xf7,0x368,0xf7,0x37e,0xf7,0x393,0xf7,0x3a9,0xf7,0x3b4,0xf7,0x3d5, +0xf7,0x3e5,0xf7,0x3f4,0xf7,0x402,0xf7,0x426,0xf7,0x43d,0xf7,0x455,0xf7,0x46c,0xf7,0x47b, +0xf7,0x48a,0xf7,0x49b,0xf7,0x4a9,0xf7,0x4bb,0xf7,0x4d5,0xf7,0x4f0,0xf7,0x505,0xf7,0x522, +0xf7,0x533,0xf7,0x53e,0xf7,0x55d,0xf7,0x573,0xf7,0x584,0xf7,0x594,0xf7,0x5af,0xf7,0x5c8, +0xf7,0x5d9,0xf7,0x5f3,0xf7,0x606,0xf7,0x616,0xf7,0x630,0xf7,0x649,0xf7,0x660,0xf7,0x674, +0xf7,0x68a,0xf7,0x69e,0xf7,0x6b4,0xf7,0x6ce,0xf7,0x6e6,0xf7,0x702,0xf7,0x70a,0xf7,0x712, +0xf7,0x71a,0xf7,0x722,0xf7,0x72b,0xf7,0x738,0xf7,0x74b,0xf7,0x768,0xf7,0x785,0xf7,0x7a2, +0xf7,0x7c0,0xf7,0x7de,0xf7,0x802,0xf7,0x80f,0xf7,0x829,0xf7,0x83e,0xf7,0x859,0xf7,0x870, +0xf7,0x887,0xf7,0x8a9,0xf7,0x8c8,0xf7,0x8e1,0xf7,0x90e,0xf7,0x947,0xf7,0x978,0xf7,0x9a7, +0xf7,0x9d6,0xf7,0x9eb,0xf7,0xa04,0xf7,0xa2f,0xf7,0x1000,0x1019,0xa60,0x173,0xc80,0x18e,0x331c, +0xfd,0x333b,0x2db,0x3479,0x2f1,0x34d3,0x2fb,0x3730,0x31d,0x405b,0x389,0x40cb,0x393,0x43b0,0x3c7,0x43ee, +0x3cf,0x4f33,0x49b,0x4fb1,0x4a5,0x4fd6,0x4ab,0x4ff0,0x4b1,0x5011,0x4b8,0x502b,0xfd,0x5050,0xfd,0x5076, +0x4bf,0x5120,0x4d5,0x5199,0x4e8,0x524b,0x503,0x5282,0x50a,0x5462,0x51e,0x58e2,0x546,0x2000,0x2001,0x5941, +0x54e,0x3000,0x3001,0x59cd,0,0x4000,0x400e,0x59df,0,0x59e8,0,0x5a02,0,0x5a13,0,0x5a24, +0,0x5a3a,0,0x5a43,0,0x5a60,0,0x5a7e,0,0x5a9c,0,0x5aba,0,0x5ad0,0,0x5ae4, +0,0x5afa,0,0x7000,0x7001,0x5b13,0,0x87a,0x12,0,1,0x12,0x20,0x898,0x4a,0, +1,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14, +0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24, +0x54,0x5b,0x67,0x6b,0x76,0x7a,0x81,0x82,0x84,0x85,0xc8,0xca,0xd6,0xd8,0xda,0xdc, +0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xe9,0xea,0xf0,0x2e,0x40,0x4c,0x5e,0x68,0x79,0x84, +0x91,0x9e,0xab,0xb8,0xc5,0xd2,0xdf,0xec,0xf9,0x106,0x113,0x120,0x12d,0x13a,0x147,0x154, +0x161,0x16e,0x17b,0x188,0x195,0x1a2,0x1af,0x1bc,0x1c9,0x1d6,0x1e3,0x1f0,0x1fd,0x20c,0x21b,0x22a, +0x239,0x248,0x257,0x266,0x275,0x28f,0x2a3,0x2b7,0x2d2,0x2e1,0x2ea,0x2fa,0x302,0x30b,0x31a,0x323, +0x333,0x344,0x355,0xa39,1,0,0x17,0xa6f,0xa80,0xa91,0xaa5,0xabc,0xad4,0xae6,0xafb,0xb12, +0xb27,0xb37,0xb49,0xb66,0xb82,0xb94,0xbb1,0xbcd,0xbe9,0xbfe,0xc13,0xc2d,0xc48,0xc63,0xbdb,1, +0,0x149,0xc8b,0xc98,0xcab,0xcd3,0xcf1,0xd0f,0xd27,0xd52,0xd7c,0xd94,0xda7,0xdba,0xdc9,0xdd8, +0xde7,0xdf6,0xe0d,0xe1e,0xe31,0xe44,0xe51,0xe5e,0xe6d,0xe7e,0xe93,0xea4,0xeaf,0xeb8,0xec9,0xeda, +0xeed,0xeff,0xf12,0xf25,0xf64,0xf71,0xf7e,0xf8b,0xfa0,0xfd0,0xfea,0x100b,0x1036,0x1059,0x10b7,0x10de, +0x10f9,0x1108,0x112f,0x1157,0x117a,0x119d,0x11c7,0x11e0,0x11ff,0x1222,0x1246,0x1259,0x1273,0x129d,0x12b5,0x12dd, +0x1306,0x1319,0x132c,0x133f,0x1366,0x1375,0x1395,0x13c3,0x13e1,0x140f,0x142b,0x1446,0x145f,0x1478,0x1499,0x14c9, +0x14e8,0x150a,0x153e,0x156b,0x15b0,0x15d1,0x15fb,0x161c,0x1645,0x1658,0x168b,0x16a2,0x16b1,0x16c2,0x16ed,0x1704, +0x1735,0x1763,0x17a6,0x17b1,0x17ea,0x17fb,0x180c,0x1819,0x182c,0x1866,0x188a,0x18ae,0x18e8,0x1920,0x194b,0x1963, +0x198f,0x19bb,0x19c8,0x19d7,0x19f4,0x1a16,0x1a44,0x1a64,0x1a8b,0x1ab2,0x1ad1,0x1ae4,0x1af5,0x1b06,0x1b2b,0x1b50, +0x1b77,0x1bab,0x1bd8,0x1bf6,0x1c09,0x1c22,0x1c5b,0x1c6a,0x1c8a,0x1cac,0x1cce,0x1ce5,0x1cfc,0x1d29,0x1d42,0x1d5b, +0x1d8c,0x1db6,0x1dd1,0x1de4,0x1e03,0x1e0c,0x1e1f,0x1e3d,0x1e5b,0x1e6e,0x1e85,0x1e9a,0x1ecf,0x1ef3,0x1f08,0x1f17, +0x1f2a,0x1f4e,0x1f57,0x1f7b,0x1f92,0x1fa5,0x1fb4,0x1fbf,0x1fe0,0x1ff8,0x2007,0x2016,0x2025,0x203c,0x2051,0x2066, +0x209f,0x20b2,0x20ce,0x20d9,0x20e6,0x2114,0x2138,0x215b,0x216e,0x2190,0x21a3,0x21be,0x21e1,0x2204,0x2229,0x223a, +0x2269,0x2296,0x22ad,0x22c8,0x22d7,0x2302,0x233a,0x2374,0x23a2,0x23b3,0x23c0,0x23e4,0x23f3,0x240f,0x2429,0x2446, +0x247e,0x2493,0x24c0,0x24df,0x250d,0x252d,0x2561,0x2570,0x259a,0x25bd,0x25e8,0x25f3,0x2604,0x261f,0x2643,0x2650, +0x2665,0x268c,0x26b7,0x26ee,0x2701,0x2712,0x2742,0x2753,0x2762,0x2777,0x2795,0x27a8,0x27bb,0x27d2,0x27ef,0x27fa, +0x2803,0x2825,0x283a,0x285f,0x2876,0x289f,0x28ba,0x28cf,0x28e8,0x2909,0x293e,0x294f,0x2980,0x29a4,0x29b5,0x29ce, +0x29d9,0x2a06,0x2a28,0x2a56,0x2a89,0x2a98,0x2aa9,0x2ac6,0x2b08,0x2b2f,0x2b3c,0x2b51,0x2b75,0x2b9b,0x2bd4,0x2be5, +0x2c09,0x2c14,0x2c21,0x2c30,0x2c55,0x2c83,0x2c9f,0x2cbc,0x2cc9,0x2cda,0x2cf8,0x2d1b,0x2d38,0x2d45,0x2d65,0x2d82, +0x2da3,0x2dcc,0x2ddd,0x2dfc,0x2e15,0x2e2e,0x2e3f,0x2e88,0x2e99,0x2eb2,0x2ee1,0x2f0e,0x2f33,0x2f75,0x2f91,0x2fa0, +0x2fb7,0x2fe5,0x2ffe,0x3027,0x3041,0x307c,0x309a,0x30a9,0x30c9,0x30e4,0x3108,0x3124,0x3142,0x3160,0x3177,0x3186, +0x3191,0x31ce,0x31e1,0x320b,0x322b,0x3259,0x327d,0x32a5,0x32ca,0x32d5,0x32ee,0x1fe5,1,0,0x12,0x3352, +0x3362,0x3375,0x3385,0x3395,0x33a4,0x33b4,0x33c6,0x33d9,0x33eb,0x33fb,0x340b,0x341a,0x3429,0x3439,0x3446,0x3455, +0x3469,0x20a3,1,0,6,0x348e,0x3499,0x34a6,0x34b3,0x34c0,0x34cb,0x20e7,1,0,0x1e,0x34e8, +0x34f7,0x350c,0x3521,0x3536,0x354a,0x355b,0x356f,0x3582,0x3593,0x35ac,0x35be,0x35cf,0x35e3,0x35f6,0x360e,0x3620, +0x362b,0x363b,0x3649,0x365e,0x3673,0x3689,0x36a3,0x36b9,0x36c9,0x36dd,0x36f1,0x3702,0x371a,0x2312,1,0, +0x68,0x3742,0x3765,0x376e,0x377b,0x3786,0x378f,0x379a,0x37a3,0x37bc,0x37c1,0x37ca,0x37e7,0x37f0,0x37fd,0x3806, +0x382a,0x3831,0x383a,0x384d,0x3858,0x3861,0x386c,0x3885,0x388e,0x389d,0x38a8,0x38b1,0x38bc,0x38c5,0x38cc,0x38d5, +0x38e0,0x38e9,0x3902,0x390b,0x3918,0x3923,0x3934,0x393f,0x3954,0x396b,0x3974,0x397d,0x3996,0x39a1,0x39aa,0x39b3, +0x39ca,0x39e7,0x39f2,0x3a03,0x3a0e,0x3a15,0x3a22,0x3a2f,0x3a5c,0x3a71,0x3a7a,0x3a95,0x3ab8,0x3ad9,0x3afa,0x3b1f, +0x3b46,0x3b67,0x3b8a,0x3bab,0x3bd2,0x3bf3,0x3c18,0x3c37,0x3c56,0x3c75,0x3c92,0x3cb3,0x3cd4,0x3cf7,0x3d1c,0x3d3b, +0x3d5a,0x3d7b,0x3da2,0x3dc7,0x3de6,0x3e07,0x3e2a,0x3e45,0x3e5e,0x3e79,0x3e92,0x3eaf,0x3eca,0x3ee7,0x3f06,0x3f23, +0x3f40,0x3f5f,0x3f7c,0x3f97,0x3fb4,0x3fd1,0x4004,0x402b,0x403e,0x2675,1,0,6,0x406c,0x407b,0x408b, +0x409b,0x40ab,0x40bc,0x26d3,1,0,0x30,0x40da,0x40e6,0x40f4,0x4103,0x4112,0x4122,0x4133,0x4147,0x415c, +0x4172,0x4185,0x4199,0x41a9,0x41b2,0x41bd,0x41cd,0x41e9,0x41fb,0x4209,0x4218,0x4224,0x4239,0x424d,0x4260,0x426e, +0x4282,0x4290,0x429a,0x42ac,0x42b8,0x42c6,0x42d6,0x42dd,0x42e4,0x42eb,0x42f2,0x42f9,0x430f,0x4330,0x870,0x4342, +0x434d,0x435c,0x4365,0x4370,0x4383,0x4394,0x43a5,0x2963,1,0,4,0x43c1,0x43cc,0x43d8,0x43e2,0x2989, +1,0,0xc8,0x43f9,0x4406,0x441b,0x4428,0x4437,0x4445,0x4454,0x4463,0x4475,0x4484,0x4492,0x44a3,0x44b2, +0x44c1,0x44ce,0x44da,0x44e9,0x44f8,0x4502,0x450f,0x451c,0x452b,0x4539,0x4548,0x4554,0x455e,0x456a,0x457a,0x458a, +0x4598,0x45a4,0x45b5,0x45c1,0x45cd,0x45db,0x45e8,0x45f4,0x4601,0xea4,0x460e,0x461c,0x4636,0x463f,0x464d,0x465b, +0x4667,0x4676,0x4684,0x4692,0x469e,0x46ad,0x46bb,0x46c9,0x46d6,0x46e5,0x4700,0x470f,0x4720,0x4731,0x4744,0x4756, +0x4765,0x4777,0x4786,0x4792,0x479d,0x1fb4,0x47aa,0x47b5,0x47c0,0x47cb,0x47d6,0x47f1,0x47fc,0x4807,0x4812,0x4825, +0x4839,0x4844,0x4853,0x4862,0x486d,0x4878,0x4885,0x4894,0x48a2,0x48ad,0x48c8,0x48d2,0x48e3,0x48f4,0x4903,0x4914, +0x491f,0x492a,0x4935,0x4940,0x494b,0x4956,0x4961,0x496b,0x4976,0x4986,0x4991,0x499f,0x49ac,0x49b7,0x49c6,0x49d3, +0x49e0,0x49ef,0x49fc,0x4a0d,0x4a1f,0x4a2f,0x4a3a,0x4a4d,0x4a64,0x4a72,0x4a7f,0x4a8a,0x4a97,0x4aa8,0x4ac4,0x4ada, +0x4ae5,0x4b02,0x4b12,0x4b21,0x4b2c,0x4b37,0x20ce,0x4b43,0x4b4e,0x4b66,0x4b76,0x4b85,0x4b93,0x4ba1,0x4bac,0x4bb7, +0x4bcb,0x4be2,0x4bfa,0x4c0a,0x4c1a,0x4c2a,0x4c3c,0x4c47,0x4c52,0x4c5c,0x4c68,0x4c76,0x4c89,0x4c95,0x4ca2,0x4cad, +0x4cc9,0x4cd6,0x4ce4,0x4cfd,0x29ce,0x4d0c,0x27ef,0x4d19,0x4d27,0x4d39,0x4d47,0x4d53,0x4d63,0x2c09,0x4d71,0x4d7d, +0x4d88,0x4d93,0x4d9e,0x4db2,0x4dc0,0x4dd7,0x4de3,0x4df7,0x4e05,0x4e17,0x4e2d,0x4e3b,0x4e4d,0x4e5b,0x4e78,0x4e8a, +0x4e97,0x4ea8,0x4eba,0x4ed4,0x4ee1,0x4ef4,0x4f05,0x3186,0x4f12,0x32ca,0x4f21,0x33e3,1,0,6,0x4f4d, +0x4f60,0x4f70,0x4f7e,0x4f8f,0x4f9f,0x343f,0x12,0,1,0x4fc9,0x4fcf,0x344c,0x12,0,1,0x4fc9, +0x4fcf,0x3459,1,0,3,0x4fc9,0x4fcf,0x5008,0x346f,1,0,3,0x4fc9,0x4fcf,0x5008,0x3485, +1,0,0x12,0x5092,0x509c,0x50a8,0x50af,0x50ba,0x50bf,0x50c6,0x50cd,0x50d6,0x50db,0x50e0,0x50f0,0x870, +0x4342,0x50fc,0x434d,0x510c,0x435c,0x352e,1,0,0xf,0x5092,0x5133,0x513d,0x5147,0x5152,0x4218,0x515c, +0x5168,0x5170,0x5177,0x5181,0x50a8,0x50af,0x50bf,0x518b,0x35b5,1,0,0x17,0x5092,0x51a8,0x5147,0x51b4, +0x51c1,0x51cf,0x4218,0x51da,0x50a8,0x51eb,0x50bf,0x51fa,0x5208,0x870,0x4330,0x5214,0x5225,0x4342,0x50fc,0x434d, +0x510c,0x435c,0x5236,0x36d2,1,0,3,0x5269,0x5271,0x5279,0x36eb,1,0,0x10,0x52a2,0x52a9, +0x52b8,0x52d9,0x52fc,0x5307,0x5326,0x533d,0x534a,0x5353,0x5372,0x53a5,0x53c0,0x53ef,0x540c,0x5431,0x3784,1, +0,0x24,0x5480,0x548d,0x54a0,0x54ad,0x54da,0x54ff,0x5514,0x5533,0x5554,0x5581,0x55ba,0x55dd,0x5600,0x562d, +0x5662,0x5689,0x56b2,0x56e9,0x5718,0x5739,0x575e,0x576d,0x5790,0x57a7,0x57b4,0x57c3,0x57e0,0x57f9,0x581c,0x5841, +0x585a,0x586f,0x587e,0x588f,0x589c,0x58bd,0x3954,1,0,4,0x58fb,0x5906,0x591e,0x5936,0x3990,0x36, +1,2,4,8,0xe,0x10,0x20,0x3e,0x40,0x80,0x100,0x1c0,0x200,0x400,0x800,0xe00, +0x1000,0x2000,0x4000,0x7000,0x8000,0x10000,0x20000,0x40000,0x78001,0x80000,0x100000,0x200000,0x400000,0x800000,0x1000000,0x2000000, +0x4000000,0x8000000,0xf000000,0x10000000,0x20000000,0x30f80000,0x34e8,0x34f7,0x350c,0x3521,0x596f,0x3536,0x354a,0x5965,0x355b,0x356f, +0x3582,0x5980,0x3593,0x35ac,0x35be,0x5997,0x35cf,0x35e3,0x35f6,0x59c0,0x360e,0x3620,0x362b,0x363b,0x595c,0x3649, +0x365e,0x3673,0x3689,0x36a3,0x36b9,0x36c9,0x36dd,0x36f1,0x59b6,0x3702,0x371a,0x59a1 }; -const uint8_t PropNameData::bytesTries[15412]={ +const uint8_t PropNameData::bytesTries[15527]={ 0,0x15,0x6d,0xc3,0xc7,0x73,0xc2,0x12,0x76,0x7a,0x76,0x6a,0x77,0xa2,0x52,0x78, 1,0x64,0x50,0x69,0x10,0x64,1,0x63,0x30,0x73,0x62,0x13,0x74,0x61,0x72,0x74, 0x63,0x60,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x61,0x13,0x69,0x67,0x69,0x74, @@ -166,913 +167,920 @@ const uint8_t PropNameData::bytesTries[15412]={ 0x30,0x77,0x10,0x73,0x77,0x11,0x79,0x6e,0x75,0x12,0x65,0x72,0x6e,1,0x73,0x38, 0x77,0x18,0x68,0x69,0x74,0x65,0x73,0x70,0x61,0x63,0x65,0x77,0x14,0x79,0x6e,0x74, 0x61,0x78,0x75,0x10,0x6d,0x9f,1,0x6d,0x3c,0x75,0x1a,0x6f,0x74,0x61,0x74,0x69, -0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x53,0x12,0x61,0x72,0x6b,0x53,0x66,0xc1,0xf8,0x69, -0xc1,0x3c,0x69,0xa2,0x6f,0x6a,0xa4,9,0x6c,4,0x62,0xc3,8,0x63,0x8c,0x65, +0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x53,0x12,0x61,0x72,0x6b,0x53,0x66,0xc2,0x2e,0x69, +0xc1,0x72,0x69,0xa2,0x6f,0x6a,0xa4,0x3f,0x6c,4,0x62,0xc3,8,0x63,0x8c,0x65, 0x98,0x69,0xa2,0x56,0x6f,2,0x65,0x4b,0x67,0x4c,0x77,0x11,0x65,0x72,0x4c,0x13, 0x63,0x61,0x73,0x65,0x4c,0x16,0x6d,0x61,0x70,0x70,0x69,0x6e,0x67,0xd9,0x40,4, 0x11,0x69,0x63,0x1f,0x61,0x6c,0x6f,0x72,0x64,0x65,0x72,0x65,0x78,0x63,0x65,0x70, 0x74,0x69,0x6f,0x6e,0x4b,0xd8,0x40,4,0x11,0x63,0x63,0xc3,0x10,0x18,0x61,0x64, 0x63,0x61,0x6e,0x6f,0x6e,0x69,0x63,0x1f,0x61,0x6c,0x63,0x6f,0x6d,0x62,0x69,0x6e, 0x69,0x6e,0x67,0x63,0x6c,0x61,0x73,0x73,0xc3,0x10,0x16,0x6e,0x65,0x62,0x72,0x65, -0x61,0x6b,0xc3,8,2,0x64,0x4a,0x6e,0xa2,0x5b,0x73,1,0x63,0xd9,0x40,3, -0x6f,0x16,0x63,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0xd9,0x40,3,2,0x63,0x80,0x65, -0x90,0x73,0x40,1,0x62,0x52,0x74,0x46,1,0x61,0x40,0x72,0x1c,0x69,0x6e,0x61, -0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x47,0x11,0x72,0x74,0x41,0x44, -0x1c,0x69,0x6e,0x61,0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x45,0x3e, -0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3f,0x10,0x6f,0x42,0x16,0x67,0x72,0x61, -0x70,0x68,0x69,0x63,0x43,2,0x64,0x2e,0x70,0x86,0x73,0x10,0x63,0xc3,0x17,0x11, -0x69,0x63,1,0x70,0x46,0x73,0x1e,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x63,0x61, -0x74,0x65,0x67,0x6f,0x72,0x79,0xc3,0x17,0x10,0x6f,0x1f,0x73,0x69,0x74,0x69,0x6f, -0x6e,0x61,0x6c,0x63,0x61,0x74,0x65,0x67,0x6f,0x72,0x79,0xc3,0x16,0x10,0x63,0xc3, -0x16,2,0x67,0xc3,6,0x6f,0x26,0x74,0xc3,7,0x11,0x69,0x6e,1,0x63,0x4a, -0x69,0x11,0x6e,0x67,1,0x67,0x2e,0x74,0x12,0x79,0x70,0x65,0xc3,7,0x13,0x72, -0x6f,0x75,0x70,0xc3,6,0x48,0x15,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x49,0x66,0x86, -0x67,0xa2,0x4a,0x68,3,0x61,0x36,0x65,0x58,0x73,0x68,0x79,0x13,0x70,0x68,0x65, -0x6e,0x3d,0x1f,0x6e,0x67,0x75,0x6c,0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x74, -0x79,0x70,0x65,0xc3,0xb,0x10,0x78,0x3a,0x14,0x64,0x69,0x67,0x69,0x74,0x3b,0x10, -0x74,0xc3,0xb,0x16,0x75,0x6c,0x6c,0x63,0x6f,0x6d,0x70,0x1f,0x6f,0x73,0x69,0x74, -0x69,0x6f,0x6e,0x65,0x78,0x63,0x6c,0x75,0x73,0x69,0x6f,0x6e,0x33,2,0x63,0xa2, -0x44,0x65,0xa2,0x4b,0x72,3,0x61,0x34,0x62,0x84,0x65,0x8a,0x6c,0x12,0x69,0x6e, -0x6b,0x39,0x11,0x70,0x68,0x7c,0x12,0x65,0x6d,0x65,3,0x62,0x5e,0x63,0x30,0x65, -0x48,0x6c,0x12,0x69,0x6e,0x6b,0x39,0x1a,0x6c,0x75,0x73,0x74,0x65,0x72,0x62,0x72, -0x65,0x61,0x6b,0xc3,0x12,0x14,0x78,0x74,0x65,0x6e,0x64,0x37,0x12,0x61,0x73,0x65, -0x35,0x11,0x78,0x74,0x37,0xc2,5,1,0x62,0xc3,0x12,0x6d,0xd9,0x20,0,0x1c, -0x6e,0x65,0x72,0x61,0x6c,0x63,0x61,0x74,0x65,0x67,0x6f,0x72,0x79,0xc2,5,0x13, -0x6d,0x61,0x73,0x6b,0xd9,0x20,0,0x61,0xa2,0xa2,0x62,0xa2,0xd0,0x63,0xa4,0x4f, -0x64,0xa6,0x1c,0x65,5,0x6d,0x75,0x6d,0x6e,0x70,0xa2,0x6b,0x78,0x10,0x74,0x30, -1,0x65,0x2c,0x70,0x12,0x69,0x63,0x74,0xa1,0x12,0x6e,0x64,0x65,1,0x64,0x24, -0x72,0x31,0x1b,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0xa1, -0x10,0x6f,1,0x64,0x97,0x6a,0x10,0x69,0x92,3,0x63,0x44,0x6b,0x54,0x6d,0x70, -0x70,0x1a,0x72,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x95,0x17,0x6f, -0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x9b,0x1c,0x65,0x79,0x63,0x61,0x70,0x73,0x65, -0x71,0x75,0x65,0x6e,0x63,0x65,0xa3,0x42,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72, -0x96,0x13,0x62,0x61,0x73,0x65,0x99,0x12,0x72,0x65,0x73,0x95,0x61,0x30,0x62,0x4e, -0x63,0x12,0x6f,0x6d,0x70,0x9b,0xc2,4,0x1b,0x73,0x74,0x61,0x73,0x69,0x61,0x6e, -0x77,0x69,0x64,0x74,0x68,0xc3,4,0x12,0x61,0x73,0x65,0x99,3,0x67,0x44,0x68, -0x4a,0x6c,0x4e,0x73,0x1a,0x63,0x69,0x69,0x68,0x65,0x78,0x64,0x69,0x67,0x69,0x74, -0x23,0x10,0x65,0xd9,0x40,0,0x11,0x65,0x78,0x23,1,0x6e,0x38,0x70,0x11,0x68, -0x61,0x20,0x14,0x62,0x65,0x74,0x69,0x63,0x21,0x11,0x75,0x6d,0x79,5,0x6c,0x22, -0x6c,0x36,0x6d,0x52,0x70,1,0x62,0xd9,0x40,0xd,0x74,0xc3,0x15,2,0x61,0x32, -0x6b,0xc3,1,0x6f,0x11,0x63,0x6b,0xc3,1,0x11,0x6e,0x6b,0x7b,0x10,0x67,0xd9, -0x40,1,0x61,0xa2,0x4f,0x63,0xc3,0,0x69,0x11,0x64,0x69,2,0x63,0x54,0x6d, -0x74,0x70,0x1b,0x61,0x69,0x72,0x65,0x64,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0xd8, -0x40,0xd,0x13,0x74,0x79,0x70,0x65,0xc3,0x15,0x24,1,0x6c,0x30,0x6f,0x14,0x6e, -0x74,0x72,0x6f,0x6c,0x25,0x12,0x61,0x73,0x73,0xc3,0,0x26,0x14,0x69,0x72,0x72, -0x6f,0x72,1,0x65,0x38,0x69,0x16,0x6e,0x67,0x67,0x6c,0x79,0x70,0x68,0xd9,0x40, -1,0x10,0x64,0x27,0x17,0x73,0x69,0x63,0x65,0x6d,0x6f,0x6a,0x69,0xa3,0x41,6, -0x68,0x7c,0x68,0x54,0x69,0x85,0x6f,0xa2,0x6f,0x77,4,0x63,0x30,0x6b,0x36,0x6c, -0x87,0x74,0x8b,0x75,0x89,1,0x66,0x8d,0x6d,0x8f,0x11,0x63,0x66,0x91,0x18,0x61, -0x6e,0x67,0x65,0x73,0x77,0x68,0x65,0x6e,4,0x63,0x44,0x6c,0x6c,0x6e,0x7e,0x74, -0x98,0x75,0x18,0x70,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x64,0x89,0x12,0x61,0x73, -0x65,1,0x66,0x30,0x6d,0x14,0x61,0x70,0x70,0x65,0x64,0x8f,0x14,0x6f,0x6c,0x64, -0x65,0x64,0x8d,0x18,0x6f,0x77,0x65,0x72,0x63,0x61,0x73,0x65,0x64,0x87,0x1c,0x66, -0x6b,0x63,0x63,0x61,0x73,0x65,0x66,0x6f,0x6c,0x64,0x65,0x64,0x91,0x18,0x69,0x74, -0x6c,0x65,0x63,0x61,0x73,0x65,0x64,0x8b,0x13,0x6d,0x70,0x65,0x78,0x33,0x61,0x2e, -0x63,0xa2,0x48,0x66,0xd9,0x40,2,1,0x6e,0x72,0x73,0x10,0x65,3,0x64,0x83, -0x66,0x3a,0x69,0x4a,0x73,0x17,0x65,0x6e,0x73,0x69,0x74,0x69,0x76,0x65,0x65,0x15, -0x6f,0x6c,0x64,0x69,0x6e,0x67,0xd9,0x40,2,0x17,0x67,0x6e,0x6f,0x72,0x61,0x62, -0x6c,0x65,0x85,0x13,0x6f,0x6e,0x69,0x63,0x1f,0x61,0x6c,0x63,0x6f,0x6d,0x62,0x69, -0x6e,0x69,0x6e,0x67,0x63,0x6c,0x61,0x73,0x73,0xc3,2,0x10,0x63,0xc3,2,3, -0x61,0x30,0x65,0x34,0x69,0xa2,0x41,0x74,0xc3,3,0x11,0x73,0x68,0x29,2,0x63, -0x3a,0x66,0x58,0x70,0x2c,0x16,0x72,0x65,0x63,0x61,0x74,0x65,0x64,0x2d,0x1d,0x6f, -0x6d,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x74,0x79,0x70,0x65,0xc3,3,0x15, -0x61,0x75,0x6c,0x74,0x69,0x67,0x1f,0x6e,0x6f,0x72,0x61,0x62,0x6c,0x65,0x63,0x6f, -0x64,0x65,0x70,0x6f,0x69,0x6e,0x74,0x2b,0x2a,0x10,0x61,0x2e,0x15,0x63,0x72,0x69, -0x74,0x69,0x63,0x2f,3,0x66,0x34,0x6e,0x3e,0x74,0x42,0x79,0x22,0x11,0x65,0x73, -0x23,0x20,0x13,0x61,0x6c,0x73,0x65,0x21,0x20,0x10,0x6f,0x21,0x22,0x12,0x72,0x75, -0x65,0x23,0xb,0x6b,0x5b,0x6f,0x23,0x6f,0x3c,0x72,0x4c,0x76,1,0x69,0x24,0x72, -0x33,0x13,0x72,0x61,0x6d,0x61,0x33,0x10,0x76,0x22,0x14,0x65,0x72,0x6c,0x61,0x79, -0x23,0xa2,0xe2,0x13,0x69,0x67,0x68,0x74,0xa3,0xe2,0x6b,0x58,0x6c,0x74,0x6e,3, -0x6b,0x2f,0x6f,0x30,0x72,0x21,0x75,0x12,0x6b,0x74,0x61,0x2f,0x19,0x74,0x72,0x65, -0x6f,0x72,0x64,0x65,0x72,0x65,0x64,0x21,1,0x61,0x24,0x76,0x31,0x18,0x6e,0x61, -0x76,0x6f,0x69,0x63,0x69,0x6e,0x67,0x31,0xa2,0xe0,0x12,0x65,0x66,0x74,0xa3,0xe0, -0x64,0x45,0x64,0x4e,0x68,0x88,0x69,1,0x6f,0x26,0x73,0xa3,0xf0,0x1a,0x74,0x61, -0x73,0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74,0xa3,0xf0,2,0x61,0xa3,0xea,0x62, -0xa3,0xe9,0x6f,0x13,0x75,0x62,0x6c,0x65,1,0x61,0x30,0x62,0x13,0x65,0x6c,0x6f, -0x77,0xa3,0xe9,0x13,0x62,0x6f,0x76,0x65,0xa3,0xea,0x12,0x61,0x6e,0x72,0x2c,0x15, -0x65,0x61,0x64,0x69,0x6e,0x67,0x2d,0x61,0xa2,0x7b,0x62,0xa2,0xd4,0x63,0x11,0x63, -0x63,4,0x31,0x3c,0x32,0xa2,0x42,0x33,0xa2,0x56,0x38,0xa2,0x64,0x39,0x10,0x31, -0xa3,0x5b,9,0x35,0xa,0x35,0x3f,0x36,0x41,0x37,0x43,0x38,0x45,0x39,0x47,0x30, -0x30,0x31,0x3c,0x32,0x42,0x33,0x4e,0x34,0x3d,0x34,1,0x33,0xa3,0x67,0x37,0xa3, -0x6b,0x36,0x10,0x38,0xa3,0x76,0x38,1,0x32,0xa3,0x7a,0x39,0xa3,0x81,0x3a,2, -0x30,0xa3,0x82,0x32,0xa3,0x84,0x33,0xa3,0x85,9,0x35,0xa,0x35,0x53,0x36,0x55, -0x37,0x57,0x38,0x59,0x39,0x5b,0x30,0x49,0x31,0x4b,0x32,0x4d,0x33,0x4f,0x34,0x51, -6,0x33,8,0x33,0x63,0x34,0x65,0x35,0x67,0x36,0x69,0x30,0x5d,0x31,0x5f,0x32, -0x61,0x10,0x34,0xa3,0x54,0xa2,0xe6,3,0x62,0xa0,0x6c,0xa3,0xe4,0x72,0xa3,0xe8, -0x74,2,0x61,0x74,0x62,0x7c,0x74,0x14,0x61,0x63,0x68,0x65,0x64,1,0x61,0x3e, -0x62,0x13,0x65,0x6c,0x6f,0x77,0xa2,0xca,0x13,0x6c,0x65,0x66,0x74,0xa3,0xc8,0x13, -0x62,0x6f,0x76,0x65,0xa2,0xd6,0x14,0x72,0x69,0x67,0x68,0x74,0xa3,0xd8,0xa2,0xd6, -0x10,0x72,0xa3,0xd8,0xa2,0xca,0x10,0x6c,0xa3,0xc8,0x12,0x6f,0x76,0x65,0xa2,0xe6, -1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xe8,0x12,0x65,0x66,0x74,0xa3, -0xe4,0xa2,0xdc,2,0x65,0x2c,0x6c,0xa3,0xda,0x72,0xa3,0xde,0x12,0x6c,0x6f,0x77, -0xa2,0xdc,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xde,0x12,0x65,0x66, -0x74,0xa3,0xda,0xb,0x6e,0xc0,0xca,0x72,0x5f,0x72,0x46,0x73,0xa2,0x48,0x77,1, -0x68,0x24,0x73,0x33,0x17,0x69,0x74,0x65,0x73,0x70,0x61,0x63,0x65,0x33,0x22,1, -0x69,0x30,0x6c,2,0x65,0x3d,0x69,0x4b,0x6f,0x3f,0x18,0x67,0x68,0x74,0x74,0x6f, -0x6c,0x65,0x66,0x74,0x22,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72,0x72, -0x69,0x64,0x65,0x3f,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x3d,0x15,0x73, -0x6f,0x6c,0x61,0x74,0x65,0x4b,0x30,0x1e,0x65,0x67,0x6d,0x65,0x6e,0x74,0x73,0x65, -0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x31,0x6e,0xa2,0x41,0x6f,0xa2,0x53,0x70,2, -0x61,0x66,0x64,0x86,0x6f,0x1b,0x70,0x64,0x69,0x72,0x65,0x63,0x74,0x69,0x6f,0x6e, -0x61,0x6c,1,0x66,0x32,0x69,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4d,0x14,0x6f, -0x72,0x6d,0x61,0x74,0x41,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70, -0x61,0x72,0x61,0x74,0x6f,0x72,0x2f,1,0x66,0x41,0x69,0x4d,1,0x6f,0x28,0x73, -0x10,0x6d,0x43,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b, -0x43,1,0x6e,0x35,0x74,0x19,0x68,0x65,0x72,0x6e,0x65,0x75,0x74,0x72,0x61,0x6c, -0x35,0x65,0x88,0x65,0x98,0x66,0xa2,0x6a,0x6c,0x20,1,0x65,0x30,0x72,2,0x65, -0x37,0x69,0x49,0x6f,0x39,0x18,0x66,0x74,0x74,0x6f,0x72,0x69,0x67,0x68,0x74,0x20, -2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72,0x72,0x69,0x64,0x65,0x39,0x17, -0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x37,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65, -0x49,3,0x6e,0x25,0x73,0x27,0x74,0x29,0x75,0x15,0x72,0x6f,0x70,0x65,0x61,0x6e, -2,0x6e,0x3c,0x73,0x46,0x74,0x18,0x65,0x72,0x6d,0x69,0x6e,0x61,0x74,0x6f,0x72, -0x29,0x14,0x75,0x6d,0x62,0x65,0x72,0x25,0x17,0x65,0x70,0x61,0x72,0x61,0x74,0x6f, -0x72,0x27,1,0x69,0x28,0x73,0x10,0x69,0x47,0x1f,0x72,0x73,0x74,0x73,0x74,0x72, -0x6f,0x6e,0x67,0x69,0x73,0x6f,0x6c,0x61,0x74,0x65,0x47,0x61,0x4e,0x62,0x84,0x63, -1,0x6f,0x24,0x73,0x2d,0x1c,0x6d,0x6d,0x6f,0x6e,0x73,0x65,0x70,0x61,0x72,0x61, -0x74,0x6f,0x72,0x2d,2,0x6c,0x3b,0x6e,0x2b,0x72,0x13,0x61,0x62,0x69,0x63,1, -0x6c,0x30,0x6e,0x14,0x75,0x6d,0x62,0x65,0x72,0x2b,0x14,0x65,0x74,0x74,0x65,0x72, -0x3b,0x2e,1,0x6e,0x45,0x6f,0x1c,0x75,0x6e,0x64,0x61,0x72,0x79,0x6e,0x65,0x75, -0x74,0x72,0x61,0x6c,0x45,0,0x16,0x6d,0xc9,0x20,0x74,0xc2,0x30,0x77,0x89,0x77, -0x86,0x79,0xa2,0x46,0x7a,1,0x61,0x58,0x6e,0x1a,0x61,0x6d,0x65,0x6e,0x6e,0x79, -0x6d,0x75,0x73,0x69,0x63,0xa4,0x40,0x19,0x61,0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69, -0x6f,0x6e,0xa5,0x40,0x1c,0x6e,0x61,0x62,0x61,0x7a,0x61,0x72,0x73,0x71,0x75,0x61, -0x72,0x65,0xa5,0x18,0x10,0x61,1,0x6e,0x36,0x72,0x16,0x61,0x6e,0x67,0x63,0x69, -0x74,0x69,0xa3,0xfc,0x12,0x63,0x68,0x6f,0xa5,0x2c,1,0x65,0x88,0x69,2,0x6a, -0x3c,0x72,0x68,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3,0x48,0x12, -0x69,0x6e,0x67,0xa2,0x74,0x1e,0x68,0x65,0x78,0x61,0x67,0x72,0x61,0x6d,0x73,0x79, -0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x74,0x16,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0xa3, -0x49,0x13,0x7a,0x69,0x64,0x69,0xa5,0x34,0x74,0xa2,0x65,0x75,0xa4,0x4f,0x76,3, -0x61,0x3c,0x65,0x80,0x69,0xa2,0x50,0x73,0xa2,0x6c,0x12,0x73,0x75,0x70,0xa3,0x7d, -1,0x69,0xa3,0x9f,0x72,0x1e,0x69,0x61,0x74,0x69,0x6f,0x6e,0x73,0x65,0x6c,0x65, -0x63,0x74,0x6f,0x72,0x73,0xa2,0x6c,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65, -0x6e,0x74,0xa3,0x7d,1,0x64,0x3c,0x72,0x19,0x74,0x69,0x63,0x61,0x6c,0x66,0x6f, -0x72,0x6d,0x73,0xa3,0x91,0x14,0x69,0x63,0x65,0x78,0x74,0xa2,0xaf,0x16,0x65,0x6e, -0x73,0x69,0x6f,0x6e,0x73,0xa3,0xaf,0x15,0x74,0x68,0x6b,0x75,0x71,0x69,0xa5,0x3f, -5,0x69,0x3f,0x69,0x5a,0x6f,0x8c,0x72,0x1c,0x61,0x6e,0x73,0x70,0x6f,0x72,0x74, -0x61,0x6e,0x64,0x6d,0x61,0x70,0xa2,0xcf,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0xa3,0xcf,2,0x62,0x34,0x66,0x3c,0x72,0x13,0x68,0x75,0x74,0x61,0xa3,0xfb,0x13, -0x65,0x74,0x61,0x6e,0x57,0x14,0x69,0x6e,0x61,0x67,0x68,0xa3,0x90,0x11,0x74,0x6f, -0xa5,0x3d,0x61,0x3e,0x65,0xa2,0xa0,0x68,0x10,0x61,1,0x61,0x24,0x69,0x53,0x11, -0x6e,0x61,0x3d,4,0x67,0x8e,0x69,0xa2,0x49,0x6b,0xa2,0x72,0x6d,0xa2,0x74,0x6e, -0x10,0x67,1,0x73,0x68,0x75,0x10,0x74,0xa4,0x10,1,0x63,0x40,0x73,0x11,0x75, -0x70,0xa4,0x33,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x33,0x18,0x6f,0x6d, -0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0xa5,0x11,0x10,0x61,0xa5,0x3c,2,0x61,0x2a, -0x62,0x32,0x73,0xa3,0x60,0x12,0x6c,0x6f,0x67,0xa3,0x62,0x13,0x61,0x6e,0x77,0x61, -0xa3,0x65,3,0x6c,0x52,0x74,0x56,0x76,0x5e,0x78,0x16,0x75,0x61,0x6e,0x6a,0x69, -0x6e,0x67,0xa2,0x7c,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x7c,0x10,0x65, -0xa3,0x70,0x12,0x68,0x61,0x6d,0xa3,0xae,0x12,0x69,0x65,0x74,0xa3,0xb7,0x11,0x72, -0x69,0xa3,0xdc,0x11,0x69,0x6c,0x48,0x12,0x73,0x75,0x70,0xa4,0x2b,0x16,0x70,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0xa5,0x2b,0x13,0x6c,0x75,0x67,0x75,0x4b,2,0x63,0x8c, -0x67,0xa2,0x41,0x6e,0x1f,0x69,0x66,0x69,0x65,0x64,0x63,0x61,0x6e,0x61,0x64,0x69, -0x61,0x6e,0x61,0x62,0x6f,0x1f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x73,0x79,0x6c, -0x6c,0x61,0x62,0x69,0x63,0x73,0x62,0x17,0x65,0x78,0x74,0x65,0x6e,0x64,0x65,0x64, -0xa2,0xad,0x10,0x61,0xa5,0x3e,0x11,0x61,0x73,0x62,0x12,0x65,0x78,0x74,0xa2,0xad, -0x10,0x61,0xa5,0x3e,0x15,0x61,0x72,0x69,0x74,0x69,0x63,0xa3,0x78,0x70,0xc3,0x4b, -0x70,0xa6,0x61,0x72,0xa8,0x1d,0x73,7,0x6f,0xc1,0xbe,0x6f,0xa2,0x69,0x70,0xa2, -0x85,0x75,0xa2,0xa4,0x79,2,0x6c,0x50,0x6d,0x62,0x72,0x12,0x69,0x61,0x63,0x3a, -0x12,0x73,0x75,0x70,0xa4,0x17,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x17, -0x17,0x6f,0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0xa3,0x8f,0x13,0x62,0x6f,0x6c,0x73, -1,0x61,0x4c,0x66,0x10,0x6f,0x1f,0x72,0x6c,0x65,0x67,0x61,0x63,0x79,0x63,0x6f, -0x6d,0x70,0x75,0x74,0x69,0x6e,0x67,0xa5,0x32,0x1f,0x6e,0x64,0x70,0x69,0x63,0x74, -0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x78,0x74,1,0x61,0xa5,0x2a,0x65,0x14, -0x6e,0x64,0x65,0x64,0x61,0xa5,0x2a,2,0x67,0x34,0x72,0x3e,0x79,0x13,0x6f,0x6d, -0x62,0x6f,0xa5,0x16,0x13,0x64,0x69,0x61,0x6e,0xa5,0x23,0x17,0x61,0x73,0x6f,0x6d, -0x70,0x65,0x6e,0x67,0xa3,0xda,1,0x61,0x32,0x65,0x14,0x63,0x69,0x61,0x6c,0x73, -0xa3,0x56,0x12,0x63,0x69,0x6e,0x1f,0x67,0x6d,0x6f,0x64,0x69,0x66,0x69,0x65,0x72, -0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,2,0x6e,0x48,0x70,0x76,0x74,0x1d,0x74, -0x6f,0x6e,0x73,0x69,0x67,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa5,6,0x15, -0x64,0x61,0x6e,0x65,0x73,0x65,0xa2,0x9b,0x12,0x73,0x75,0x70,0xa2,0xdb,0x16,0x70, -0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xdb,4,0x61,0xa2,0xa8,0x65,0x5c,0x6d,0x9e, -0x70,0xa2,0x4b,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70, -0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5,0x10,0x72,1,0x61, -0x4e,0x73,0x12,0x63,0x72,0x69,0x1f,0x70,0x74,0x73,0x61,0x6e,0x64,0x73,0x75,0x62, -0x73,0x63,0x72,0x69,0x70,0x74,0x73,0x73,0x14,0x6e,0x64,0x73,0x75,0x62,0x73,0x1b, -0x61,0x74,0x68,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,1,0x6c, -0x40,0x75,1,0x61,0x6e,0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3, -0x8e,0x15,0x65,0x6d,0x65,0x6e,0x74,0x61,1,0x6c,0x50,0x72,0x1e,0x79,0x70,0x72, -0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0x61,0x72,0x65,0x61,1,0x61,0xa3,0x6d, -0x62,0xa3,0x6e,3,0x61,0x5c,0x6d,0x78,0x70,0xa2,0x41,0x73,0x13,0x79,0x6d,0x62, -0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70, -0x68,0x73,0xa5,5,0x14,0x72,0x72,0x6f,0x77,0x73,2,0x61,0xa3,0x67,0x62,0xa3, -0x68,0x63,0xa3,0xfa,0x13,0x61,0x74,0x68,0x65,0x1f,0x6d,0x61,0x74,0x69,0x63,0x61, -0x6c,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,0x19,0x75,0x6e,0x63, -0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x61,0x88,0x68,0xa2,0x48,0x69,0xa2, -0x71,0x6d,0x12,0x61,0x6c,0x6c,1,0x66,0x46,0x6b,0x15,0x61,0x6e,0x61,0x65,0x78, -0x74,0xa4,0x29,0x15,0x65,0x6e,0x73,0x69,0x6f,0x6e,0xa5,0x29,0x12,0x6f,0x72,0x6d, -1,0x73,0xa3,0x54,0x76,0x16,0x61,0x72,0x69,0x61,0x6e,0x74,0x73,0xa3,0x54,1, -0x6d,0x36,0x75,0x16,0x72,0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0xa1,0x15,0x61,0x72, -0x69,0x74,0x61,0x6e,0xa3,0xac,1,0x61,0x52,0x6f,0x13,0x72,0x74,0x68,0x61,0x1f, -0x6e,0x64,0x66,0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73, -0xa3,0xf7,1,0x72,0x2e,0x76,0x12,0x69,0x61,0x6e,0xa3,0x79,0x12,0x61,0x64,0x61, -0xa3,0xd9,1,0x64,0x50,0x6e,0x13,0x68,0x61,0x6c,0x61,0x50,0x1d,0x61,0x72,0x63, -0x68,0x61,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xf9,0x13,0x64,0x68, -0x61,0x6d,0xa3,0xf8,5,0x72,0x35,0x72,0x44,0x73,0x64,0x75,1,0x61,0xa3,0x4e, -0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x69,0x76,0x61,0x74, -0x65,0x75,0x73,0x65,0xa2,0x4e,0x13,0x61,0x72,0x65,0x61,0xa3,0x4e,0x1b,0x61,0x6c, -0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76,0x69,0xa3,0xf6,0x61,0x40,0x68,0x82, -0x6c,0x19,0x61,0x79,0x69,0x6e,0x67,0x63,0x61,0x72,0x64,0x73,0xa3,0xcc,2,0x68, -0x38,0x6c,0x4a,0x75,0x15,0x63,0x69,0x6e,0x68,0x61,0x75,0xa3,0xf5,0x17,0x61,0x77, -0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0xf3,0x15,0x6d,0x79,0x72,0x65,0x6e,0x65,0xa3, -0xf4,1,0x61,0x8e,0x6f,1,0x65,0x74,0x6e,0x16,0x65,0x74,0x69,0x63,0x65,0x78, -0x74,0xa2,0x72,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0x8d,0x15,0x6e,0x73,0x69, -0x6f,0x6e,0x73,0xa2,0x72,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, -0xa3,0x8d,0x15,0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x97,1,0x67,0x3e,0x69,0x13, -0x73,0x74,0x6f,0x73,0xa2,0xa6,0x13,0x64,0x69,0x73,0x63,0xa3,0xa6,0x12,0x73,0x70, -0x61,0xa3,0x96,1,0x65,0x5c,0x75,1,0x6d,0x2a,0x6e,0x11,0x69,0x63,0x67,0x10, -0x69,0xa2,0xc0,0x1d,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0xa3,0xc0,0x13,0x6a,0x61,0x6e,0x67,0xa3,0xa3,0x6d,0xa2,0xf0,0x6e,0xa8, -0x23,0x6f,6,0x70,0x63,0x70,0x56,0x72,0x8a,0x73,0xa2,0x4c,0x74,0x10,0x74,0x1f, -0x6f,0x6d,0x61,0x6e,0x73,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73, -0xa5,0x28,0x18,0x74,0x69,0x63,0x61,0x6c,0x63,0x68,0x61,0x72,0x1f,0x61,0x63,0x74, -0x65,0x72,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x74,0x69,0x6f,0x6e,0x85,1,0x69, -0x46,0x6e,0x1e,0x61,0x6d,0x65,0x6e,0x74,0x61,0x6c,0x64,0x69,0x6e,0x67,0x62,0x61, -0x74,0x73,0xa3,0xf2,0x11,0x79,0x61,0x47,1,0x61,0x30,0x6d,0x13,0x61,0x6e,0x79, -0x61,0xa3,0x7a,0x11,0x67,0x65,0xa5,0xf,0x63,0xa2,0x7b,0x67,0xa2,0x7b,0x6c,1, -0x63,0xa2,0x6c,0x64,6,0x70,0x42,0x70,0x3a,0x73,0x5a,0x74,0x88,0x75,0x14,0x79, -0x67,0x68,0x75,0x72,0xa5,0x3b,0x11,0x65,0x72,1,0x6d,0x2e,0x73,0x12,0x69,0x61, -0x6e,0xa3,0x8c,0x11,0x69,0x63,0xa3,0xf1,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74, -0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xbb,0x13,0x64,0x69,0x61,0x6e,0xa5, -0x22,0x14,0x75,0x72,0x6b,0x69,0x63,0xa3,0xbf,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f, -0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xf0,0x17,0x75,0x6e,0x67, -0x61,0x72,0x69,0x61,0x6e,0xa5,4,0x14,0x74,0x61,0x6c,0x69,0x63,0xa3,0x58,0x13, -0x68,0x69,0x6b,0x69,0xa3,0x9d,0x10,0x72,0x85,0x12,0x68,0x61,0x6d,0x65,6,0x6f, -0x86,0x6f,0x6c,0x72,0xa2,0x61,0x75,0xa2,0x62,0x79,0x14,0x61,0x6e,0x6d,0x61,0x72, -0x58,0x12,0x65,0x78,0x74,2,0x61,0xa3,0xb6,0x62,0xa3,0xee,0x65,0x13,0x6e,0x64, -0x65,0x64,1,0x61,0xa3,0xb6,0x62,0xa3,0xee,1,0x64,0x52,0x6e,0x15,0x67,0x6f, -0x6c,0x69,0x61,0x6e,0x6a,0x12,0x73,0x75,0x70,0xa4,0xd,0x16,0x70,0x6c,0x65,0x6d, -0x65,0x6e,0x74,0xa5,0xd,0x10,0x69,0xa2,0xec,0x13,0x66,0x69,0x65,0x72,1,0x6c, -0x3c,0x74,0x19,0x6f,0x6e,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0xa3,0x8a,0x15, -0x65,0x74,0x74,0x65,0x72,0x73,0x2d,0x10,0x6f,0xa3,0xed,1,0x6c,0x44,0x73,0x11, -0x69,0x63,0xa2,0x5c,0x18,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5c, -0x13,0x74,0x61,0x6e,0x69,0xa5,3,0x61,0xa2,0x9b,0x65,0xa4,0x4c,0x69,1,0x61, -0xa2,0x8f,0x73,0x10,0x63,5,0x70,0x18,0x70,0xa2,0x71,0x73,0x36,0x74,0x17,0x65, -0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8f, -0x61,0xa2,0x66,0x65,0x46,0x6d,0x19,0x61,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c, -0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x17,0x6c,0x6c,0x61,0x6e,0x65,0x6f,0x75, -0x73,2,0x6d,0x3a,0x73,0x6c,0x74,0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c, -0x81,0x11,0x61,0x74,0x1f,0x68,0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x73,0x79, -0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x15,0x79,0x6d,0x62, -0x6f,0x6c,0x73,0x8e,0x12,0x61,0x6e,0x64,1,0x61,0x3c,0x70,0x19,0x69,0x63,0x74, -0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa3,0xcd,0x14,0x72,0x72,0x6f,0x77,0x73,0xa3, -0x73,0x10,0x6f,0xa3,0xd8,7,0x72,0x6f,0x72,0x44,0x73,0x4e,0x74,0x62,0x79,0x19, -0x61,0x6e,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0xa5,0x20,0x13,0x63,0x68,0x65, -0x6e,0xa5,0xc,0x18,0x61,0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa5,0x14,0x10, -0x68,2,0x61,0x3a,0x65,0x4a,0x6f,0x17,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73, -0x7f,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d,0xa3,0x5d,0x16,0x6d,0x61,0x74,0x69, -0x63,0x61,0x6c,1,0x61,0x36,0x6f,0x17,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73, -0x7f,0x11,0x6c,0x70,0x1f,0x68,0x61,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x73,0x79, -0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5d,0x68,0x50,0x6b,0x7e,0x6c,0x88,0x6e,1,0x64, -0x34,0x69,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3,0xea,0x12,0x61,0x69,0x63,0xa3, -0xc6,1,0x61,0x3e,0x6a,0x12,0x6f,0x6e,0x67,0xa2,0xaa,0x14,0x74,0x69,0x6c,0x65, -0x73,0xa3,0xaa,0x13,0x6a,0x61,0x6e,0x69,0xa3,0xe9,0x13,0x61,0x73,0x61,0x72,0xa5, -0x1f,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x4f,3,0x64,0x6c,0x65,0x7e,0x6e,0xa2, -0x47,0x72,0x14,0x6f,0x69,0x74,0x69,0x63,1,0x63,0x3c,0x68,0x19,0x69,0x65,0x72, -0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xd7,0x15,0x75,0x72,0x73,0x69,0x76,0x65, -0xa3,0xd6,0x17,0x65,0x66,0x61,0x69,0x64,0x72,0x69,0x6e,0xa5,0x21,0x17,0x74,0x65, -0x69,0x6d,0x61,0x79,0x65,0x6b,0xa2,0xb8,0x12,0x65,0x78,0x74,0xa2,0xd5,0x16,0x65, -0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xd5,0x18,0x64,0x65,0x6b,0x69,0x6b,0x61,0x6b, -0x75,0x69,0xa3,0xeb,6,0x6b,0x3b,0x6b,0x56,0x6f,0x5a,0x75,0x64,0x79,0x11,0x69, -0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61,0x63,0x68,0x75,0x65,0x68,0x6d,0x6f, -0x6e,0x67,0xa5,0x27,0x10,0x6f,0xa3,0x92,0x14,0x62,0x6c,0x6f,0x63,0x6b,0x21,1, -0x6d,0x2c,0x73,0x11,0x68,0x75,0xa5,0x15,0x17,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d, -0x73,0x7b,0x61,0x44,0x62,0x21,0x65,0x10,0x77,1,0x61,0xa5,0xe,0x74,0x14,0x61, -0x69,0x6c,0x75,0x65,0xa3,0x8b,2,0x62,0x3c,0x67,0x4a,0x6e,0x17,0x64,0x69,0x6e, -0x61,0x67,0x61,0x72,0x69,0xa5,0x26,0x15,0x61,0x74,0x61,0x65,0x61,0x6e,0xa3,0xef, -0x16,0x6d,0x75,0x6e,0x64,0x61,0x72,0x69,0xa5,0x47,0x67,0xc4,0x5d,0x6a,0xc1,0xe4, -0x6a,0xa2,0xdf,0x6b,0xa2,0xf8,0x6c,4,0x61,0x54,0x65,0xa2,0x6b,0x69,0xa2,0x82, -0x6f,0xa2,0xc1,0x79,1,0x63,0x2e,0x64,0x12,0x69,0x61,0x6e,0xa3,0xa9,0x12,0x69, -0x61,0x6e,0xa3,0xa7,1,0x6f,0x55,0x74,0x11,0x69,0x6e,1,0x31,0x96,0x65,0x11, -0x78,0x74,6,0x64,0x21,0x64,0xa3,0x95,0x65,0x2c,0x66,0xa5,0x39,0x67,0xa5,0x3a, -0xa2,0xe7,0x13,0x6e,0x64,0x65,0x64,6,0x64,0xc,0x64,0xa3,0x95,0x65,0xa3,0xe7, -0x66,0xa5,0x39,0x67,0xa5,0x3a,0x61,0x2a,0x62,0x29,0x63,0xa3,0x94,0x26,0x18,0x64, -0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x6d,0x24,0x12,0x73,0x75,0x70,0x24,0x16, -0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x25,1,0x70,0x42,0x74,0x1d,0x74,0x65,0x72, -0x6c,0x69,0x6b,0x65,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x79,0x12,0x63,0x68,0x61, -0xa3,0x9c,2,0x6d,0x4e,0x6e,0x54,0x73,0x10,0x75,0xa2,0xb0,0x12,0x73,0x75,0x70, -0xa4,0x31,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x31,0x11,0x62,0x75,0xa3, -0x6f,0x12,0x65,0x61,0x72,1,0x61,0xa3,0xe8,0x62,1,0x69,0x38,0x73,0x17,0x79, -0x6c,0x6c,0x61,0x62,0x61,0x72,0x79,0xa3,0x75,0x17,0x64,0x65,0x6f,0x67,0x72,0x61, -0x6d,0x73,0xa3,0x76,0x1a,0x77,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73, -0xa3,0x4d,0x10,0x61,1,0x6d,0x32,0x76,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0xb5, -0x10,0x6f,0x5c,0x12,0x65,0x78,0x74,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,1,0x61, -0xa2,0x43,0x68,4,0x61,0x40,0x69,0x50,0x6d,0x6e,0x6f,0x86,0x75,0x15,0x64,0x61, -0x77,0x61,0x64,0x69,0xa3,0xe6,0x16,0x72,0x6f,0x73,0x68,0x74,0x68,0x69,0xa3,0x89, -0x1d,0x74,0x61,0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73,0x63,0x72,0x69,0x70,0x74,0xa5, -0x30,0x11,0x65,0x72,0x68,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x71,0x12, -0x6a,0x6b,0x69,0xa3,0xe5,5,0x74,0x35,0x74,0x34,0x77,0x7a,0x79,0x13,0x61,0x68, -0x6c,0x69,0xa3,0xa2,0x14,0x61,0x6b,0x61,0x6e,0x61,0x9e,1,0x65,0x4c,0x70,0x10, -0x68,0x1f,0x6f,0x6e,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f, -0x6e,0x73,0xa3,0x6b,0x11,0x78,0x74,0xa3,0x6b,0x10,0x69,0xa5,0x46,0x69,0xa2,0x4e, -0x6b,0xa2,0x51,0x6e,3,0x61,0x34,0x62,0x84,0x67,0x8a,0x6e,0x12,0x61,0x64,0x61, -0x4d,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0xcb,0x16,0x70,0x6c,0x65,0x6d,0x65, -0x6e,0x74,0xa3,0xcb,0x11,0x78,0x74,2,0x61,0xa5,0x13,0x62,0xa5,0x38,0x65,0x13, -0x6e,0x64,0x65,0x64,1,0x61,0xa5,0x13,0x62,0xa5,0x38,0x11,0x75,0x6e,0xa3,0x42, -0x11,0x78,0x69,0x96,0x17,0x72,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x97,0x12,0x74, -0x68,0x69,0xa3,0xc1,0x1c,0x74,0x6f,0x76,0x69,0x6b,0x6e,0x75,0x6d,0x65,0x72,0x61, -0x6c,0x73,0xa5,0x45,0x67,0xa2,0xb5,0x68,0xa4,0x84,0x69,3,0x64,0x4c,0x6d,0xa2, -0x55,0x6e,0xa2,0x62,0x70,0x13,0x61,0x65,0x78,0x74,0x2a,0x16,0x65,0x6e,0x73,0x69, -0x6f,0x6e,0x73,0x2b,1,0x63,0x99,0x65,0x17,0x6f,0x67,0x72,0x61,0x70,0x68,0x69, -0x63,1,0x64,0x56,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa4,0xb,0x1d,0x61, -0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa5,0xb,0x13, -0x65,0x73,0x63,0x72,0x1f,0x69,0x70,0x74,0x69,0x6f,0x6e,0x63,0x68,0x61,0x72,0x61, -0x63,0x74,0x65,0x72,0x73,0x99,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61, -0x6d,0x61,0x69,0x63,0xa3,0xba,1,0x64,0x62,0x73,0x1b,0x63,0x72,0x69,0x70,0x74, -0x69,0x6f,0x6e,0x61,0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61, -0x6e,0xa3,0xbd,0x13,0x6c,0x61,0x76,0x69,0xa3,0xbe,0x11,0x69,0x63,1,0x6e,0x3e, -0x73,0x1a,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa5,0x1e,0x19, -0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0xa3,0xb2,4,0x65,0x74,0x6c, -0xa2,0x82,0x6f,0xa2,0x9a,0x72,0xa2,0x9e,0x75,2,0x6a,0x34,0x6e,0x3e,0x72,0x14, -0x6d,0x75,0x6b,0x68,0x69,0x43,0x14,0x61,0x72,0x61,0x74,0x69,0x45,0x18,0x6a,0x61, -0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa5,0x1c,1,0x6e,0xa2,0x46,0x6f,1,0x6d, -0x6e,0x72,0x13,0x67,0x69,0x61,0x6e,0x5a,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2, -0x87,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x87,0x11,0x78,0x74,0xa4,0x1b, -0x14,0x65,0x6e,0x64,0x65,0x64,0xa5,0x1b,0x1a,0x65,0x74,0x72,0x69,0x63,0x73,0x68, -0x61,0x70,0x65,0x73,0x8c,0x12,0x65,0x78,0x74,0xa2,0xe3,0x14,0x65,0x6e,0x64,0x65, -0x64,0xa3,0xe3,0x1e,0x65,0x72,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, -0x69,0x6f,0x6e,0x71,0x17,0x61,0x67,0x6f,0x6c,0x69,0x74,0x69,0x63,0xa2,0x88,0x12, -0x73,0x75,0x70,0xa4,0xa,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0xa,0x13, -0x74,0x68,0x69,0x63,0xa3,0x59,1,0x61,0x5c,0x65,0x11,0x65,0x6b,0x30,1,0x61, -0x38,0x65,0x11,0x78,0x74,0x6e,0x14,0x65,0x6e,0x64,0x65,0x64,0x6f,0x17,0x6e,0x64, -0x63,0x6f,0x70,0x74,0x69,0x63,0x31,0x13,0x6e,0x74,0x68,0x61,0xa3,0xe4,2,0x61, -0xa2,0x48,0x65,0xa2,0xdf,0x69,1,0x67,0x30,0x72,0x14,0x61,0x67,0x61,0x6e,0x61, -0x9d,0x10,0x68,1,0x70,0x3a,0x73,0x18,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65, -0x73,0xa3,0x4b,1,0x72,0x3c,0x75,0x19,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74, -0x65,0x73,0xa3,0x4c,0x11,0x69,0x76,0x1f,0x61,0x74,0x65,0x75,0x73,0x65,0x73,0x75, -0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c,2,0x6c,0x32,0x6e,0x9a,0x74, -0x12,0x72,0x61,0x6e,0xa5,2,0x10,0x66,2,0x61,0x58,0x6d,0x70,0x77,0x14,0x69, -0x64,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66,0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68, -0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x1a,0x6e,0x64,0x66,0x75,0x6c,0x6c,0x66,0x6f, -0x72,0x6d,0x73,0xa3,0x57,0x13,0x61,0x72,0x6b,0x73,0xa3,0x52,2,0x67,0x34,0x69, -0xa2,0x45,0x75,0x12,0x6e,0x6f,0x6f,0xa3,0x63,0x11,0x75,0x6c,0xa2,0x4a,2,0x63, -0x3c,0x6a,0x5e,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3,0x4a,0x1f, -0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x6a,0x61,0x6d,0x6f, -0xa3,0x41,0x12,0x61,0x6d,0x6f,0x5c,0x17,0x65,0x78,0x74,0x65,0x6e,0x64,0x65,0x64, -1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,0x19,0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67, -0x79,0x61,0xa5,0x1d,0x13,0x62,0x72,0x65,0x77,0x37,0x61,0xa4,0xc,0x62,0xa6,0x59, -0x63,0xa8,0x2e,0x64,0xac,0xe3,0x65,5,0x6d,0xa9,0x6d,0x94,0x6e,0xa2,0x41,0x74, -0x15,0x68,0x69,0x6f,0x70,0x69,0x63,0x5e,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2, -0x86,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x86,0x11,0x78,0x74,0xa2,0x85, -2,0x61,0xa3,0xc8,0x62,0xa5,0x37,0x65,0x13,0x6e,0x64,0x65,0x64,0xa2,0x85,1, -0x61,0xa3,0xc8,0x62,0xa5,0x37,0x16,0x6f,0x74,0x69,0x63,0x6f,0x6e,0x73,0xa3,0xce, -0x15,0x63,0x6c,0x6f,0x73,0x65,0x64,2,0x61,0x5a,0x63,0x9e,0x69,0x1c,0x64,0x65, -0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x75,0x70,0xa2,0xc4,0x16,0x70,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc4,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d,0x86, -1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0xc3,0x13,0x72,0x69,0x63,0x73,0x86,0x18, -0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc3,0x11,0x6a,0x6b,0xa2,0x44, -0x1f,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x61,0x6e,0x64,0x6d,0x6f,0x6e,0x74,0x68, -0x73,0xa3,0x44,0x61,0x4a,0x67,0x76,0x6c,1,0x62,0x30,0x79,0x13,0x6d,0x61,0x69, -0x63,0xa5,0x25,0x13,0x61,0x73,0x61,0x6e,0xa3,0xe2,0x13,0x72,0x6c,0x79,0x64,0x1f, -0x79,0x6e,0x61,0x73,0x74,0x69,0x63,0x63,0x75,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d, -0xa5,1,0x1f,0x79,0x70,0x74,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c, -0x79,0x70,0x68,1,0x66,0x26,0x73,0xa3,0xc2,0x1c,0x6f,0x72,0x6d,0x61,0x74,0x63, -0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa5,0x24,7,0x6e,0xc0,0xf2,0x6e,0x3e,0x72, -0xa2,0x5d,0x73,0xa2,0xe5,0x76,0x14,0x65,0x73,0x74,0x61,0x6e,0xa3,0xbc,1,0x61, -0x92,0x63,0x13,0x69,0x65,0x6e,0x74,1,0x67,0x34,0x73,0x15,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0xa3,0xa5,0x13,0x72,0x65,0x65,0x6b,1,0x6d,0x34,0x6e,0x15,0x75,0x6d, -0x62,0x65,0x72,0x73,0xa3,0x7f,0x13,0x75,0x73,0x69,0x63,0xa2,0x7e,0x19,0x61,0x6c, -0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x7e,0x10,0x74,0x1f,0x6f,0x6c,0x69, -0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xfe,2, -0x61,0x32,0x6d,0xa2,0x7e,0x72,0x12,0x6f,0x77,0x73,0x7d,0x12,0x62,0x69,0x63,0x38, -3,0x65,0x4a,0x6d,0x80,0x70,0xa2,0x50,0x73,0x11,0x75,0x70,0xa2,0x80,0x16,0x70, -0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x80,0x11,0x78,0x74,3,0x61,0xa3,0xd2,0x62, -0xa5,0x35,0x63,0xa5,0x41,0x65,0x13,0x6e,0x64,0x65,0x64,2,0x61,0xa3,0xd2,0x62, -0xa5,0x35,0x63,0xa5,0x41,0x12,0x61,0x74,0x68,0xa2,0xd3,0x18,0x65,0x6d,0x61,0x74, -0x69,0x63,0x61,0x6c,0x61,0x1f,0x6c,0x70,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x73, -0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd3,1,0x66,0x42,0x72,0x1e,0x65,0x73,0x65, -0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72,0x6d,0x73,1,0x61,0xa3,0x51, -0x62,0xa3,0x55,0x14,0x65,0x6e,0x69,0x61,0x6e,0x35,0x12,0x63,0x69,0x69,0x23,0x64, -0x9e,0x65,0xa2,0x42,0x68,0xa2,0x4d,0x6c,1,0x63,0x62,0x70,0x17,0x68,0x61,0x62, -0x65,0x74,0x69,0x63,0x70,1,0x66,0xa3,0x50,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74, -0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x50,0x16,0x68,0x65,0x6d, -0x69,0x63,0x61,0x6c,0xa2,0xd0,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd0, -0x12,0x6c,0x61,0x6d,0xa5,7,0x1a,0x67,0x65,0x61,0x6e,0x6e,0x75,0x6d,0x62,0x65, -0x72,0x73,0xa3,0x77,0x11,0x6f,0x6d,0xa3,0xfd,7,0x6f,0x71,0x6f,0x64,0x72,0xa2, -0x41,0x75,0xa2,0x58,0x79,0x1b,0x7a,0x61,0x6e,0x74,0x69,0x6e,0x65,0x6d,0x75,0x73, -0x69,0x63,0xa2,0x5b,0x18,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5b, -1,0x70,0x34,0x78,0x16,0x64,0x72,0x61,0x77,0x69,0x6e,0x67,0x89,0x14,0x6f,0x6d, -0x6f,0x66,0x6f,0xa0,0x12,0x65,0x78,0x74,0xa2,0x43,0x14,0x65,0x6e,0x64,0x65,0x64, -0xa3,0x43,0x10,0x61,1,0x68,0x40,0x69,0x12,0x6c,0x6c,0x65,0x92,0x17,0x70,0x61, -0x74,0x74,0x65,0x72,0x6e,0x73,0x93,0x11,0x6d,0x69,0xa3,0xc9,1,0x67,0x2c,0x68, -0x11,0x69,0x64,0xa3,0x64,0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x81,0x61,0x48,0x65, -0xa2,0x4e,0x68,0xa2,0x52,0x6c,0x1a,0x6f,0x63,0x6b,0x65,0x6c,0x65,0x6d,0x65,0x6e, -0x74,0x73,0x8b,3,0x6c,0x34,0x6d,0x40,0x73,0x66,0x74,0x11,0x61,0x6b,0xa3,0xc7, -0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x93,0x11,0x75,0x6d,0xa2,0xb1,0x12,0x73,0x75, -0x70,0xa2,0xca,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xca,1,0x69,0x30, -0x73,0x13,0x61,0x76,0x61,0x68,0xa3,0xdd,0x15,0x63,0x6c,0x61,0x74,0x69,0x6e,0x23, -0x14,0x6e,0x67,0x61,0x6c,0x69,0x41,0x16,0x61,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa5, -8,5,0x6f,0xc1,0x60,0x6f,0xa2,0x69,0x75,0xa4,0x24,0x79,1,0x70,0xa2,0x44, -0x72,0x14,0x69,0x6c,0x6c,0x69,0x63,0x32,1,0x65,0x4c,0x73,0x11,0x75,0x70,0xa2, -0x61,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa2,0x61,0x12,0x61,0x72,0x79,0xa3, -0x61,0x11,0x78,0x74,4,0x61,0xa3,0x9e,0x62,0xa3,0xa0,0x63,0xa5,9,0x64,0xa5, -0x43,0x65,0x13,0x6e,0x64,0x65,0x64,3,0x61,0xa3,0x9e,0x62,0xa3,0xa0,0x63,0xa5, -9,0x64,0xa5,0x43,0x10,0x72,1,0x69,0x34,0x6f,0x15,0x6d,0x69,0x6e,0x6f,0x61, -0x6e,0xa5,0x36,0x1a,0x6f,0x74,0x73,0x79,0x6c,0x6c,0x61,0x62,0x61,0x72,0x79,0xa3, -0x7b,3,0x6d,0x5a,0x6e,0xa2,0x95,0x70,0xa2,0xa0,0x75,0x17,0x6e,0x74,0x69,0x6e, -0x67,0x72,0x6f,0x64,0xa2,0x9a,0x17,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0xa3, -0x9a,2,0x62,0x3a,0x6d,0xa2,0x5f,0x70,0x15,0x61,0x74,0x6a,0x61,0x6d,0x6f,0xa3, -0x41,0x14,0x69,0x6e,0x69,0x6e,0x67,2,0x64,0x46,0x68,0x9e,0x6d,0x1d,0x61,0x72, -0x6b,0x73,0x66,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,0x1e,0x69,0x61, -0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x6d,0x61,0x72,0x6b,0x73,0x2e,2,0x65, -0x40,0x66,0xa6,0x4c,0x73,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, -0x83,0x16,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3,0xe0,0x17,0x61,0x6c,0x66,0x6d, -0x61,0x72,0x6b,0x73,0xa3,0x52,0x11,0x6f,0x6e,0x1f,0x69,0x6e,0x64,0x69,0x63,0x6e, -0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0xa3,0xb2,0x1b,0x74,0x72,0x6f, -0x6c,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x73,0x83,0x12,0x74,0x69,0x63,0xa2,0x84, -0x1b,0x65,0x70,0x61,0x63,0x74,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xdf,1, -0x6e,0x3e,0x72,0x1b,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0x75,0x15,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa2,0x98,0x16,0x6e,0x75,0x6d,0x62,0x65, -0x72,0x73,0xa2,0x99,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, -0x69,0x6f,0x6e,0xa3,0x99,0x61,0xa2,0xe4,0x68,0xa4,0xe,0x6a,0x10,0x6b,0xa2,0x47, -4,0x63,0x8c,0x65,0xa2,0x80,0x72,0xa2,0x9b,0x73,0xa2,0xad,0x75,0x1f,0x6e,0x69, -0x66,0x69,0x65,0x64,0x69,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x47, -0x18,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e,7,0x65,0x6b,0x65,0xa5,0, -0x66,0xa5,0x12,0x67,0xa5,0x2e,0x68,0xa5,0x42,0x14,0x6f,0x6d,0x70,0x61,0x74,0xa2, -0x45,1,0x66,0x96,0x69,1,0x62,0x44,0x64,0x17,0x65,0x6f,0x67,0x72,0x61,0x70, -0x68,0x73,0xa2,0x4f,0x12,0x73,0x75,0x70,0xa3,0x5f,0x14,0x69,0x6c,0x69,0x74,0x79, -0xa2,0x45,1,0x66,0x54,0x69,0x18,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73, -0xa2,0x4f,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x5f,0x13, -0x6f,0x72,0x6d,0x73,0xa3,0x53,0x11,0x78,0x74,7,0x65,0xc,0x65,0xa5,0,0x66, -0xa5,0x12,0x67,0xa5,0x2e,0x68,0xa5,0x42,0x61,0xa3,0x46,0x62,0xa3,0x5e,0x63,0xa3, -0xc5,0x64,0xa3,0xd1,0x19,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x73,0x75,0x70,0x94, -0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x95,1,0x74,0x50,0x79,0x14,0x6d,0x62, -0x6f,0x6c,0x73,0x9a,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, -0x69,0x6f,0x6e,0x9b,0x14,0x72,0x6f,0x6b,0x65,0x73,0xa3,0x82,2,0x6e,0x48,0x72, -0x64,0x75,0x1d,0x63,0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61, -0x6e,0xa3,0xde,0x1d,0x61,0x64,0x69,0x61,0x6e,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69, -0x63,0x73,0x63,0x12,0x69,0x61,0x6e,0xa3,0xa8,2,0x61,0x3a,0x65,0x4c,0x6f,0x16, -0x72,0x61,0x73,0x6d,0x69,0x61,0x6e,0xa5,0x2d,1,0x6b,0x26,0x6d,0xa3,0xa4,0x11, -0x6d,0x61,0xa3,0xd4,1,0x72,0x38,0x73,0x17,0x73,0x73,0x79,0x6d,0x62,0x6f,0x6c, -0x73,0xa5,0x19,0x13,0x6f,0x6b,0x65,0x65,0x60,0x12,0x73,0x75,0x70,0xa2,0xff,0x16, -0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xff,3,0x65,0x3e,0x69,0x8e,0x6f,0xa2, -0x71,0x75,0x15,0x70,0x6c,0x6f,0x79,0x61,0x6e,0xa3,0xe1,1,0x73,0x60,0x76,0x16, -0x61,0x6e,0x61,0x67,0x61,0x72,0x69,0x3e,0x12,0x65,0x78,0x74,0xa2,0xb3,1,0x61, -0xa5,0x44,0x65,0x13,0x6e,0x64,0x65,0x64,0xa2,0xb3,0x10,0x61,0xa5,0x44,0x13,0x65, -0x72,0x65,0x74,0xa3,0x5a,2,0x61,0x3a,0x6e,0x82,0x76,0x16,0x65,0x73,0x61,0x6b, -0x75,0x72,0x75,0xa5,0x2f,0x18,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x73,0x2e, -2,0x65,0x30,0x66,0x36,0x73,0x11,0x75,0x70,0xa3,0x83,0x11,0x78,0x74,0xa3,0xe0, -0x18,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,0x14,0x67,0x62,0x61,0x74, -0x73,0x91,1,0x67,0x3e,0x6d,0x12,0x69,0x6e,0x6f,0xa2,0xab,0x14,0x74,0x69,0x6c, -0x65,0x73,0xa3,0xab,0x11,0x72,0x61,0xa5,0x1a,8,0x6d,0x5f,0x6d,0x3a,0x6e,0x48, -0x73,0x7a,0x76,0xa2,0x4b,0x77,0x12,0x69,0x64,0x65,0x43,0x11,0x65,0x64,0x32,0x12, -0x69,0x61,0x6c,0x33,2,0x61,0x40,0x62,0x37,0x6f,1,0x62,0x28,0x6e,0x10,0x65, -0x21,0x13,0x72,0x65,0x61,0x6b,0x37,0x10,0x72,0x34,0x12,0x72,0x6f,0x77,0x35,2, -0x6d,0x38,0x71,0x46,0x75,1,0x62,0x3d,0x70,0x3e,0x11,0x65,0x72,0x3f,1,0x61, -0x24,0x6c,0x39,0x11,0x6c,0x6c,0x39,1,0x72,0x3b,0x75,0x12,0x61,0x72,0x65,0x3b, -0x12,0x65,0x72,0x74,0x40,0x13,0x69,0x63,0x61,0x6c,0x41,0x63,0x58,0x65,0x92,0x66, -0x96,0x69,1,0x6e,0x36,0x73,0x10,0x6f,0x30,0x14,0x6c,0x61,0x74,0x65,0x64,0x31, -0x11,0x69,0x74,0x2e,0x12,0x69,0x61,0x6c,0x2f,2,0x61,0x36,0x69,0x48,0x6f,0x10, -0x6d,0x24,0x12,0x70,0x61,0x74,0x25,0x10,0x6e,0x22,0x15,0x6f,0x6e,0x69,0x63,0x61, -0x6c,0x23,0x13,0x72,0x63,0x6c,0x65,0x27,0x11,0x6e,0x63,0x27,2,0x69,0x3a,0x6f, -0x44,0x72,0x10,0x61,0x2c,0x14,0x63,0x74,0x69,0x6f,0x6e,0x2d,0x10,0x6e,0x28,0x11, -0x61,0x6c,0x29,0x11,0x6e,0x74,0x2b,4,0x61,0x3a,0x66,0x4c,0x68,0x5e,0x6e,0x70, -0x77,0x2a,0x12,0x69,0x64,0x65,0x2b,0x22,0x17,0x6d,0x62,0x69,0x67,0x75,0x6f,0x75, -0x73,0x23,0x26,0x17,0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x27,0x24,0x17,0x61, -0x6c,0x66,0x77,0x69,0x64,0x74,0x68,0x25,0x20,1,0x61,0x30,0x65,0x14,0x75,0x74, -0x72,0x61,0x6c,0x21,0x28,0x13,0x72,0x72,0x6f,0x77,0x29,0xd,0x6e,0xc0,0xfb,0x73, -0x6d,0x73,0x3a,0x74,0x98,0x75,0xa2,0x49,0x7a,2,0x6c,0x3b,0x70,0x3d,0x73,0x39, -5,0x6f,0x28,0x6f,0x57,0x70,0x34,0x75,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65, -0x45,0x11,0x61,0x63,1,0x65,0x32,0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x31, -0x18,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x39,0x63,0x53,0x6b,0x55,0x6d, -0x51,0x1d,0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72, -0x27,1,0x6e,0x40,0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74, -0x74,0x65,0x72,0x23,0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x21,0x6e,0x8a, -0x6f,0xa2,0x47,0x70,8,0x66,0x14,0x66,0x5b,0x69,0x59,0x6f,0x4f,0x72,0x24,0x73, -0x49,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0x43,0x61,0x2c,0x63,0x4d,0x64, -0x47,0x65,0x4b,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72, -0x61,0x74,0x6f,0x72,0x3d,2,0x64,0x33,0x6c,0x35,0x6f,0x36,0x1b,0x6e,0x73,0x70, -0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x2d,1,0x70,0x7c,0x74,0x12,0x68, -0x65,0x72,3,0x6c,0x38,0x6e,0x42,0x70,0x4c,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c, -0x57,0x14,0x65,0x74,0x74,0x65,0x72,0x2b,0x14,0x75,0x6d,0x62,0x65,0x72,0x37,0x19, -0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x1c,0x65,0x6e,0x70,0x75, -0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,0x66,0x9e,0x66,0x88,0x69,0xa2, -0x4b,0x6c,0xa2,0x5c,0x6d,4,0x61,0x60,0x63,0x31,0x65,0x2f,0x6e,0x2d,0x6f,0x15, -0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c,0x30,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c, -0x55,0x14,0x65,0x74,0x74,0x65,0x72,0x29,0x17,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0x51,1,0x69,0x2e,0x6f,0x13,0x72,0x6d,0x61,0x74,0x41,0x1d,0x6e,0x61,0x6c, -0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x5b,0x10,0x6e,0x1f,0x69, -0x74,0x69,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x59, -6,0x6d,0x18,0x6d,0x29,0x6f,0x28,0x74,0x27,0x75,0x23,0x2a,0x1c,0x77,0x65,0x72, -0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x25,0x65,0x28,0x69,0x3c,0x6c, -0x25,0x19,0x74,0x74,0x65,0x72,0x6e,0x75,0x6d,0x62,0x65,0x72,0x35,0x1a,0x6e,0x65, -0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x3b,0x63,0x44,0x64,0xa2,0x60,0x65, -0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x2f,6,0x6e, -0x39,0x6e,0x46,0x6f,0x4e,0x73,0x45,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73, -0x79,0x6d,0x62,0x6f,0x6c,0x53,0x20,0x12,0x74,0x72,0x6c,0x3f,0x42,0x10,0x6e,1, -0x6e,0x2c,0x74,0x12,0x72,0x6f,0x6c,0x3f,0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75, -0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x4d,0x63,0x3f,0x66,0x41,0x6c,0x1d, -0x6f,0x73,0x65,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x4b,2, -0x61,0x30,0x65,0x4a,0x69,0x12,0x67,0x69,0x74,0x33,0x1c,0x73,0x68,0x70,0x75,0x6e, -0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x47,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e, -0x75,0x6d,0x62,0x65,0x72,0x33,0,0x13,0x6e,0xc1,0xf,0x74,0x76,0x74,0x4c,0x76, -0x9a,0x77,0xa2,0x48,0x79,0xa2,0x49,0x7a,1,0x61,0x2c,0x68,0x12,0x61,0x69,0x6e, -0x8b,0x11,0x69,0x6e,0x85,2,0x61,0x36,0x65,0x3c,0x68,0x14,0x69,0x6e,0x79,0x65, -0x68,0xa3,0x66,1,0x68,0x71,0x77,0x73,1,0x68,0x28,0x74,0x10,0x68,0x77,0x16, -0x6d,0x61,0x72,0x62,0x75,0x74,0x61,0x74,0x13,0x67,0x6f,0x61,0x6c,0x3d,0x1a,0x65, -0x72,0x74,0x69,0x63,0x61,0x6c,0x74,0x61,0x69,0x6c,0xa3,0x67,0x11,0x61,0x77,0x79, -1,0x65,0x32,0x75,0x11,0x64,0x68,0x80,0x11,0x68,0x65,0x83,0x10,0x68,0x7a,1, -0x62,0x34,0x77,0x16,0x69,0x74,0x68,0x74,0x61,0x69,0x6c,0x7f,0x14,0x61,0x72,0x72, -0x65,0x65,0x7d,0x6e,0xa2,0x4c,0x70,0xa2,0x69,0x71,0xa2,0x69,0x72,0xa2,0x6f,0x73, -5,0x74,0x22,0x74,0x38,0x77,0x4c,0x79,0x16,0x72,0x69,0x61,0x63,0x77,0x61,0x77, -0x6f,0x18,0x72,0x61,0x69,0x67,0x68,0x74,0x77,0x61,0x77,0xa3,0x55,0x15,0x61,0x73, -0x68,0x6b,0x61,0x66,0x6d,0x61,0x2e,0x65,0x38,0x68,0x11,0x69,0x6e,0x6b,0x10,0x64, -0x62,0x11,0x68,0x65,0x65,1,0x65,0x2e,0x6d,0x13,0x6b,0x61,0x74,0x68,0x69,0x10, -0x6e,0x67,2,0x6f,0x2c,0x75,0x50,0x79,0x10,0x61,0x91,1,0x6a,0x28,0x6f,0x10, -0x6e,0x55,0x1a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x67,0x72,0x6f,0x75,0x70,0x21,0x10, -0x6e,0x57,0x10,0x65,0x59,0x10,0x61,1,0x66,0x5b,0x70,0x10,0x68,0x5d,1,0x65, -0x38,0x6f,0x18,0x68,0x69,0x6e,0x67,0x79,0x61,0x79,0x65,0x68,0x93,1,0x68,0x5f, -0x76,0x16,0x65,0x72,0x73,0x65,0x64,0x70,0x65,0x61,0x67,0xc1,0xc7,0x67,0xa4,0x52, -0x68,0xa4,0x59,0x6b,0xa4,0x99,0x6c,0xa4,0xb2,0x6d,2,0x61,0x2e,0x65,0xa4,0x3e, -0x69,0x10,0x6d,0x53,1,0x6c,0xa2,0xe7,0x6e,0x16,0x69,0x63,0x68,0x61,0x65,0x61, -0x6e,0,0x12,0x6e,0x76,0x73,0x51,0x73,0x3e,0x74,0x5c,0x77,0xa0,0x79,0xa2,0x42, -0x7a,0x13,0x61,0x79,0x69,0x6e,0xa3,0x54,0x10,0x61,1,0x64,0x2e,0x6d,0x12,0x65, -0x6b,0x68,0xa3,0x4c,0x11,0x68,0x65,0xa3,0x4b,3,0x61,0x38,0x65,0x3c,0x68,0x4a, -0x77,0x13,0x65,0x6e,0x74,0x79,0xa3,0x51,0x10,0x77,0xa3,0x4d,1,0x6e,0xa3,0x4e, -0x74,0x10,0x68,0xa3,0x4f,0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x50,0x11,0x61,0x77, -0xa3,0x52,0x12,0x6f,0x64,0x68,0xa3,0x53,0x6e,0x3a,0x6f,0x40,0x70,0x46,0x71,0x4a, -0x72,0x12,0x65,0x73,0x68,0xa3,0x4a,0x11,0x75,0x6e,0xa3,0x46,0x11,0x6e,0x65,0xa3, -0x47,0x10,0x65,0xa3,0x48,0x12,0x6f,0x70,0x68,0xa3,0x49,0x67,0x33,0x67,0x38,0x68, -0x40,0x6b,0x5e,0x6c,0x66,0x6d,0x11,0x65,0x6d,0xa3,0x45,0x13,0x69,0x6d,0x65,0x6c, -0xa1,1,0x65,0x32,0x75,0x14,0x6e,0x64,0x72,0x65,0x64,0xa3,0x42,0x11,0x74,0x68, -0xa3,0x41,0x12,0x61,0x70,0x68,0xa3,0x43,0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x44, -0x61,0x34,0x62,0x4a,0x64,0x50,0x66,0x12,0x69,0x76,0x65,0x9f,1,0x6c,0x2a,0x79, -0x11,0x69,0x6e,0x97,0x12,0x65,0x70,0x68,0x95,0x12,0x65,0x74,0x68,0x99,1,0x61, -0x30,0x68,0x14,0x61,0x6d,0x65,0x64,0x68,0x9d,0x13,0x6c,0x65,0x74,0x68,0x9b,0x15, -0x61,0x79,0x61,0x6c,0x61,0x6d,6,0x6e,0x2c,0x6e,0x34,0x72,0x5e,0x73,0x62,0x74, -0x11,0x74,0x61,0xa3,0x63,2,0x67,0x2e,0x6e,0x32,0x79,0x10,0x61,0xa3,0x60,0x10, -0x61,0xa3,0x5d,1,0x61,0xa3,0x5e,0x6e,0x10,0x61,0xa3,0x5f,0x10,0x61,0xa3,0x61, -0x11,0x73,0x61,0xa3,0x62,0x62,0x3c,0x6a,0x42,0x6c,0x10,0x6c,1,0x61,0xa3,0x5b, -0x6c,0x10,0x61,0xa3,0x5c,0x11,0x68,0x61,0xa3,0x59,0x10,0x61,0xa3,0x5a,0x11,0x65, -0x6d,0x51,0x10,0x61,1,0x66,0x37,0x6d,0x11,0x61,0x6c,0x39,1,0x61,0x40,0x65, -0x3e,1,0x68,0x28,0x74,0x10,0x68,0x45,0x40,0x13,0x67,0x6f,0x61,0x6c,0x43,2, -0x68,0x3b,0x6d,0x5c,0x6e,0x1a,0x69,0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79, -0x61,1,0x6b,0x2a,0x70,0x10,0x61,0xa3,0x65,0x15,0x69,0x6e,0x6e,0x61,0x79,0x61, -0xa3,0x64,0x1a,0x7a,0x61,0x6f,0x6e,0x68,0x65,0x68,0x67,0x6f,0x61,0x6c,0x3d,2, -0x61,0x3a,0x68,0x44,0x6e,0x17,0x6f,0x74,0x74,0x65,0x64,0x68,0x65,0x68,0x4b,1, -0x66,0x47,0x70,0x10,0x68,0x49,0x12,0x61,0x70,0x68,0x89,0x11,0x61,0x6d,0x4c,0x12, -0x61,0x64,0x68,0x4f,0x61,0x6e,0x62,0xa2,0x54,0x64,0xa2,0x70,0x65,0x31,0x66,2, -0x61,0x3e,0x65,0x4a,0x69,0x19,0x6e,0x61,0x6c,0x73,0x65,0x6d,0x6b,0x61,0x74,0x68, -0x35,0x15,0x72,0x73,0x69,0x79,0x65,0x68,0x8f,0x86,0x10,0x68,0x33,2,0x66,0x3c, -0x69,0x70,0x6c,1,0x61,0x28,0x65,0x10,0x66,0x27,0x11,0x70,0x68,0x25,0x14,0x72, -0x69,0x63,0x61,0x6e,2,0x66,0x30,0x6e,0x36,0x71,0x11,0x61,0x66,0xa3,0x58,0x11, -0x65,0x68,0xa3,0x56,0x12,0x6f,0x6f,0x6e,0xa3,0x57,0x10,0x6e,0x23,1,0x65,0x4a, -0x75,0x10,0x72,0x1f,0x75,0x73,0x68,0x61,0x73,0x6b,0x69,0x79,0x65,0x68,0x62,0x61, -0x72,0x72,0x65,0x65,0x8d,1,0x68,0x29,0x74,0x10,0x68,0x2b,0x11,0x61,0x6c,0x2c, -0x16,0x61,0x74,0x68,0x72,0x69,0x73,0x68,0x2f,7,0x6e,0x2e,0x6e,0x2c,0x72,0x3e, -0x74,0x56,0x75,0x21,0x18,0x6f,0x6e,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x21,0x28, -0x1a,0x69,0x67,0x68,0x74,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x29,0x2a,0x19,0x72, -0x61,0x6e,0x73,0x70,0x61,0x72,0x65,0x6e,0x74,0x2b,0x63,0x23,0x64,0x40,0x6a,0x56, -0x6c,0x26,0x19,0x65,0x66,0x74,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x27,0x24,0x19, -0x75,0x61,0x6c,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x25,0x19,0x6f,0x69,0x6e,0x63, -0x61,0x75,0x73,0x69,0x6e,0x67,0x23,0,0x13,0x6e,0xc0,0xd0,0x73,0x49,0x73,0x48, -0x75,0x78,0x77,0x84,0x78,0x9c,0x7a,0x10,0x77,0x58,1,0x6a,0x75,0x73,0x13,0x70, -0x61,0x63,0x65,0x59,4,0x61,0x51,0x67,0x53,0x70,0x28,0x75,0x30,0x79,0x57,0x54, -0x12,0x61,0x63,0x65,0x55,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x53,0x15,0x6e, -0x6b,0x6e,0x6f,0x77,0x6e,0x21,1,0x6a,0x5d,0x6f,0x17,0x72,0x64,0x6a,0x6f,0x69, -0x6e,0x65,0x72,0x5d,0x10,0x78,0x21,0x6e,0x60,0x6f,0xa2,0x41,0x70,0xa2,0x50,0x71, -0xa2,0x6e,0x72,1,0x65,0x24,0x69,0x6f,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69, -0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x6f,4,0x65,0x3e,0x6c,0x5b,0x6f,0x46, -0x73,0x45,0x75,0x46,0x14,0x6d,0x65,0x72,0x69,0x63,0x47,0x15,0x78,0x74,0x6c,0x69, -0x6e,0x65,0x5b,0x17,0x6e,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x45,0x10,0x70,0x48, -0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,1, -0x6f,0x3e,0x72,0x4c,0x1a,0x65,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63, -0x4d,0x4a,0x1b,0x73,0x74,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4b, -0x10,0x75,0x4e,0x16,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x68,0x7b,0x68,0x50, -0x69,0x86,0x6a,0xa2,0x61,0x6c,0xa2,0x65,0x6d,0x1c,0x61,0x6e,0x64,0x61,0x74,0x6f, -0x72,0x79,0x62,0x72,0x65,0x61,0x6b,0x2d,4,0x32,0x5f,0x33,0x61,0x65,0x34,0x6c, -0x6d,0x79,0x3a,0x13,0x70,0x68,0x65,0x6e,0x3b,0x19,0x62,0x72,0x65,0x77,0x6c,0x65, -0x74,0x74,0x65,0x72,0x6d,2,0x64,0x28,0x6e,0x3c,0x73,0x41,0x3c,0x18,0x65,0x6f, -0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x3d,0x3e,1,0x66,0x3e,0x73,0x11,0x65,0x70, -1,0x61,0x22,0x65,0x14,0x72,0x61,0x62,0x6c,0x65,0x3f,0x18,0x69,0x78,0x6e,0x75, -0x6d,0x65,0x72,0x69,0x63,0x41,2,0x6c,0x63,0x74,0x65,0x76,0x67,1,0x66,0x43, -0x69,0x15,0x6e,0x65,0x66,0x65,0x65,0x64,0x43,0x61,0x40,0x62,0x70,0x63,0xa2,0x55, -0x65,0xa2,0xdb,0x67,0x10,0x6c,0x38,0x11,0x75,0x65,0x39,2,0x69,0x23,0x6c,0x34, -0x6d,0x16,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x24,0x17,0x70,0x68,0x61,0x62, -0x65,0x74,0x69,0x63,0x25,4,0x32,0x27,0x61,0x29,0x62,0x2b,0x6b,0x2d,0x72,0x12, -0x65,0x61,0x6b,2,0x61,0x36,0x62,0x3e,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0x57,0x13,0x66,0x74,0x65,0x72,0x29,1,0x65,0x2a,0x6f,0x11,0x74,0x68,0x27,0x13, -0x66,0x6f,0x72,0x65,0x2b,7,0x6d,0x51,0x6d,0x33,0x6f,0x28,0x70,0x69,0x72,0x35, -1,0x6d,0x76,0x6e,1,0x64,0x3c,0x74,0x1a,0x69,0x6e,0x67,0x65,0x6e,0x74,0x62, -0x72,0x65,0x61,0x6b,0x2f,0x15,0x69,0x74,0x69,0x6f,0x6e,0x61,0x1f,0x6c,0x6a,0x61, -0x70,0x61,0x6e,0x65,0x73,0x65,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x6b,1,0x62, -0x3a,0x70,0x19,0x6c,0x65,0x78,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x51,0x18,0x69, -0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x33,0x61,0x6a,0x62,0x2f,0x6a,0x6b,0x6c, -0x30,0x13,0x6f,0x73,0x65,0x70,1,0x61,0x38,0x75,0x18,0x6e,0x63,0x74,0x75,0x61, -0x74,0x69,0x6f,0x6e,0x31,0x18,0x72,0x65,0x6e,0x74,0x68,0x65,0x73,0x69,0x73,0x69, -0x1b,0x72,0x72,0x69,0x61,0x67,0x65,0x72,0x65,0x74,0x75,0x72,0x6e,0x35,2,0x62, -0x3e,0x6d,0x46,0x78,0x36,0x18,0x63,0x6c,0x61,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x37, -0x70,0x12,0x61,0x73,0x65,0x71,0x72,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x73, -1,0x64,0x42,0x6e,1,0x6f,0x32,0x75,0x26,0x14,0x6d,0x65,0x72,0x69,0x63,0x27, -0x11,0x6e,0x65,0x21,1,0x65,0x2e,0x69,0x24,0x12,0x67,0x69,0x74,0x25,0x22,0x14, -0x63,0x69,0x6d,0x61,0x6c,0x23,0,0x18,0x6e,0xc4,0x6f,0x74,0xc1,0x91,0x77,0x96, -0x77,0xa2,0x4c,0x78,0xa2,0x70,0x79,0xa2,0x7a,0x7a,6,0x73,0x1e,0x73,0x34,0x78, -0x42,0x79,0x48,0x7a,0x11,0x7a,0x7a,0xa3,0x67,0x10,0x79,1,0x65,0xa3,0xae,0x6d, -0xa3,0x81,0x11,0x78,0x78,0xa3,0x66,0x11,0x79,0x79,0x21,0x61,0x30,0x69,0x58,0x6d, -0x11,0x74,0x68,0xa3,0x80,0x10,0x6e,1,0x61,0x26,0x62,0xa3,0xb1,0x1a,0x62,0x61, -0x7a,0x61,0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa3,0xb1,0x11,0x6e,0x68,0x23,2, -0x61,0x30,0x63,0x5a,0x6f,0x11,0x6c,0x65,0xa3,0x9b,1,0x6e,0x3c,0x72,0x10,0x61, -0xa2,0x92,0x15,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0x92,0x12,0x63,0x68,0x6f,0xa3, -0xbc,0x11,0x68,0x6f,0xa3,0xbc,1,0x70,0x2c,0x73,0x11,0x75,0x78,0xa3,0x65,0x11, -0x65,0x6f,0x9b,1,0x65,0x2c,0x69,0x72,0x11,0x69,0x69,0x73,0x11,0x7a,0x69,0xa2, -0xc0,0x11,0x64,0x69,0xa3,0xc0,0x74,0x66,0x75,0xa2,0xde,0x76,1,0x61,0x48,0x69, -1,0x73,0x38,0x74,0x10,0x68,0xa2,0xc5,0x13,0x6b,0x75,0x71,0x69,0xa3,0xc5,0x10, -0x70,0xa3,0x64,0x10,0x69,0xa2,0x63,0x10,0x69,0xa3,0x63,7,0x68,0x3e,0x68,0x34, -0x69,0x48,0x6e,0x86,0x6f,0x11,0x74,0x6f,0xa3,0xc4,0x10,0x61,1,0x61,0x24,0x69, -0x6d,0x6a,0x11,0x6e,0x61,0x6b,2,0x62,0x3a,0x66,0x4a,0x72,0x10,0x68,0xa2,0x9e, -0x12,0x75,0x74,0x61,0xa3,0x9e,1,0x65,0x24,0x74,0x6f,0x12,0x74,0x61,0x6e,0x6f, -0x14,0x69,0x6e,0x61,0x67,0x68,0x99,0x11,0x73,0x61,0xa3,0xc3,0x61,0x36,0x65,0xa2, -0x65,0x66,0xa2,0x71,0x67,0x11,0x6c,0x67,0x75,6,0x6c,0x28,0x6c,0x32,0x6d,0x38, -0x6e,0x44,0x76,0x10,0x74,0xa3,0x7f,1,0x65,0x89,0x75,0x97,1,0x69,0x24,0x6c, -0x67,0x10,0x6c,0x67,0x10,0x67,0xa2,0x9a,1,0x73,0x2a,0x75,0x10,0x74,0xa3,0x9a, -0x10,0x61,0xa3,0xc3,0x67,0x36,0x69,0x52,0x6b,0x10,0x72,0xa2,0x99,0x10,0x69,0xa3, -0x99,1,0x61,0x30,0x62,0x7a,0x13,0x61,0x6e,0x77,0x61,0x7b,0x12,0x6c,0x6f,0x67, -0x75,2,0x6c,0x32,0x74,0x34,0x76,0x12,0x69,0x65,0x74,0xa3,0x7f,0x10,0x65,0x89, -0x12,0x68,0x61,0x6d,0xa3,0x6a,1,0x6c,0x2a,0x6e,0x10,0x67,0xa3,0x62,0x10,0x75, -0x68,0x11,0x67,0x75,0x69,0x11,0x6e,0x67,0x99,1,0x67,0x32,0x6e,0x14,0x6b,0x6e, -0x6f,0x77,0x6e,0xa3,0x67,0x11,0x61,0x72,0x8a,0x13,0x69,0x74,0x69,0x63,0x8b,0x71, -0xc1,0x13,0x71,0xa2,0xde,0x72,0xa2,0xe3,0x73,6,0x69,0x8a,0x69,0x72,0x6f,0xa2, -0x4c,0x75,0xa2,0x75,0x79,1,0x6c,0x46,0x72,4,0x63,0x65,0x65,0xa3,0x5f,0x69, -0x2c,0x6a,0xa3,0x60,0x6e,0xa3,0x61,0x11,0x61,0x63,0x65,0x10,0x6f,0x94,0x16,0x74, -0x69,0x6e,0x61,0x67,0x72,0x69,0x95,2,0x64,0x3c,0x67,0x4c,0x6e,1,0x64,0xa3, -0x91,0x68,0x62,0x12,0x61,0x6c,0x61,0x63,0x10,0x64,0xa2,0xa6,0x12,0x68,0x61,0x6d, -0xa3,0xa6,0x17,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa3,0x70,2,0x67,0x3a, -0x72,0x52,0x79,0x10,0x6f,0xa2,0xb0,0x12,0x6d,0x62,0x6f,0xa3,0xb0,1,0x64,0x26, -0x6f,0xa3,0xb8,0xa2,0xb7,0x12,0x69,0x61,0x6e,0xa3,0xb7,0x10,0x61,0xa2,0x98,0x16, -0x73,0x6f,0x6d,0x70,0x65,0x6e,0x67,0xa3,0x98,0x11,0x6e,0x64,0xa2,0x71,0x14,0x61, -0x6e,0x65,0x73,0x65,0xa3,0x71,0x61,0x5c,0x67,0xa2,0x43,0x68,1,0x61,0x2a,0x72, -0x10,0x64,0xa3,0x97,2,0x72,0x28,0x76,0x30,0x77,0x87,0x12,0x61,0x64,0x61,0xa3, -0x97,0x12,0x69,0x61,0x6e,0x87,2,0x6d,0x40,0x72,0x58,0x75,0x10,0x72,0xa2,0x6f, -0x15,0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0x6f,1,0x61,0x26,0x72,0xa3,0x7e,0x14, -0x72,0x69,0x74,0x61,0x6e,0xa3,0x7e,1,0x61,0xa3,0x5e,0x62,0xa3,0x85,0x11,0x6e, -0x77,0xa3,0x70,0x11,0x61,0x61,1,0x63,0x2f,0x69,0x23,3,0x65,0x3e,0x6a,0x48, -0x6f,0x4e,0x75,0x10,0x6e,1,0x69,0x24,0x72,0x61,0x10,0x63,0x61,0x13,0x6a,0x61, -0x6e,0x67,0xa3,0x6e,0x11,0x6e,0x67,0xa3,0x6e,1,0x68,0x2a,0x72,0x10,0x6f,0xa3, -0x5d,0x10,0x67,0xa3,0xb6,0x6e,0xa2,0x83,0x6f,0xa4,1,0x70,5,0x6c,0x1e,0x6c, -0x44,0x72,0x4a,0x73,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76, -0x69,0xa3,0x7b,0x11,0x72,0x64,0xa3,0x5c,0x11,0x74,0x69,0xa3,0x7d,0x61,0x7c,0x65, -0xa2,0x54,0x68,3,0x61,0x3e,0x6c,0x4e,0x6e,0x5e,0x6f,0x16,0x65,0x6e,0x69,0x63, -0x69,0x61,0x6e,0xa3,0x5b,0x10,0x67,0xa2,0x5a,0x12,0x73,0x70,0x61,0xa3,0x5a,2, -0x69,0xa3,0x7a,0x70,0xa3,0x7b,0x76,0xa3,0x7c,0x10,0x78,0xa3,0x5b,2,0x68,0x3e, -0x6c,0x50,0x75,0x10,0x63,0xa2,0xa5,0x14,0x69,0x6e,0x68,0x61,0x75,0xa3,0xa5,0x17, -0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0x4b,0x10,0x6d,0xa2,0x90,0x14,0x79, -0x72,0x65,0x6e,0x65,0xa3,0x90,0x11,0x72,0x6d,0xa3,0x59,6,0x6b,0x36,0x6b,0x56, -0x73,0x6e,0x75,0x74,0x79,0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61, -0x63,0x68,0x75,0x65,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0xba,1,0x67,0x2e,0x6f,0xa2, -0x57,0x10,0x6f,0xa3,0x57,0x10,0x62,0xa3,0x84,0x11,0x68,0x75,0xa3,0x96,0x12,0x73, -0x68,0x75,0xa3,0x96,0x61,0x42,0x62,0x9e,0x65,0x10,0x77,1,0x61,0xa3,0xaa,0x74, -0x14,0x61,0x69,0x6c,0x75,0x65,0x97,3,0x62,0x32,0x67,0x40,0x6e,0x56,0x72,0x10, -0x62,0xa3,0x8e,0x15,0x61,0x74,0x61,0x65,0x61,0x6e,0xa3,0x8f,0x10,0x6d,0xa2,0xc7, -0x15,0x75,0x6e,0x64,0x61,0x72,0x69,0xa3,0xc7,0x10,0x64,0xa2,0xbb,0x16,0x69,0x6e, -0x61,0x67,0x61,0x72,0x69,0xa3,0xbb,0x11,0x61,0x74,0xa3,0x8f,4,0x67,0x3c,0x6c, -0x4e,0x72,0xa2,0x8e,0x73,0xa2,0x9c,0x75,0x11,0x67,0x72,0xa3,0xc2,1,0x61,0x2a, -0x68,0x11,0x61,0x6d,0x5b,0x10,0x6d,0x5b,1,0x63,0xa2,0x6a,0x64,6,0x70,0x41, -0x70,0x3a,0x73,0x58,0x74,0x86,0x75,0x14,0x79,0x67,0x68,0x75,0x72,0xa3,0xc2,0x11, -0x65,0x72,1,0x6d,0x2c,0x73,0x12,0x69,0x61,0x6e,0x9b,0x11,0x69,0x63,0xa3,0x59, -0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e, -0xa3,0x85,0x13,0x64,0x69,0x61,0x6e,0xa3,0xb8,0x14,0x75,0x72,0x6b,0x69,0x63,0xa3, -0x58,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69, -0x61,0x6e,0xa3,0x8e,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa3,0x4c,0x14, -0x74,0x61,0x6c,0x69,0x63,0x5d,1,0x68,0x26,0x6b,0xa3,0x6d,0x12,0x69,0x6b,0x69, -0xa3,0x6d,2,0x69,0x2c,0x6b,0x30,0x79,0x10,0x61,0x5f,0x11,0x79,0x61,0x5f,0x10, -0x68,0xa3,0x58,2,0x61,0x36,0x67,0x3c,0x6d,0x10,0x61,0x84,0x12,0x6e,0x79,0x61, -0x85,0x11,0x67,0x65,0xa3,0xab,0x10,0x65,0xa3,0xab,0x68,0xc3,0x15,0x6b,0xc2,0x2c, -0x6b,0xa4,0x17,0x6c,0xa4,0xba,0x6d,8,0x6f,0x46,0x6f,0x48,0x72,0x74,0x74,0x80, -0x75,0x86,0x79,1,0x61,0x28,0x6d,0x10,0x72,0x59,0x13,0x6e,0x6d,0x61,0x72,0x59, -2,0x64,0x2e,0x6e,0x32,0x6f,0x10,0x6e,0xa3,0x72,0x10,0x69,0xa3,0xa3,0x10,0x67, -0x56,0x14,0x6f,0x6c,0x69,0x61,0x6e,0x57,0x10,0x6f,0xa2,0x95,0x10,0x6f,0xa3,0x95, -0x11,0x65,0x69,0xa3,0x73,0x11,0x6c,0x74,0xa2,0xa4,0x12,0x61,0x6e,0x69,0xa3,0xa4, -0x61,0x36,0x65,0xa2,0x67,0x69,0xa2,0xbd,0x6c,0x11,0x79,0x6d,0x55,6,0x6e,0x38, -0x6e,0x32,0x72,0x5c,0x73,0x6c,0x79,0x10,0x61,0xa3,0x55,1,0x64,0x38,0x69,0xa2, -0x79,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3,0x79,0xa2,0x54,0x12,0x61,0x69,0x63, -0xa3,0x54,0x10,0x63,0xa2,0xa9,0x12,0x68,0x65,0x6e,0xa3,0xa9,0x18,0x61,0x72,0x61, -0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xaf,0x68,0x36,0x6b,0x4c,0x6c,0x15,0x61,0x79, -0x61,0x6c,0x61,0x6d,0x55,1,0x61,0x26,0x6a,0xa3,0xa0,0x13,0x6a,0x61,0x6e,0x69, -0xa3,0xa0,0x10,0x61,0xa2,0xb4,0x12,0x73,0x61,0x72,0xa3,0xb4,3,0x64,0x78,0x65, -0x94,0x6e,0xa2,0x42,0x72,1,0x63,0xa3,0x8d,0x6f,0xa2,0x56,0x13,0x69,0x74,0x69, -0x63,1,0x63,0x3c,0x68,0x19,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73, -0xa3,0x56,0x15,0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0x8d,1,0x65,0x26,0x66,0xa3, -0xb5,0x16,0x66,0x61,0x69,0x64,0x72,0x69,0x6e,0xa3,0xb5,0x17,0x74,0x65,0x69,0x6d, -0x61,0x79,0x65,0x6b,0xa3,0x73,0x10,0x64,0xa2,0x8c,0x17,0x65,0x6b,0x69,0x6b,0x61, -0x6b,0x75,0x69,0xa3,0x8c,0x11,0x61,0x6f,0xa3,0x5c,6,0x6e,0x1a,0x6e,0x34,0x6f, -0x38,0x70,0x3e,0x74,0x11,0x68,0x69,0xa3,0x78,0x11,0x64,0x61,0x4b,0x11,0x72,0x65, -0xa3,0x77,0x11,0x65,0x6c,0xa3,0x8a,0x61,0x32,0x68,0xa2,0x44,0x69,0x11,0x74,0x73, -0xa3,0xbf,5,0x74,0x23,0x74,0x34,0x77,0x56,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3, -0x4f,0x14,0x61,0x6b,0x61,0x6e,0x61,0x4c,0x19,0x6f,0x72,0x68,0x69,0x72,0x61,0x67, -0x61,0x6e,0x61,0x8d,0x10,0x69,0xa3,0xc6,0x69,0x38,0x6c,0x40,0x6e,1,0x61,0x4d, -0x6e,0x12,0x61,0x64,0x61,0x4b,0x12,0x74,0x68,0x69,0xa3,0x78,0x10,0x69,0xa3,0x4f, -4,0x61,0x40,0x69,0x52,0x6d,0x70,0x6f,0x7c,0x75,0x15,0x64,0x61,0x77,0x61,0x64, -0x69,0xa3,0x91,0x10,0x72,0x92,0x15,0x6f,0x73,0x68,0x74,0x68,0x69,0x93,0x1d,0x74, -0x61,0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73,0x63,0x72,0x69,0x70,0x74,0xa3,0xbf,1, -0x65,0x24,0x72,0x4f,0x10,0x72,0x4f,0x10,0x6a,0xa2,0x9d,0x11,0x6b,0x69,0xa3,0x9d, -4,0x61,0x5c,0x65,0x90,0x69,0xa0,0x6f,0xa2,0x5d,0x79,1,0x63,0x34,0x64,0x10, -0x69,0xa2,0x6c,0x11,0x61,0x6e,0xa3,0x6c,0x10,0x69,0xa2,0x6b,0x11,0x61,0x6e,0xa3, -0x6b,2,0x6e,0x42,0x6f,0x46,0x74,3,0x66,0xa3,0x50,0x67,0xa3,0x51,0x69,0x24, -0x6e,0x53,0x10,0x6e,0x53,0x10,0x61,0xa3,0x6a,0x50,0x10,0x6f,0x51,0x11,0x70,0x63, -0xa2,0x52,0x11,0x68,0x61,0xa3,0x52,2,0x6d,0x2e,0x6e,0x36,0x73,0x10,0x75,0xa3, -0x83,0x10,0x62,0x80,0x10,0x75,0x81,2,0x61,0xa3,0x53,0x62,0x83,0x65,0x11,0x61, -0x72,1,0x61,0xa3,0x53,0x62,0x83,0x11,0x6d,0x61,0xa3,0x8b,0x68,0x6e,0x69,0xa2, -0x95,0x6a,2,0x61,0x30,0x70,0x52,0x75,0x11,0x72,0x63,0xa3,0x94,1,0x6d,0x38, -0x76,0x10,0x61,0xa2,0x4e,0x13,0x6e,0x65,0x73,0x65,0xa3,0x4e,0x10,0x6f,0xa3,0xad, -0x11,0x61,0x6e,0xa3,0x69,6,0x6c,0x1e,0x6c,0x34,0x6d,0x3a,0x72,0x48,0x75,0x11, -0x6e,0x67,0xa3,0x4c,0x11,0x75,0x77,0xa3,0x9c,0x10,0x6e,1,0x67,0xa3,0x4b,0x70, -0xa3,0xba,0x11,0x6b,0x74,0x8d,0x61,0x3c,0x65,0xa2,0x43,0x69,0x11,0x72,0x61,0x48, -0x13,0x67,0x61,0x6e,0x61,0x49,1,0x6e,0x34,0x74,0x10,0x72,0xa2,0xa2,0x11,0x61, -0x6e,0xa3,0xa2,0x42,6,0x6f,0xe,0x6f,0x77,0x73,0xa3,0x49,0x74,0xa3,0x4a,0x75, -0x12,0x6e,0x6f,0x6f,0x77,0x62,0xa3,0xac,0x67,0x3e,0x69,0x42,0x19,0x66,0x69,0x72, -0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa3,0xb6,0x44,0x11,0x75,0x6c,0x45,0x11,0x62, -0x72,0x46,0x11,0x65,0x77,0x47,2,0x6d,0x2e,0x6e,0x4a,0x74,0x11,0x61,0x6c,0x5d, -0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0x74, -2,0x64,0x66,0x68,0x6a,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x61, -0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0x7d,0x13, -0x6c,0x61,0x76,0x69,0xa3,0x7a,0x10,0x73,0xa3,0x4d,0x15,0x65,0x72,0x69,0x74,0x65, -0x64,0x23,0x64,0xc1,0xd,0x64,0xa2,0x7a,0x65,0xa2,0xc1,0x67,4,0x65,0x82,0x6c, -0x9a,0x6f,0xa2,0x46,0x72,0xa2,0x55,0x75,2,0x6a,0x3c,0x6e,0x4e,0x72,1,0x6d, -0x24,0x75,0x41,0x13,0x75,0x6b,0x68,0x69,0x41,1,0x61,0x24,0x72,0x3f,0x13,0x72, -0x61,0x74,0x69,0x3f,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xb3, -0x10,0x6f,1,0x6b,0xa3,0x48,0x72,0x38,0x13,0x67,0x69,0x61,0x6e,0x39,0x11,0x61, -0x67,0x90,0x15,0x6f,0x6c,0x69,0x74,0x69,0x63,0x91,1,0x6e,0x30,0x74,0x10,0x68, -0x3a,0x11,0x69,0x63,0x3b,1,0x67,0xa3,0xb3,0x6d,0xa3,0xaf,1,0x61,0x32,0x65, -1,0x65,0x24,0x6b,0x3d,0x10,0x6b,0x3d,0x10,0x6e,0xa2,0x89,0x12,0x74,0x68,0x61, -0xa3,0x89,4,0x65,0x46,0x69,0x6c,0x6f,0x8c,0x73,0x9a,0x75,0x11,0x70,0x6c,0xa2, -0x87,0x13,0x6f,0x79,0x61,0x6e,0xa3,0x87,1,0x73,0x38,0x76,0x10,0x61,0x34,0x15, -0x6e,0x61,0x67,0x61,0x72,0x69,0x35,0x13,0x65,0x72,0x65,0x74,0x33,1,0x61,0x36, -0x76,0x16,0x65,0x73,0x61,0x6b,0x75,0x72,0x75,0xa3,0xbe,0x10,0x6b,0xa3,0xbe,0x11, -0x67,0x72,0xa2,0xb2,0x10,0x61,0xa3,0xb2,0x11,0x72,0x74,0x33,2,0x67,0x3a,0x6c, -0x72,0x74,0x11,0x68,0x69,0x36,0x13,0x6f,0x70,0x69,0x63,0x37,0x10,0x79,2,0x64, -0xa3,0x45,0x68,0xa3,0x46,0x70,0xa2,0x47,0x1e,0x74,0x69,0x61,0x6e,0x68,0x69,0x65, -0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x47,1,0x62,0x36,0x79,0x10,0x6d, -0xa2,0xb9,0x12,0x61,0x69,0x63,0xa3,0xb9,0x10,0x61,0xa2,0x88,0x12,0x73,0x61,0x6e, -0xa3,0x88,0x61,0xa2,0xc9,0x62,0xa4,0x2e,0x63,6,0x6f,0x52,0x6f,0x76,0x70,0x92, -0x75,0xa2,0x41,0x79,1,0x70,0x3e,0x72,2,0x69,0x2a,0x6c,0x31,0x73,0xa3,0x44, -0x13,0x6c,0x6c,0x69,0x63,0x31,0x10,0x72,1,0x69,0x34,0x6f,0x15,0x6d,0x69,0x6e, -0x6f,0x61,0x6e,0xa3,0xc1,0x11,0x6f,0x74,0x7f,1,0x6d,0x30,0x70,0x10,0x74,0x2e, -0x11,0x69,0x63,0x2f,0x12,0x6d,0x6f,0x6e,0x21,1,0x6d,0x28,0x72,0x10,0x74,0x7f, -0x10,0x6e,0xa3,0xc1,0x16,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa3,0x65,0x61,0x32, -0x68,0xa2,0x41,0x69,0x11,0x72,0x74,0xa3,0x43,3,0x6b,0x4c,0x6e,0x50,0x72,0x76, -0x75,0x1d,0x63,0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e, -0xa3,0x9f,0x10,0x6d,0xa3,0x76,1,0x61,0x24,0x73,0x71,0x1d,0x64,0x69,0x61,0x6e, -0x61,0x62,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x71,0x10,0x69,0xa2,0x68,0x11, -0x61,0x6e,0xa3,0x68,3,0x61,0x32,0x65,0x44,0x6f,0x52,0x72,0x10,0x73,0xa3,0xbd, -1,0x6b,0x26,0x6d,0xa3,0x42,0x11,0x6d,0x61,0xa3,0x76,0x10,0x72,0x2c,0x13,0x6f, -0x6b,0x65,0x65,0x2d,0x16,0x72,0x61,0x73,0x6d,0x69,0x61,0x6e,0xa3,0xbd,6,0x68, -0x4a,0x68,0x48,0x6e,0x4e,0x72,0x76,0x76,1,0x65,0x2a,0x73,0x10,0x74,0xa3,0x75, -0x13,0x73,0x74,0x61,0x6e,0xa3,0x75,0x11,0x6f,0x6d,0xa3,0xa1,0x11,0x61,0x74,0x1f, -0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73, -0xa3,0x9c,1,0x61,0x3e,0x6d,2,0x65,0x2a,0x69,0xa3,0x74,0x6e,0x27,0x13,0x6e, -0x69,0x61,0x6e,0x27,0x10,0x62,0x24,0x11,0x69,0x63,0x25,0x64,0x30,0x66,0x44,0x67, -0x11,0x68,0x62,0xa3,0x9f,0x10,0x6c,1,0x61,0x26,0x6d,0xa3,0xa7,0x10,0x6d,0xa3, -0xa7,0x11,0x61,0x6b,0xa3,0x93,6,0x6c,0x3c,0x6c,0x52,0x6f,0x56,0x72,0x66,0x75, -1,0x67,0x30,0x68,1,0x64,0x79,0x69,0x10,0x64,0x79,0x10,0x69,0x8e,0x13,0x6e, -0x65,0x73,0x65,0x8f,0x11,0x69,0x73,0xa1,0x11,0x70,0x6f,0x2a,0x13,0x6d,0x6f,0x66, -0x6f,0x2b,0x10,0x61,1,0x68,0x2e,0x69,0x7c,0x12,0x6c,0x6c,0x65,0x7d,0xa2,0x41, -0x11,0x6d,0x69,0xa3,0x41,0x61,0x48,0x65,0x9c,0x68,1,0x61,0x2a,0x6b,0x10,0x73, -0xa3,0xa8,0x15,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa3,0xa8,3,0x6c,0x3a,0x6d,0x48, -0x73,0x54,0x74,1,0x61,0x24,0x6b,0x9f,0x10,0x6b,0x9f,0x10,0x69,0x9c,0x13,0x6e, -0x65,0x73,0x65,0x9d,0x10,0x75,0xa2,0x82,0x10,0x6d,0xa3,0x82,0x10,0x73,0xa2,0x86, -0x13,0x61,0x76,0x61,0x68,0xa3,0x86,0x11,0x6e,0x67,0x28,0x12,0x61,0x6c,0x69,0x29, -3,0x6c,0x42,0x6e,0x90,0x74,0xa2,0x46,0x76,0x24,0x17,0x6f,0x77,0x65,0x6c,0x6a, -0x61,0x6d,0x6f,0x25,0x22,1,0x65,0x54,0x76,0x28,1,0x73,0x38,0x74,0x2a,0x17, -0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x2b,0x16,0x79,0x6c,0x6c,0x61,0x62,0x6c, -0x65,0x29,0x18,0x61,0x64,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x23,1,0x61,0x21, -0x6f,0x1a,0x74,0x61,0x70,0x70,0x6c,0x69,0x63,0x61,0x62,0x6c,0x65,0x21,0x26,0x1a, -0x72,0x61,0x69,0x6c,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x27,1,0x6e,0x2c,0x79, -0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,1,0x6e,0x2c,0x79,0x22,0x11,0x65, -0x73,0x23,0x20,0x10,0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65,0x73, -0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,2,0x6d,0x30,0x6e, -0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20,0x10, -0x6f,0x21,0xb,0x72,0x39,0x76,0xc,0x76,0x33,0x78,0x2a,0x7a,0x11,0x77,0x6a,0x43, -0x10,0x78,0x21,0x72,0x28,0x73,0x50,0x74,0x31,1,0x65,0x24,0x69,0x39,0x1e,0x67, -0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x39,1, -0x6d,0x35,0x70,0x18,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x35,0x6c,0x1f, -0x6c,0x3c,0x6f,0x4a,0x70,1,0x70,0x37,0x72,0x14,0x65,0x70,0x65,0x6e,0x64,0x37, -0x28,1,0x66,0x2b,0x76,0x2c,0x10,0x74,0x2f,0x13,0x74,0x68,0x65,0x72,0x21,0x63, -0x4c,0x65,0x64,0x67,1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74,0x65,0x72, -0x7a,0x77,0x6a,0x41,0x10,0x7a,0x41,2,0x6e,0x23,0x6f,0x24,0x72,0x25,0x14,0x6e, -0x74,0x72,0x6f,0x6c,0x23,2,0x62,0x34,0x6d,0x4e,0x78,0x26,0x13,0x74,0x65,0x6e, -0x64,0x27,0x3a,1,0x61,0x24,0x67,0x3d,0x11,0x73,0x65,0x3a,0x12,0x67,0x61,0x7a, -0x3d,0x3e,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x3f,9,0x6e,0x4a,0x6e,0x34, -0x6f,0x44,0x73,0x60,0x75,0x94,0x78,0x10,0x78,0x21,0x10,0x75,0x2a,0x14,0x6d,0x65, -0x72,0x69,0x63,0x2b,1,0x6c,0x2c,0x74,0x12,0x68,0x65,0x72,0x21,0x14,0x65,0x74, -0x74,0x65,0x72,0x2d,3,0x63,0x36,0x65,0x46,0x70,0x31,0x74,0x32,0x12,0x65,0x72, -0x6d,0x33,0x3c,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3d,0x2e,0x10,0x70,0x2f, -0x10,0x70,0x34,0x12,0x70,0x65,0x72,0x35,0x61,0x46,0x63,0x52,0x65,0x64,0x66,0x72, -0x6c,2,0x65,0x2d,0x66,0x3b,0x6f,0x28,0x12,0x77,0x65,0x72,0x29,0x10,0x74,0x22, -0x12,0x65,0x72,0x6d,0x23,1,0x6c,0x24,0x72,0x37,0x24,0x12,0x6f,0x73,0x65,0x25, -0x10,0x78,0x38,0x13,0x74,0x65,0x6e,0x64,0x39,0x10,0x6f,0x26,0x13,0x72,0x6d,0x61, -0x74,0x27,0,0x10,0x6c,0x88,0x72,0x40,0x72,0x36,0x73,0x5e,0x77,0x7a,0x78,0x8a, -0x7a,0x11,0x77,0x6a,0x4b,1,0x65,0x24,0x69,0x3b,0x1e,0x67,0x69,0x6f,0x6e,0x61, -0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x3b,1,0x69,0x24,0x71,0x3f, -0x18,0x6e,0x67,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x3f,0x17,0x73,0x65,0x67,0x73, -0x70,0x61,0x63,0x65,0x4d,0x10,0x78,0x21,0x6c,0x36,0x6d,0x3c,0x6e,0x76,0x6f,0x13, -0x74,0x68,0x65,0x72,0x21,1,0x65,0x23,0x66,0x35,3,0x62,0x37,0x69,0x28,0x6c, -0x29,0x6e,0x2b,0x10,0x64,1,0x6c,0x34,0x6e,0x11,0x75,0x6d,0x2a,0x12,0x6c,0x65, -0x74,0x37,0x14,0x65,0x74,0x74,0x65,0x72,0x29,2,0x65,0x36,0x6c,0x39,0x75,0x2c, -0x14,0x6d,0x65,0x72,0x69,0x63,0x2d,0x14,0x77,0x6c,0x69,0x6e,0x65,0x39,0x66,0x3f, -0x66,0x40,0x67,0x4e,0x68,0x70,0x6b,0x10,0x61,0x26,0x15,0x74,0x61,0x6b,0x61,0x6e, -0x61,0x27,0x10,0x6f,0x24,0x13,0x72,0x6d,0x61,0x74,0x25,1,0x61,0x3a,0x6c,0x19, -0x75,0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a,0x49,0x10,0x7a,0x49,1,0x65, -0x24,0x6c,0x3d,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,0x61, -0x86,0x63,0x92,0x64,0x94,0x65,2,0x62,0x44,0x6d,0x5e,0x78,0x2e,0x13,0x74,0x65, -0x6e,0x64,0x32,0x15,0x6e,0x75,0x6d,0x6c,0x65,0x74,0x2f,0x42,1,0x61,0x24,0x67, -0x45,0x11,0x73,0x65,0x42,0x12,0x67,0x61,0x7a,0x45,0x46,0x16,0x6f,0x64,0x69,0x66, -0x69,0x65,0x72,0x47,0x15,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x10,0x72,0x31,1, -0x6f,0x24,0x71,0x41,0x18,0x75,0x62,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x41,2, -0x63,0x32,0x6e,0x3c,0x6f,0x22,0x12,0x70,0x65,0x6e,0x23,0x24,0x13,0x6c,0x6f,0x73, -0x65,0x25,0x20,0x12,0x6f,0x6e,0x65,0x21,6,0x6f,0x65,0x6f,0x4a,0x72,0x5c,0x74, -0x64,0x76,0x1d,0x69,0x73,0x75,0x61,0x6c,0x6f,0x72,0x64,0x65,0x72,0x6c,0x65,0x66, -0x74,0x3d,0x18,0x76,0x65,0x72,0x73,0x74,0x72,0x75,0x63,0x6b,0x2d,0x13,0x69,0x67, -0x68,0x74,0x2f,0x11,0x6f,0x70,0x30,0x12,0x61,0x6e,0x64,2,0x62,0x32,0x6c,0x62, -0x72,0x13,0x69,0x67,0x68,0x74,0x3b,0x14,0x6f,0x74,0x74,0x6f,0x6d,0x32,0x12,0x61, -0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x35,0x12,0x65,0x66,0x74, -0x3f,0x12,0x65,0x66,0x74,0x36,0x17,0x61,0x6e,0x64,0x72,0x69,0x67,0x68,0x74,0x39, -0x62,0x2c,0x6c,0x5c,0x6e,0x10,0x61,0x21,0x14,0x6f,0x74,0x74,0x6f,0x6d,0x22,0x12, -0x61,0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x27,0x12,0x65,0x66, -0x74,0x25,0x12,0x65,0x66,0x74,0x28,0x17,0x61,0x6e,0x64,0x72,0x69,0x67,0x68,0x74, -0x2b,0xd,0x6e,0xaa,0x72,0x70,0x72,0x92,0x73,0xa2,0x46,0x74,0xa2,0x54,0x76,1, -0x69,0x60,0x6f,0x12,0x77,0x65,0x6c,0x62,1,0x64,0x3a,0x69,0x19,0x6e,0x64,0x65, -0x70,0x65,0x6e,0x64,0x65,0x6e,0x74,0x67,0x17,0x65,0x70,0x65,0x6e,0x64,0x65,0x6e, -0x74,0x65,1,0x72,0x2e,0x73,0x13,0x61,0x72,0x67,0x61,0x61,0x12,0x61,0x6d,0x61, -0x5f,0x1d,0x65,0x67,0x69,0x73,0x74,0x65,0x72,0x73,0x68,0x69,0x66,0x74,0x65,0x72, -0x57,0x1e,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x6d,0x6f,0x64,0x69,0x66,0x69,0x65, -0x72,0x59,0x12,0x6f,0x6e,0x65,1,0x6c,0x2c,0x6d,0x12,0x61,0x72,0x6b,0x5d,0x14, -0x65,0x74,0x74,0x65,0x72,0x5b,0x6e,0x3c,0x6f,0x7c,0x70,0x18,0x75,0x72,0x65,0x6b, -0x69,0x6c,0x6c,0x65,0x72,0x55,1,0x6f,0x4c,0x75,1,0x6b,0x3c,0x6d,0x12,0x62, -0x65,0x72,0x50,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x53,0x11,0x74,0x61,0x4f,0x16, -0x6e,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x4d,0x13,0x74,0x68,0x65,0x72,0x21,0x67,0x3e, -0x67,0x4a,0x69,0x64,0x6a,0x82,0x6d,0x1d,0x6f,0x64,0x69,0x66,0x79,0x69,0x6e,0x67, -0x6c,0x65,0x74,0x74,0x65,0x72,0x4b,0x1c,0x65,0x6d,0x69,0x6e,0x61,0x74,0x69,0x6f, -0x6e,0x6d,0x61,0x72,0x6b,0x45,0x1e,0x6e,0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x73, -0x74,0x61,0x63,0x6b,0x65,0x72,0x47,0x14,0x6f,0x69,0x6e,0x65,0x72,0x49,0x61,0xa2, -0xba,0x62,0xa2,0xc0,0x63,1,0x61,0xa2,0xa2,0x6f,0x16,0x6e,0x73,0x6f,0x6e,0x61, -0x6e,0x74,0x2a,8,0x6b,0x67,0x6b,0x48,0x6d,0x52,0x70,0x5c,0x73,0xa2,0x42,0x77, -0x19,0x69,0x74,0x68,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x43,0x14,0x69,0x6c,0x6c, -0x65,0x72,0x35,0x14,0x65,0x64,0x69,0x61,0x6c,0x37,1,0x6c,0x52,0x72,0x10,0x65, -1,0x63,0x2e,0x66,0x13,0x69,0x78,0x65,0x64,0x3d,0x19,0x65,0x64,0x69,0x6e,0x67, -0x72,0x65,0x70,0x68,0x61,0x3b,0x18,0x61,0x63,0x65,0x68,0x6f,0x6c,0x64,0x65,0x72, -0x39,0x10,0x75,1,0x62,0x3e,0x63,0x1b,0x63,0x65,0x65,0x64,0x69,0x6e,0x67,0x72, -0x65,0x70,0x68,0x61,0x41,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x64,0x3f,0x64,0x4c,0x66, -0x52,0x68,0x5a,0x69,0x1e,0x6e,0x69,0x74,0x69,0x61,0x6c,0x70,0x6f,0x73,0x74,0x66, -0x69,0x78,0x65,0x64,0x33,0x12,0x65,0x61,0x64,0x2d,0x13,0x69,0x6e,0x61,0x6c,0x2f, -0x18,0x65,0x61,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,0x1d,0x6e,0x74,0x69,0x6c, -0x6c,0x61,0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x29,0x16,0x76,0x61,0x67,0x72, -0x61,0x68,0x61,0x23,1,0x69,0x4a,0x72,0x10,0x61,0x1f,0x68,0x6d,0x69,0x6a,0x6f, -0x69,0x6e,0x69,0x6e,0x67,0x6e,0x75,0x6d,0x62,0x65,0x72,0x27,0x12,0x6e,0x64,0x75, -0x25,2,0x72,0x38,0x74,0x46,0x75,0x26,0x15,0x70,0x72,0x69,0x67,0x68,0x74,0x27, -0x20,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x21,1,0x72,0x24,0x75,0x25,0x22,0x18, -0x61,0x6e,0x73,0x66,0x6f,0x72,0x6d,0x65,0x64,1,0x72,0x32,0x75,0x15,0x70,0x72, -0x69,0x67,0x68,0x74,0x25,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x23,0xd,0x6e,0xc1, -0x86,0x73,0xa8,0x73,0x4c,0x74,0xa2,0x76,0x75,0xa2,0x83,0x7a,0xd8,0x70,0,2, -0x6c,0xd9,0x20,0,0x70,0xd9,0x40,0,0x73,0xc3,0,0xfe,0xf,0,0,0, -7,0x6f,0x3c,0x6f,0xff,8,0,0,0,0x70,0x3a,0x75,0x6e,0x79,0x13,0x6d, -0x62,0x6f,0x6c,0xff,0xf,0,0,0,0x11,0x61,0x63,1,0x65,0x34,0x69,0x15, -0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0,0x18,0x73,0x65,0x70,0x61,0x72,0x61,0x74, -0x6f,0x72,0xc3,0,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0xe1,0,0,0x63, -0xff,2,0,0,0,0x65,0x38,0x6b,0xff,4,0,0,0,0x6d,0xff,1, -0,0,0,0x16,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x70,0,0x1d,0x69, -0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,1,0x6e, -0x40,0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72, -0x25,0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x23,0x6e,0xa2,0x69,0x6f,0xa2, -0x89,0x70,0xfe,0x30,0xf8,0,0,9,0x69,0x33,0x69,0xff,0x10,0,0,0, -0x6f,0xfd,0x80,0,0,0x72,0x54,0x73,0xf9,0,0,0x75,0x12,0x6e,0x63,0x74, -0xfe,0x30,0xf8,0,0,0x15,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x30,0xf8,0, -0,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xdd,0,0,0x61,0x48,0x63, -0xfd,0x40,0,0,0x64,0xe9,0,0,0x65,0xfd,0x20,0,0,0x66,0xff,0x20, -0,0,0,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72, -0x61,0x74,0x6f,0x72,0xd9,0x40,0,0xbe,0,3,0x64,0xa7,0,0x6c,0xab,0, -0x6f,0x30,0x75,0x13,0x6d,0x62,0x65,0x72,0xbf,0,0xb2,0,0x1b,0x6e,0x73,0x70, -0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa1,1,0x70,0x92,0x74,0x12,0x68, -0x65,0x72,0xe6,0x80,1,3,0x6c,0x40,0x6e,0x4a,0x70,0x56,0x73,0x14,0x79,0x6d, -0x62,0x6f,0x6c,0xff,8,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x61,0x14, -0x75,0x6d,0x62,0x65,0x72,0xb3,0,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, -0x6f,0x6e,0xfd,0x80,0,0,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, -0x74,0x69,0x6f,0x6e,0xf9,0,0,0x66,0xc0,0xc4,0x66,0xa2,0x47,0x69,0xa2,0x64, -0x6c,0xa2,0x79,0x6d,0xa4,0xc0,4,0x61,0x6c,0x63,0xa5,0,0x65,0xa3,0x80,0x6e, -0xa1,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c,0x38,0x73,0x14,0x79,0x6d, -0x62,0x6f,0x6c,0xff,4,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x41,1, -0x72,0x3c,0x74,0x16,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff,1,0,0,0, -0x10,0x6b,0xa5,0xc0,1,0x69,0x32,0x6f,0x13,0x72,0x6d,0x61,0x74,0xdb,0,0, -0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff, -0x20,0,0,0,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75,0x6e,0x63, -0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x10,0,0,0,0x9c,7,0x6d,0x18, -0x6d,0x41,0x6f,0x28,0x74,0x31,0x75,0x25,0x60,0x1c,0x77,0x65,0x72,0x63,0x61,0x73, -0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x29,0x63,0x3d,0x65,0x28,0x69,0x42,0x6c,0x29, -0x13,0x74,0x74,0x65,0x72,0x9c,0x15,0x6e,0x75,0x6d,0x62,0x65,0x72,0xab,0,0x1a, -0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x20,0,0x63,0x46, -0x64,0xa2,0x96,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61,0x72, -0x6b,0xa3,0x80,0xe6,0x80,1,7,0x6e,0x57,0x6e,0x52,0x6f,0x5e,0x73,0xe1,0, -0,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff, -2,0,0,0,0x22,0x12,0x74,0x72,0x6c,0xd9,0x80,0,0xdc,0,0,1, -0x6d,0x62,0x6e,1,0x6e,0x30,0x74,0x12,0x72,0x6f,0x6c,0xd9,0x80,0,0x1f,0x65, -0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd, -0x40,0,0,0x19,0x62,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0xc0, -0x61,0x58,0x63,0xd9,0x80,0,0x66,0xdb,0,0,0x6c,0x1d,0x6f,0x73,0x65,0x70, -0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x20,0,0,0x18,0x73, -0x65,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,2,0x61,0x32,0x65,0x50,0x69,0x12, -0x67,0x69,0x74,0xa7,0,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, -0x69,0x6f,0x6e,0xe9,0,0,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62, -0x65,0x72,0xa7,0 +0x61,0x6b,0xc3,8,2,0x64,0x4a,0x6e,0xa2,0x91,0x73,1,0x63,0xd9,0x40,3, +0x6f,0x16,0x63,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0xd9,0x40,3,2,0x63,0xa2,0x44, +0x65,0xa2,0x6c,0x73,0x40,2,0x62,0x48,0x74,0x64,0x75,0xa2,0x48,0x1b,0x6e,0x61, +0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0xa3,0x48,0x44,0x1c,0x69,0x6e, +0x61,0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x45,0x46,1,0x61,0x40, +0x72,0x1c,0x69,0x6e,0x61,0x72,0x79,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x47, +0x11,0x72,0x74,0x41,0x3e,0x10,0x6f,1,0x6d,0x30,0x6e,0x14,0x74,0x69,0x6e,0x75, +0x65,0x3f,0x16,0x70,0x61,0x74,0x6d,0x61,0x74,0x68,1,0x63,0x30,0x73,0x13,0x74, +0x61,0x72,0x74,0xa3,0x49,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0xa3,0x4a,0x10, +0x6f,0x42,0x16,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x43,2,0x64,0x2e,0x70,0x86, +0x73,0x10,0x63,0xc3,0x17,0x11,0x69,0x63,1,0x70,0x46,0x73,0x1e,0x79,0x6c,0x6c, +0x61,0x62,0x69,0x63,0x63,0x61,0x74,0x65,0x67,0x6f,0x72,0x79,0xc3,0x17,0x10,0x6f, +0x1f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x63,0x61,0x74,0x65,0x67,0x6f,0x72, +0x79,0xc3,0x16,0x10,0x63,0xc3,0x16,2,0x67,0xc3,6,0x6f,0x26,0x74,0xc3,7, +0x11,0x69,0x6e,1,0x63,0x4a,0x69,0x11,0x6e,0x67,1,0x67,0x2e,0x74,0x12,0x79, +0x70,0x65,0xc3,7,0x13,0x72,0x6f,0x75,0x70,0xc3,6,0x48,0x15,0x6f,0x6e,0x74, +0x72,0x6f,0x6c,0x49,0x66,0x86,0x67,0xa2,0x4a,0x68,3,0x61,0x36,0x65,0x58,0x73, +0x68,0x79,0x13,0x70,0x68,0x65,0x6e,0x3d,0x1f,0x6e,0x67,0x75,0x6c,0x73,0x79,0x6c, +0x6c,0x61,0x62,0x6c,0x65,0x74,0x79,0x70,0x65,0xc3,0xb,0x10,0x78,0x3a,0x14,0x64, +0x69,0x67,0x69,0x74,0x3b,0x10,0x74,0xc3,0xb,0x16,0x75,0x6c,0x6c,0x63,0x6f,0x6d, +0x70,0x1f,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x65,0x78,0x63,0x6c,0x75,0x73,0x69, +0x6f,0x6e,0x33,2,0x63,0xa2,0x44,0x65,0xa2,0x4b,0x72,3,0x61,0x34,0x62,0x84, +0x65,0x8a,0x6c,0x12,0x69,0x6e,0x6b,0x39,0x11,0x70,0x68,0x7c,0x12,0x65,0x6d,0x65, +3,0x62,0x5e,0x63,0x30,0x65,0x48,0x6c,0x12,0x69,0x6e,0x6b,0x39,0x1a,0x6c,0x75, +0x73,0x74,0x65,0x72,0x62,0x72,0x65,0x61,0x6b,0xc3,0x12,0x14,0x78,0x74,0x65,0x6e, +0x64,0x37,0x12,0x61,0x73,0x65,0x35,0x11,0x78,0x74,0x37,0xc2,5,1,0x62,0xc3, +0x12,0x6d,0xd9,0x20,0,0x1c,0x6e,0x65,0x72,0x61,0x6c,0x63,0x61,0x74,0x65,0x67, +0x6f,0x72,0x79,0xc2,5,0x13,0x6d,0x61,0x73,0x6b,0xd9,0x20,0,0x61,0xa2,0xa2, +0x62,0xa2,0xd0,0x63,0xa4,0x4f,0x64,0xa6,0x1c,0x65,5,0x6d,0x75,0x6d,0x6e,0x70, +0xa2,0x6b,0x78,0x10,0x74,0x30,1,0x65,0x2c,0x70,0x12,0x69,0x63,0x74,0xa1,0x12, +0x6e,0x64,0x65,1,0x64,0x24,0x72,0x31,0x1b,0x70,0x69,0x63,0x74,0x6f,0x67,0x72, +0x61,0x70,0x68,0x69,0x63,0xa1,0x10,0x6f,1,0x64,0x97,0x6a,0x10,0x69,0x92,3, +0x63,0x44,0x6b,0x54,0x6d,0x70,0x70,0x1a,0x72,0x65,0x73,0x65,0x6e,0x74,0x61,0x74, +0x69,0x6f,0x6e,0x95,0x17,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x9b,0x1c,0x65, +0x79,0x63,0x61,0x70,0x73,0x65,0x71,0x75,0x65,0x6e,0x63,0x65,0xa3,0x42,0x16,0x6f, +0x64,0x69,0x66,0x69,0x65,0x72,0x96,0x13,0x62,0x61,0x73,0x65,0x99,0x12,0x72,0x65, +0x73,0x95,0x61,0x30,0x62,0x4e,0x63,0x12,0x6f,0x6d,0x70,0x9b,0xc2,4,0x1b,0x73, +0x74,0x61,0x73,0x69,0x61,0x6e,0x77,0x69,0x64,0x74,0x68,0xc3,4,0x12,0x61,0x73, +0x65,0x99,3,0x67,0x44,0x68,0x4a,0x6c,0x4e,0x73,0x1a,0x63,0x69,0x69,0x68,0x65, +0x78,0x64,0x69,0x67,0x69,0x74,0x23,0x10,0x65,0xd9,0x40,0,0x11,0x65,0x78,0x23, +1,0x6e,0x38,0x70,0x11,0x68,0x61,0x20,0x14,0x62,0x65,0x74,0x69,0x63,0x21,0x11, +0x75,0x6d,0x79,5,0x6c,0x22,0x6c,0x36,0x6d,0x52,0x70,1,0x62,0xd9,0x40,0xd, +0x74,0xc3,0x15,2,0x61,0x32,0x6b,0xc3,1,0x6f,0x11,0x63,0x6b,0xc3,1,0x11, +0x6e,0x6b,0x7b,0x10,0x67,0xd9,0x40,1,0x61,0xa2,0x4f,0x63,0xc3,0,0x69,0x11, +0x64,0x69,2,0x63,0x54,0x6d,0x74,0x70,0x1b,0x61,0x69,0x72,0x65,0x64,0x62,0x72, +0x61,0x63,0x6b,0x65,0x74,0xd8,0x40,0xd,0x13,0x74,0x79,0x70,0x65,0xc3,0x15,0x24, +1,0x6c,0x30,0x6f,0x14,0x6e,0x74,0x72,0x6f,0x6c,0x25,0x12,0x61,0x73,0x73,0xc3, +0,0x26,0x14,0x69,0x72,0x72,0x6f,0x72,1,0x65,0x38,0x69,0x16,0x6e,0x67,0x67, +0x6c,0x79,0x70,0x68,0xd9,0x40,1,0x10,0x64,0x27,0x17,0x73,0x69,0x63,0x65,0x6d, +0x6f,0x6a,0x69,0xa3,0x41,6,0x68,0x7c,0x68,0x54,0x69,0x85,0x6f,0xa2,0x6f,0x77, +4,0x63,0x30,0x6b,0x36,0x6c,0x87,0x74,0x8b,0x75,0x89,1,0x66,0x8d,0x6d,0x8f, +0x11,0x63,0x66,0x91,0x18,0x61,0x6e,0x67,0x65,0x73,0x77,0x68,0x65,0x6e,4,0x63, +0x44,0x6c,0x6c,0x6e,0x7e,0x74,0x98,0x75,0x18,0x70,0x70,0x65,0x72,0x63,0x61,0x73, +0x65,0x64,0x89,0x12,0x61,0x73,0x65,1,0x66,0x30,0x6d,0x14,0x61,0x70,0x70,0x65, +0x64,0x8f,0x14,0x6f,0x6c,0x64,0x65,0x64,0x8d,0x18,0x6f,0x77,0x65,0x72,0x63,0x61, +0x73,0x65,0x64,0x87,0x1c,0x66,0x6b,0x63,0x63,0x61,0x73,0x65,0x66,0x6f,0x6c,0x64, +0x65,0x64,0x91,0x18,0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x64,0x8b,0x13,0x6d, +0x70,0x65,0x78,0x33,0x61,0x2e,0x63,0xa2,0x48,0x66,0xd9,0x40,2,1,0x6e,0x72, +0x73,0x10,0x65,3,0x64,0x83,0x66,0x3a,0x69,0x4a,0x73,0x17,0x65,0x6e,0x73,0x69, +0x74,0x69,0x76,0x65,0x65,0x15,0x6f,0x6c,0x64,0x69,0x6e,0x67,0xd9,0x40,2,0x17, +0x67,0x6e,0x6f,0x72,0x61,0x62,0x6c,0x65,0x85,0x13,0x6f,0x6e,0x69,0x63,0x1f,0x61, +0x6c,0x63,0x6f,0x6d,0x62,0x69,0x6e,0x69,0x6e,0x67,0x63,0x6c,0x61,0x73,0x73,0xc3, +2,0x10,0x63,0xc3,2,3,0x61,0x30,0x65,0x34,0x69,0xa2,0x41,0x74,0xc3,3, +0x11,0x73,0x68,0x29,2,0x63,0x3a,0x66,0x58,0x70,0x2c,0x16,0x72,0x65,0x63,0x61, +0x74,0x65,0x64,0x2d,0x1d,0x6f,0x6d,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x74, +0x79,0x70,0x65,0xc3,3,0x15,0x61,0x75,0x6c,0x74,0x69,0x67,0x1f,0x6e,0x6f,0x72, +0x61,0x62,0x6c,0x65,0x63,0x6f,0x64,0x65,0x70,0x6f,0x69,0x6e,0x74,0x2b,0x2a,0x10, +0x61,0x2e,0x15,0x63,0x72,0x69,0x74,0x69,0x63,0x2f,3,0x66,0x34,0x6e,0x3e,0x74, +0x42,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x13,0x61,0x6c,0x73,0x65,0x21,0x20,0x10, +0x6f,0x21,0x22,0x12,0x72,0x75,0x65,0x23,0xb,0x6b,0x5b,0x6f,0x23,0x6f,0x3c,0x72, +0x4c,0x76,1,0x69,0x24,0x72,0x33,0x13,0x72,0x61,0x6d,0x61,0x33,0x10,0x76,0x22, +0x14,0x65,0x72,0x6c,0x61,0x79,0x23,0xa2,0xe2,0x13,0x69,0x67,0x68,0x74,0xa3,0xe2, +0x6b,0x58,0x6c,0x74,0x6e,3,0x6b,0x2f,0x6f,0x30,0x72,0x21,0x75,0x12,0x6b,0x74, +0x61,0x2f,0x19,0x74,0x72,0x65,0x6f,0x72,0x64,0x65,0x72,0x65,0x64,0x21,1,0x61, +0x24,0x76,0x31,0x18,0x6e,0x61,0x76,0x6f,0x69,0x63,0x69,0x6e,0x67,0x31,0xa2,0xe0, +0x12,0x65,0x66,0x74,0xa3,0xe0,0x64,0x45,0x64,0x4e,0x68,0x88,0x69,1,0x6f,0x26, +0x73,0xa3,0xf0,0x1a,0x74,0x61,0x73,0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74,0xa3, +0xf0,2,0x61,0xa3,0xea,0x62,0xa3,0xe9,0x6f,0x13,0x75,0x62,0x6c,0x65,1,0x61, +0x30,0x62,0x13,0x65,0x6c,0x6f,0x77,0xa3,0xe9,0x13,0x62,0x6f,0x76,0x65,0xa3,0xea, +0x12,0x61,0x6e,0x72,0x2c,0x15,0x65,0x61,0x64,0x69,0x6e,0x67,0x2d,0x61,0xa2,0x7b, +0x62,0xa2,0xd4,0x63,0x11,0x63,0x63,4,0x31,0x3c,0x32,0xa2,0x42,0x33,0xa2,0x56, +0x38,0xa2,0x64,0x39,0x10,0x31,0xa3,0x5b,9,0x35,0xa,0x35,0x3f,0x36,0x41,0x37, +0x43,0x38,0x45,0x39,0x47,0x30,0x30,0x31,0x3c,0x32,0x42,0x33,0x4e,0x34,0x3d,0x34, +1,0x33,0xa3,0x67,0x37,0xa3,0x6b,0x36,0x10,0x38,0xa3,0x76,0x38,1,0x32,0xa3, +0x7a,0x39,0xa3,0x81,0x3a,2,0x30,0xa3,0x82,0x32,0xa3,0x84,0x33,0xa3,0x85,9, +0x35,0xa,0x35,0x53,0x36,0x55,0x37,0x57,0x38,0x59,0x39,0x5b,0x30,0x49,0x31,0x4b, +0x32,0x4d,0x33,0x4f,0x34,0x51,6,0x33,8,0x33,0x63,0x34,0x65,0x35,0x67,0x36, +0x69,0x30,0x5d,0x31,0x5f,0x32,0x61,0x10,0x34,0xa3,0x54,0xa2,0xe6,3,0x62,0xa0, +0x6c,0xa3,0xe4,0x72,0xa3,0xe8,0x74,2,0x61,0x74,0x62,0x7c,0x74,0x14,0x61,0x63, +0x68,0x65,0x64,1,0x61,0x3e,0x62,0x13,0x65,0x6c,0x6f,0x77,0xa2,0xca,0x13,0x6c, +0x65,0x66,0x74,0xa3,0xc8,0x13,0x62,0x6f,0x76,0x65,0xa2,0xd6,0x14,0x72,0x69,0x67, +0x68,0x74,0xa3,0xd8,0xa2,0xd6,0x10,0x72,0xa3,0xd8,0xa2,0xca,0x10,0x6c,0xa3,0xc8, +0x12,0x6f,0x76,0x65,0xa2,0xe6,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3, +0xe8,0x12,0x65,0x66,0x74,0xa3,0xe4,0xa2,0xdc,2,0x65,0x2c,0x6c,0xa3,0xda,0x72, +0xa3,0xde,0x12,0x6c,0x6f,0x77,0xa2,0xdc,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68, +0x74,0xa3,0xde,0x12,0x65,0x66,0x74,0xa3,0xda,0xb,0x6e,0xc0,0xca,0x72,0x5f,0x72, +0x46,0x73,0xa2,0x48,0x77,1,0x68,0x24,0x73,0x33,0x17,0x69,0x74,0x65,0x73,0x70, +0x61,0x63,0x65,0x33,0x22,1,0x69,0x30,0x6c,2,0x65,0x3d,0x69,0x4b,0x6f,0x3f, +0x18,0x67,0x68,0x74,0x74,0x6f,0x6c,0x65,0x66,0x74,0x22,2,0x65,0x38,0x69,0x48, +0x6f,0x16,0x76,0x65,0x72,0x72,0x69,0x64,0x65,0x3f,0x17,0x6d,0x62,0x65,0x64,0x64, +0x69,0x6e,0x67,0x3d,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4b,0x30,0x1e,0x65,0x67, +0x6d,0x65,0x6e,0x74,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x31,0x6e,0xa2, +0x41,0x6f,0xa2,0x53,0x70,2,0x61,0x66,0x64,0x86,0x6f,0x1b,0x70,0x64,0x69,0x72, +0x65,0x63,0x74,0x69,0x6f,0x6e,0x61,0x6c,1,0x66,0x32,0x69,0x15,0x73,0x6f,0x6c, +0x61,0x74,0x65,0x4d,0x14,0x6f,0x72,0x6d,0x61,0x74,0x41,0x1f,0x72,0x61,0x67,0x72, +0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2f,1,0x66,0x41, +0x69,0x4d,1,0x6f,0x28,0x73,0x10,0x6d,0x43,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69, +0x6e,0x67,0x6d,0x61,0x72,0x6b,0x43,1,0x6e,0x35,0x74,0x19,0x68,0x65,0x72,0x6e, +0x65,0x75,0x74,0x72,0x61,0x6c,0x35,0x65,0x88,0x65,0x98,0x66,0xa2,0x6a,0x6c,0x20, +1,0x65,0x30,0x72,2,0x65,0x37,0x69,0x49,0x6f,0x39,0x18,0x66,0x74,0x74,0x6f, +0x72,0x69,0x67,0x68,0x74,0x20,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72, +0x72,0x69,0x64,0x65,0x39,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x37,0x15, +0x73,0x6f,0x6c,0x61,0x74,0x65,0x49,3,0x6e,0x25,0x73,0x27,0x74,0x29,0x75,0x15, +0x72,0x6f,0x70,0x65,0x61,0x6e,2,0x6e,0x3c,0x73,0x46,0x74,0x18,0x65,0x72,0x6d, +0x69,0x6e,0x61,0x74,0x6f,0x72,0x29,0x14,0x75,0x6d,0x62,0x65,0x72,0x25,0x17,0x65, +0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x27,1,0x69,0x28,0x73,0x10,0x69,0x47,0x1f, +0x72,0x73,0x74,0x73,0x74,0x72,0x6f,0x6e,0x67,0x69,0x73,0x6f,0x6c,0x61,0x74,0x65, +0x47,0x61,0x4e,0x62,0x84,0x63,1,0x6f,0x24,0x73,0x2d,0x1c,0x6d,0x6d,0x6f,0x6e, +0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2d,2,0x6c,0x3b,0x6e,0x2b,0x72, +0x13,0x61,0x62,0x69,0x63,1,0x6c,0x30,0x6e,0x14,0x75,0x6d,0x62,0x65,0x72,0x2b, +0x14,0x65,0x74,0x74,0x65,0x72,0x3b,0x2e,1,0x6e,0x45,0x6f,0x1c,0x75,0x6e,0x64, +0x61,0x72,0x79,0x6e,0x65,0x75,0x74,0x72,0x61,0x6c,0x45,0,0x16,0x6d,0xc9,0x20, +0x74,0xc2,0x30,0x77,0x89,0x77,0x86,0x79,0xa2,0x46,0x7a,1,0x61,0x58,0x6e,0x1a, +0x61,0x6d,0x65,0x6e,0x6e,0x79,0x6d,0x75,0x73,0x69,0x63,0xa4,0x40,0x19,0x61,0x6c, +0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa5,0x40,0x1c,0x6e,0x61,0x62,0x61,0x7a, +0x61,0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa5,0x18,0x10,0x61,1,0x6e,0x36,0x72, +0x16,0x61,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0xfc,0x12,0x63,0x68,0x6f,0xa5,0x2c, +1,0x65,0x88,0x69,2,0x6a,0x3c,0x72,0x68,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62, +0x6c,0x65,0x73,0xa3,0x48,0x12,0x69,0x6e,0x67,0xa2,0x74,0x1e,0x68,0x65,0x78,0x61, +0x67,0x72,0x61,0x6d,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x74,0x16,0x61,0x64, +0x69,0x63,0x61,0x6c,0x73,0xa3,0x49,0x13,0x7a,0x69,0x64,0x69,0xa5,0x34,0x74,0xa2, +0x65,0x75,0xa4,0x4f,0x76,3,0x61,0x3c,0x65,0x80,0x69,0xa2,0x50,0x73,0xa2,0x6c, +0x12,0x73,0x75,0x70,0xa3,0x7d,1,0x69,0xa3,0x9f,0x72,0x1e,0x69,0x61,0x74,0x69, +0x6f,0x6e,0x73,0x65,0x6c,0x65,0x63,0x74,0x6f,0x72,0x73,0xa2,0x6c,0x19,0x73,0x75, +0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x7d,1,0x64,0x3c,0x72,0x19,0x74, +0x69,0x63,0x61,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x91,0x14,0x69,0x63,0x65,0x78, +0x74,0xa2,0xaf,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xaf,0x15,0x74,0x68, +0x6b,0x75,0x71,0x69,0xa5,0x3f,5,0x69,0x3f,0x69,0x5a,0x6f,0x8c,0x72,0x1c,0x61, +0x6e,0x73,0x70,0x6f,0x72,0x74,0x61,0x6e,0x64,0x6d,0x61,0x70,0xa2,0xcf,0x16,0x73, +0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xcf,2,0x62,0x34,0x66,0x3c,0x72,0x13,0x68, +0x75,0x74,0x61,0xa3,0xfb,0x13,0x65,0x74,0x61,0x6e,0x57,0x14,0x69,0x6e,0x61,0x67, +0x68,0xa3,0x90,0x11,0x74,0x6f,0xa5,0x3d,0x61,0x3e,0x65,0xa2,0xa0,0x68,0x10,0x61, +1,0x61,0x24,0x69,0x53,0x11,0x6e,0x61,0x3d,4,0x67,0x8e,0x69,0xa2,0x49,0x6b, +0xa2,0x72,0x6d,0xa2,0x74,0x6e,0x10,0x67,1,0x73,0x68,0x75,0x10,0x74,0xa4,0x10, +1,0x63,0x40,0x73,0x11,0x75,0x70,0xa4,0x33,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e, +0x74,0xa5,0x33,0x18,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0xa5,0x11,0x10, +0x61,0xa5,0x3c,2,0x61,0x2a,0x62,0x32,0x73,0xa3,0x60,0x12,0x6c,0x6f,0x67,0xa3, +0x62,0x13,0x61,0x6e,0x77,0x61,0xa3,0x65,3,0x6c,0x52,0x74,0x56,0x76,0x5e,0x78, +0x16,0x75,0x61,0x6e,0x6a,0x69,0x6e,0x67,0xa2,0x7c,0x16,0x73,0x79,0x6d,0x62,0x6f, +0x6c,0x73,0xa3,0x7c,0x10,0x65,0xa3,0x70,0x12,0x68,0x61,0x6d,0xa3,0xae,0x12,0x69, +0x65,0x74,0xa3,0xb7,0x11,0x72,0x69,0xa3,0xdc,0x11,0x69,0x6c,0x48,0x12,0x73,0x75, +0x70,0xa4,0x2b,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x2b,0x13,0x6c,0x75, +0x67,0x75,0x4b,2,0x63,0x8c,0x67,0xa2,0x41,0x6e,0x1f,0x69,0x66,0x69,0x65,0x64, +0x63,0x61,0x6e,0x61,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f,0x1f,0x72,0x69,0x67,0x69, +0x6e,0x61,0x6c,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x62,0x17,0x65,0x78, +0x74,0x65,0x6e,0x64,0x65,0x64,0xa2,0xad,0x10,0x61,0xa5,0x3e,0x11,0x61,0x73,0x62, +0x12,0x65,0x78,0x74,0xa2,0xad,0x10,0x61,0xa5,0x3e,0x15,0x61,0x72,0x69,0x74,0x69, +0x63,0xa3,0x78,0x70,0xc3,0x4b,0x70,0xa6,0x61,0x72,0xa8,0x1d,0x73,7,0x6f,0xc1, +0xbe,0x6f,0xa2,0x69,0x70,0xa2,0x85,0x75,0xa2,0xa4,0x79,2,0x6c,0x50,0x6d,0x62, +0x72,0x12,0x69,0x61,0x63,0x3a,0x12,0x73,0x75,0x70,0xa4,0x17,0x16,0x70,0x6c,0x65, +0x6d,0x65,0x6e,0x74,0xa5,0x17,0x17,0x6f,0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0xa3, +0x8f,0x13,0x62,0x6f,0x6c,0x73,1,0x61,0x4c,0x66,0x10,0x6f,0x1f,0x72,0x6c,0x65, +0x67,0x61,0x63,0x79,0x63,0x6f,0x6d,0x70,0x75,0x74,0x69,0x6e,0x67,0xa5,0x32,0x1f, +0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x78,0x74, +1,0x61,0xa5,0x2a,0x65,0x14,0x6e,0x64,0x65,0x64,0x61,0xa5,0x2a,2,0x67,0x34, +0x72,0x3e,0x79,0x13,0x6f,0x6d,0x62,0x6f,0xa5,0x16,0x13,0x64,0x69,0x61,0x6e,0xa5, +0x23,0x17,0x61,0x73,0x6f,0x6d,0x70,0x65,0x6e,0x67,0xa3,0xda,1,0x61,0x32,0x65, +0x14,0x63,0x69,0x61,0x6c,0x73,0xa3,0x56,0x12,0x63,0x69,0x6e,0x1f,0x67,0x6d,0x6f, +0x64,0x69,0x66,0x69,0x65,0x72,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,2,0x6e, +0x48,0x70,0x76,0x74,0x1d,0x74,0x6f,0x6e,0x73,0x69,0x67,0x6e,0x77,0x72,0x69,0x74, +0x69,0x6e,0x67,0xa5,6,0x15,0x64,0x61,0x6e,0x65,0x73,0x65,0xa2,0x9b,0x12,0x73, +0x75,0x70,0xa2,0xdb,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xdb,4,0x61, +0xa2,0xa8,0x65,0x5c,0x6d,0x9e,0x70,0xa2,0x4b,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f, +0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73, +0xa5,5,0x10,0x72,1,0x61,0x4e,0x73,0x12,0x63,0x72,0x69,0x1f,0x70,0x74,0x73, +0x61,0x6e,0x64,0x73,0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74,0x73,0x73,0x14,0x6e, +0x64,0x73,0x75,0x62,0x73,0x1b,0x61,0x74,0x68,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f, +0x72,0x73,0xa3,0x6a,1,0x6c,0x40,0x75,1,0x61,0x6e,0x6e,0x17,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x15,0x65,0x6d,0x65,0x6e,0x74,0x61,1,0x6c, +0x50,0x72,0x1e,0x79,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0x61,0x72, +0x65,0x61,1,0x61,0xa3,0x6d,0x62,0xa3,0x6e,3,0x61,0x5c,0x6d,0x78,0x70,0xa2, +0x41,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63, +0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5,0x14,0x72,0x72,0x6f,0x77,0x73, +2,0x61,0xa3,0x67,0x62,0xa3,0x68,0x63,0xa3,0xfa,0x13,0x61,0x74,0x68,0x65,0x1f, +0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73, +0xa3,0x6a,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x61, +0x88,0x68,0xa2,0x48,0x69,0xa2,0x71,0x6d,0x12,0x61,0x6c,0x6c,1,0x66,0x46,0x6b, +0x15,0x61,0x6e,0x61,0x65,0x78,0x74,0xa4,0x29,0x15,0x65,0x6e,0x73,0x69,0x6f,0x6e, +0xa5,0x29,0x12,0x6f,0x72,0x6d,1,0x73,0xa3,0x54,0x76,0x16,0x61,0x72,0x69,0x61, +0x6e,0x74,0x73,0xa3,0x54,1,0x6d,0x36,0x75,0x16,0x72,0x61,0x73,0x68,0x74,0x72, +0x61,0xa3,0xa1,0x15,0x61,0x72,0x69,0x74,0x61,0x6e,0xa3,0xac,1,0x61,0x52,0x6f, +0x13,0x72,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66,0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f, +0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa3,0xf7,1,0x72,0x2e,0x76,0x12,0x69,0x61,0x6e, +0xa3,0x79,0x12,0x61,0x64,0x61,0xa3,0xd9,1,0x64,0x50,0x6e,0x13,0x68,0x61,0x6c, +0x61,0x50,0x1d,0x61,0x72,0x63,0x68,0x61,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72, +0x73,0xa3,0xf9,0x13,0x64,0x68,0x61,0x6d,0xa3,0xf8,5,0x72,0x35,0x72,0x44,0x73, +0x64,0x75,1,0x61,0xa3,0x4e,0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, +0x71,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xa2,0x4e,0x13,0x61,0x72,0x65, +0x61,0xa3,0x4e,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76,0x69, +0xa3,0xf6,0x61,0x40,0x68,0x82,0x6c,0x19,0x61,0x79,0x69,0x6e,0x67,0x63,0x61,0x72, +0x64,0x73,0xa3,0xcc,2,0x68,0x38,0x6c,0x4a,0x75,0x15,0x63,0x69,0x6e,0x68,0x61, +0x75,0xa3,0xf5,0x17,0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0xf3,0x15,0x6d, +0x79,0x72,0x65,0x6e,0x65,0xa3,0xf4,1,0x61,0x8e,0x6f,1,0x65,0x74,0x6e,0x16, +0x65,0x74,0x69,0x63,0x65,0x78,0x74,0xa2,0x72,1,0x65,0x2c,0x73,0x11,0x75,0x70, +0xa3,0x8d,0x15,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa2,0x72,0x19,0x73,0x75,0x70,0x70, +0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x8d,0x15,0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3, +0x97,1,0x67,0x3e,0x69,0x13,0x73,0x74,0x6f,0x73,0xa2,0xa6,0x13,0x64,0x69,0x73, +0x63,0xa3,0xa6,0x12,0x73,0x70,0x61,0xa3,0x96,1,0x65,0x5c,0x75,1,0x6d,0x2a, +0x6e,0x11,0x69,0x63,0x67,0x10,0x69,0xa2,0xc0,0x1d,0x6e,0x75,0x6d,0x65,0x72,0x61, +0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xc0,0x13,0x6a,0x61,0x6e,0x67,0xa3, +0xa3,0x6d,0xa2,0xf0,0x6e,0xa8,0x23,0x6f,6,0x70,0x63,0x70,0x56,0x72,0x8a,0x73, +0xa2,0x4c,0x74,0x10,0x74,0x1f,0x6f,0x6d,0x61,0x6e,0x73,0x69,0x79,0x61,0x71,0x6e, +0x75,0x6d,0x62,0x65,0x72,0x73,0xa5,0x28,0x18,0x74,0x69,0x63,0x61,0x6c,0x63,0x68, +0x61,0x72,0x1f,0x61,0x63,0x74,0x65,0x72,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x74, +0x69,0x6f,0x6e,0x85,1,0x69,0x46,0x6e,0x1e,0x61,0x6d,0x65,0x6e,0x74,0x61,0x6c, +0x64,0x69,0x6e,0x67,0x62,0x61,0x74,0x73,0xa3,0xf2,0x11,0x79,0x61,0x47,1,0x61, +0x30,0x6d,0x13,0x61,0x6e,0x79,0x61,0xa3,0x7a,0x11,0x67,0x65,0xa5,0xf,0x63,0xa2, +0x7b,0x67,0xa2,0x7b,0x6c,1,0x63,0xa2,0x6c,0x64,6,0x70,0x42,0x70,0x3a,0x73, +0x5a,0x74,0x88,0x75,0x14,0x79,0x67,0x68,0x75,0x72,0xa5,0x3b,0x11,0x65,0x72,1, +0x6d,0x2e,0x73,0x12,0x69,0x61,0x6e,0xa3,0x8c,0x11,0x69,0x63,0xa3,0xf1,0x10,0x6f, +1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xbb, +0x13,0x64,0x69,0x61,0x6e,0xa5,0x22,0x14,0x75,0x72,0x6b,0x69,0x63,0xa3,0xbf,0x68, +0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e, +0xa3,0xf0,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa5,4,0x14,0x74,0x61, +0x6c,0x69,0x63,0xa3,0x58,0x13,0x68,0x69,0x6b,0x69,0xa3,0x9d,0x10,0x72,0x85,0x12, +0x68,0x61,0x6d,0x65,6,0x6f,0x86,0x6f,0x6c,0x72,0xa2,0x61,0x75,0xa2,0x62,0x79, +0x14,0x61,0x6e,0x6d,0x61,0x72,0x58,0x12,0x65,0x78,0x74,2,0x61,0xa3,0xb6,0x62, +0xa3,0xee,0x65,0x13,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb6,0x62,0xa3,0xee,1, +0x64,0x52,0x6e,0x15,0x67,0x6f,0x6c,0x69,0x61,0x6e,0x6a,0x12,0x73,0x75,0x70,0xa4, +0xd,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0xd,0x10,0x69,0xa2,0xec,0x13, +0x66,0x69,0x65,0x72,1,0x6c,0x3c,0x74,0x19,0x6f,0x6e,0x65,0x6c,0x65,0x74,0x74, +0x65,0x72,0x73,0xa3,0x8a,0x15,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,0x10,0x6f,0xa3, +0xed,1,0x6c,0x44,0x73,0x11,0x69,0x63,0xa2,0x5c,0x18,0x61,0x6c,0x73,0x79,0x6d, +0x62,0x6f,0x6c,0x73,0xa3,0x5c,0x13,0x74,0x61,0x6e,0x69,0xa5,3,0x61,0xa2,0x9b, +0x65,0xa4,0x4c,0x69,1,0x61,0xa2,0x8f,0x73,0x10,0x63,5,0x70,0x18,0x70,0xa2, +0x71,0x73,0x36,0x74,0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x15,0x79, +0x6d,0x62,0x6f,0x6c,0x73,0x8f,0x61,0xa2,0x66,0x65,0x46,0x6d,0x19,0x61,0x74,0x68, +0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x17,0x6c, +0x6c,0x61,0x6e,0x65,0x6f,0x75,0x73,2,0x6d,0x3a,0x73,0x6c,0x74,0x17,0x65,0x63, +0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x11,0x61,0x74,0x1f,0x68,0x65,0x6d,0x61,0x74, +0x69,0x63,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62, +0xa3,0x69,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8e,0x12,0x61,0x6e,0x64,1,0x61, +0x3c,0x70,0x19,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa3,0xcd,0x14, +0x72,0x72,0x6f,0x77,0x73,0xa3,0x73,0x10,0x6f,0xa3,0xd8,7,0x72,0x6f,0x72,0x44, +0x73,0x4e,0x74,0x62,0x79,0x19,0x61,0x6e,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73, +0xa5,0x20,0x13,0x63,0x68,0x65,0x6e,0xa5,0xc,0x18,0x61,0x72,0x61,0x6d,0x67,0x6f, +0x6e,0x64,0x69,0xa5,0x14,0x10,0x68,2,0x61,0x3a,0x65,0x4a,0x6f,0x17,0x70,0x65, +0x72,0x61,0x74,0x6f,0x72,0x73,0x7f,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d,0xa3, +0x5d,0x16,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,1,0x61,0x36,0x6f,0x17,0x70,0x65, +0x72,0x61,0x74,0x6f,0x72,0x73,0x7f,0x11,0x6c,0x70,0x1f,0x68,0x61,0x6e,0x75,0x6d, +0x65,0x72,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5d,0x68,0x50,0x6b, +0x7e,0x6c,0x88,0x6e,1,0x64,0x34,0x69,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3, +0xea,0x12,0x61,0x69,0x63,0xa3,0xc6,1,0x61,0x3e,0x6a,0x12,0x6f,0x6e,0x67,0xa2, +0xaa,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xaa,0x13,0x6a,0x61,0x6e,0x69,0xa3,0xe9, +0x13,0x61,0x73,0x61,0x72,0xa5,0x1f,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x4f,3, +0x64,0x6c,0x65,0x7e,0x6e,0xa2,0x47,0x72,0x14,0x6f,0x69,0x74,0x69,0x63,1,0x63, +0x3c,0x68,0x19,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xd7,0x15, +0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0xd6,0x17,0x65,0x66,0x61,0x69,0x64,0x72,0x69, +0x6e,0xa5,0x21,0x17,0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa2,0xb8,0x12,0x65, +0x78,0x74,0xa2,0xd5,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xd5,0x18,0x64, +0x65,0x6b,0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0xeb,6,0x6b,0x3b,0x6b,0x56,0x6f, +0x5a,0x75,0x64,0x79,0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67,0x70,0x75,0x61,0x63, +0x68,0x75,0x65,0x68,0x6d,0x6f,0x6e,0x67,0xa5,0x27,0x10,0x6f,0xa3,0x92,0x14,0x62, +0x6c,0x6f,0x63,0x6b,0x21,1,0x6d,0x2c,0x73,0x11,0x68,0x75,0xa5,0x15,0x17,0x62, +0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0x7b,0x61,0x44,0x62,0x21,0x65,0x10,0x77,1, +0x61,0xa5,0xe,0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0xa3,0x8b,2,0x62,0x3c,0x67, +0x4a,0x6e,0x17,0x64,0x69,0x6e,0x61,0x67,0x61,0x72,0x69,0xa5,0x26,0x15,0x61,0x74, +0x61,0x65,0x61,0x6e,0xa3,0xef,0x16,0x6d,0x75,0x6e,0x64,0x61,0x72,0x69,0xa5,0x47, +0x67,0xc4,0x5d,0x6a,0xc1,0xe4,0x6a,0xa2,0xdf,0x6b,0xa2,0xf8,0x6c,4,0x61,0x54, +0x65,0xa2,0x6b,0x69,0xa2,0x82,0x6f,0xa2,0xc1,0x79,1,0x63,0x2e,0x64,0x12,0x69, +0x61,0x6e,0xa3,0xa9,0x12,0x69,0x61,0x6e,0xa3,0xa7,1,0x6f,0x55,0x74,0x11,0x69, +0x6e,1,0x31,0x96,0x65,0x11,0x78,0x74,6,0x64,0x21,0x64,0xa3,0x95,0x65,0x2c, +0x66,0xa5,0x39,0x67,0xa5,0x3a,0xa2,0xe7,0x13,0x6e,0x64,0x65,0x64,6,0x64,0xc, +0x64,0xa3,0x95,0x65,0xa3,0xe7,0x66,0xa5,0x39,0x67,0xa5,0x3a,0x61,0x2a,0x62,0x29, +0x63,0xa3,0x94,0x26,0x18,0x64,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x6d,0x24, +0x12,0x73,0x75,0x70,0x24,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x25,1,0x70, +0x42,0x74,0x1d,0x74,0x65,0x72,0x6c,0x69,0x6b,0x65,0x73,0x79,0x6d,0x62,0x6f,0x6c, +0x73,0x79,0x12,0x63,0x68,0x61,0xa3,0x9c,2,0x6d,0x4e,0x6e,0x54,0x73,0x10,0x75, +0xa2,0xb0,0x12,0x73,0x75,0x70,0xa4,0x31,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, +0xa5,0x31,0x11,0x62,0x75,0xa3,0x6f,0x12,0x65,0x61,0x72,1,0x61,0xa3,0xe8,0x62, +1,0x69,0x38,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x61,0x72,0x79,0xa3,0x75,0x17, +0x64,0x65,0x6f,0x67,0x72,0x61,0x6d,0x73,0xa3,0x76,0x1a,0x77,0x73,0x75,0x72,0x72, +0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4d,0x10,0x61,1,0x6d,0x32,0x76,0x14,0x61, +0x6e,0x65,0x73,0x65,0xa3,0xb5,0x10,0x6f,0x5c,0x12,0x65,0x78,0x74,1,0x61,0xa3, +0xb4,0x62,0xa3,0xb9,1,0x61,0xa2,0x43,0x68,4,0x61,0x40,0x69,0x50,0x6d,0x6e, +0x6f,0x86,0x75,0x15,0x64,0x61,0x77,0x61,0x64,0x69,0xa3,0xe6,0x16,0x72,0x6f,0x73, +0x68,0x74,0x68,0x69,0xa3,0x89,0x1d,0x74,0x61,0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73, +0x63,0x72,0x69,0x70,0x74,0xa5,0x30,0x11,0x65,0x72,0x68,0x16,0x73,0x79,0x6d,0x62, +0x6f,0x6c,0x73,0xa3,0x71,0x12,0x6a,0x6b,0x69,0xa3,0xe5,5,0x74,0x35,0x74,0x34, +0x77,0x7a,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3,0xa2,0x14,0x61,0x6b,0x61,0x6e,0x61, +0x9e,1,0x65,0x4c,0x70,0x10,0x68,0x1f,0x6f,0x6e,0x65,0x74,0x69,0x63,0x65,0x78, +0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0x6b,0x11,0x78,0x74,0xa3,0x6b,0x10, +0x69,0xa5,0x46,0x69,0xa2,0x4e,0x6b,0xa2,0x51,0x6e,3,0x61,0x34,0x62,0x84,0x67, +0x8a,0x6e,0x12,0x61,0x64,0x61,0x4d,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0xcb, +0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xcb,0x11,0x78,0x74,2,0x61,0xa5, +0x13,0x62,0xa5,0x38,0x65,0x13,0x6e,0x64,0x65,0x64,1,0x61,0xa5,0x13,0x62,0xa5, +0x38,0x11,0x75,0x6e,0xa3,0x42,0x11,0x78,0x69,0x96,0x17,0x72,0x61,0x64,0x69,0x63, +0x61,0x6c,0x73,0x97,0x12,0x74,0x68,0x69,0xa3,0xc1,0x1c,0x74,0x6f,0x76,0x69,0x6b, +0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0xa5,0x45,0x67,0xa2,0xb5,0x68,0xa4,0x84, +0x69,3,0x64,0x4c,0x6d,0xa2,0x55,0x6e,0xa2,0x62,0x70,0x13,0x61,0x65,0x78,0x74, +0x2a,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0x2b,1,0x63,0x99,0x65,0x17,0x6f, +0x67,0x72,0x61,0x70,0x68,0x69,0x63,1,0x64,0x56,0x73,0x15,0x79,0x6d,0x62,0x6f, +0x6c,0x73,0xa4,0xb,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, +0x69,0x6f,0x6e,0xa5,0xb,0x13,0x65,0x73,0x63,0x72,0x1f,0x69,0x70,0x74,0x69,0x6f, +0x6e,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x73,0x99,0x1c,0x70,0x65,0x72, +0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0xba,1,0x64,0x62,0x73, +0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x70,0x61,1,0x68,0x32, +0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0xbd,0x13,0x6c,0x61,0x76,0x69,0xa3,0xbe, +0x11,0x69,0x63,1,0x6e,0x3e,0x73,0x1a,0x69,0x79,0x61,0x71,0x6e,0x75,0x6d,0x62, +0x65,0x72,0x73,0xa5,0x1e,0x19,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73, +0xa3,0xb2,4,0x65,0x74,0x6c,0xa2,0x82,0x6f,0xa2,0x9a,0x72,0xa2,0x9e,0x75,2, +0x6a,0x34,0x6e,0x3e,0x72,0x14,0x6d,0x75,0x6b,0x68,0x69,0x43,0x14,0x61,0x72,0x61, +0x74,0x69,0x45,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa5,0x1c,1, +0x6e,0xa2,0x46,0x6f,1,0x6d,0x6e,0x72,0x13,0x67,0x69,0x61,0x6e,0x5a,1,0x65, +0x40,0x73,0x11,0x75,0x70,0xa2,0x87,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, +0x87,0x11,0x78,0x74,0xa4,0x1b,0x14,0x65,0x6e,0x64,0x65,0x64,0xa5,0x1b,0x1a,0x65, +0x74,0x72,0x69,0x63,0x73,0x68,0x61,0x70,0x65,0x73,0x8c,0x12,0x65,0x78,0x74,0xa2, +0xe3,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0xe3,0x1e,0x65,0x72,0x61,0x6c,0x70,0x75, +0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x61,0x67,0x6f,0x6c,0x69, +0x74,0x69,0x63,0xa2,0x88,0x12,0x73,0x75,0x70,0xa4,0xa,0x16,0x70,0x6c,0x65,0x6d, +0x65,0x6e,0x74,0xa5,0xa,0x13,0x74,0x68,0x69,0x63,0xa3,0x59,1,0x61,0x5c,0x65, +0x11,0x65,0x6b,0x30,1,0x61,0x38,0x65,0x11,0x78,0x74,0x6e,0x14,0x65,0x6e,0x64, +0x65,0x64,0x6f,0x17,0x6e,0x64,0x63,0x6f,0x70,0x74,0x69,0x63,0x31,0x13,0x6e,0x74, +0x68,0x61,0xa3,0xe4,2,0x61,0xa2,0x48,0x65,0xa2,0xdf,0x69,1,0x67,0x30,0x72, +0x14,0x61,0x67,0x61,0x6e,0x61,0x9d,0x10,0x68,1,0x70,0x3a,0x73,0x18,0x75,0x72, +0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4b,1,0x72,0x3c,0x75,0x19,0x73,0x75, +0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c,0x11,0x69,0x76,0x1f,0x61,0x74, +0x65,0x75,0x73,0x65,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c, +2,0x6c,0x32,0x6e,0x9a,0x74,0x12,0x72,0x61,0x6e,0xa5,2,0x10,0x66,2,0x61, +0x58,0x6d,0x70,0x77,0x14,0x69,0x64,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66,0x75,0x6c, +0x6c,0x77,0x69,0x64,0x74,0x68,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x1a,0x6e,0x64, +0x66,0x75,0x6c,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x13,0x61,0x72,0x6b,0x73, +0xa3,0x52,2,0x67,0x34,0x69,0xa2,0x45,0x75,0x12,0x6e,0x6f,0x6f,0xa3,0x63,0x11, +0x75,0x6c,0xa2,0x4a,2,0x63,0x3c,0x6a,0x5e,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62, +0x6c,0x65,0x73,0xa3,0x4a,0x1f,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69,0x6c,0x69, +0x74,0x79,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x12,0x61,0x6d,0x6f,0x5c,0x17,0x65,0x78, +0x74,0x65,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,0x19,0x66,0x69, +0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa5,0x1d,0x13,0x62,0x72,0x65,0x77,0x37, +0x61,0xa4,0xc,0x62,0xa6,0x59,0x63,0xa8,0x2e,0x64,0xac,0xe9,0x65,5,0x6d,0xa9, +0x6d,0x94,0x6e,0xa2,0x41,0x74,0x15,0x68,0x69,0x6f,0x70,0x69,0x63,0x5e,1,0x65, +0x40,0x73,0x11,0x75,0x70,0xa2,0x86,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, +0x86,0x11,0x78,0x74,0xa2,0x85,2,0x61,0xa3,0xc8,0x62,0xa5,0x37,0x65,0x13,0x6e, +0x64,0x65,0x64,0xa2,0x85,1,0x61,0xa3,0xc8,0x62,0xa5,0x37,0x16,0x6f,0x74,0x69, +0x63,0x6f,0x6e,0x73,0xa3,0xce,0x15,0x63,0x6c,0x6f,0x73,0x65,0x64,2,0x61,0x5a, +0x63,0x9e,0x69,0x1c,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x75, +0x70,0xa2,0xc4,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc4,0x16,0x6c,0x70, +0x68,0x61,0x6e,0x75,0x6d,0x86,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0xc3,0x13, +0x72,0x69,0x63,0x73,0x86,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, +0xc3,0x11,0x6a,0x6b,0xa2,0x44,0x1f,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x61,0x6e, +0x64,0x6d,0x6f,0x6e,0x74,0x68,0x73,0xa3,0x44,0x61,0x4a,0x67,0x76,0x6c,1,0x62, +0x30,0x79,0x13,0x6d,0x61,0x69,0x63,0xa5,0x25,0x13,0x61,0x73,0x61,0x6e,0xa3,0xe2, +0x13,0x72,0x6c,0x79,0x64,0x1f,0x79,0x6e,0x61,0x73,0x74,0x69,0x63,0x63,0x75,0x6e, +0x65,0x69,0x66,0x6f,0x72,0x6d,0xa5,1,0x1f,0x79,0x70,0x74,0x69,0x61,0x6e,0x68, +0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,1,0x66,0x26,0x73,0xa3,0xc2,0x1c, +0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa5,0x24,7, +0x6e,0xc0,0xf2,0x6e,0x3e,0x72,0xa2,0x5d,0x73,0xa2,0xe5,0x76,0x14,0x65,0x73,0x74, +0x61,0x6e,0xa3,0xbc,1,0x61,0x92,0x63,0x13,0x69,0x65,0x6e,0x74,1,0x67,0x34, +0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xa5,0x13,0x72,0x65,0x65,0x6b,1, +0x6d,0x34,0x6e,0x15,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x7f,0x13,0x75,0x73,0x69, +0x63,0xa2,0x7e,0x19,0x61,0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x7e, +0x10,0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79, +0x70,0x68,0x73,0xa3,0xfe,2,0x61,0x32,0x6d,0xa2,0x7e,0x72,0x12,0x6f,0x77,0x73, +0x7d,0x12,0x62,0x69,0x63,0x38,3,0x65,0x4a,0x6d,0x80,0x70,0xa2,0x50,0x73,0x11, +0x75,0x70,0xa2,0x80,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x80,0x11,0x78, +0x74,3,0x61,0xa3,0xd2,0x62,0xa5,0x35,0x63,0xa5,0x41,0x65,0x13,0x6e,0x64,0x65, +0x64,2,0x61,0xa3,0xd2,0x62,0xa5,0x35,0x63,0xa5,0x41,0x12,0x61,0x74,0x68,0xa2, +0xd3,0x18,0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x61,0x1f,0x6c,0x70,0x68,0x61, +0x62,0x65,0x74,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd3,1,0x66, +0x42,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72, +0x6d,0x73,1,0x61,0xa3,0x51,0x62,0xa3,0x55,0x14,0x65,0x6e,0x69,0x61,0x6e,0x35, +0x12,0x63,0x69,0x69,0x23,0x64,0x9e,0x65,0xa2,0x42,0x68,0xa2,0x4d,0x6c,1,0x63, +0x62,0x70,0x17,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x70,1,0x66,0xa3,0x50,0x72, +0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72,0x6d,0x73, +0xa3,0x50,0x16,0x68,0x65,0x6d,0x69,0x63,0x61,0x6c,0xa2,0xd0,0x16,0x73,0x79,0x6d, +0x62,0x6f,0x6c,0x73,0xa3,0xd0,0x12,0x6c,0x61,0x6d,0xa5,7,0x1a,0x67,0x65,0x61, +0x6e,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x77,0x11,0x6f,0x6d,0xa3,0xfd,7, +0x6f,0x71,0x6f,0x64,0x72,0xa2,0x41,0x75,0xa2,0x58,0x79,0x1b,0x7a,0x61,0x6e,0x74, +0x69,0x6e,0x65,0x6d,0x75,0x73,0x69,0x63,0xa2,0x5b,0x18,0x61,0x6c,0x73,0x79,0x6d, +0x62,0x6f,0x6c,0x73,0xa3,0x5b,1,0x70,0x34,0x78,0x16,0x64,0x72,0x61,0x77,0x69, +0x6e,0x67,0x89,0x14,0x6f,0x6d,0x6f,0x66,0x6f,0xa0,0x12,0x65,0x78,0x74,0xa2,0x43, +0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0x43,0x10,0x61,1,0x68,0x40,0x69,0x12,0x6c, +0x6c,0x65,0x92,0x17,0x70,0x61,0x74,0x74,0x65,0x72,0x6e,0x73,0x93,0x11,0x6d,0x69, +0xa3,0xc9,1,0x67,0x2c,0x68,0x11,0x69,0x64,0xa3,0x64,0x14,0x69,0x6e,0x65,0x73, +0x65,0xa3,0x81,0x61,0x48,0x65,0xa2,0x4e,0x68,0xa2,0x52,0x6c,0x1a,0x6f,0x63,0x6b, +0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x8b,3,0x6c,0x34,0x6d,0x40,0x73,0x66, +0x74,0x11,0x61,0x6b,0xa3,0xc7,0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x93,0x11,0x75, +0x6d,0xa2,0xb1,0x12,0x73,0x75,0x70,0xa2,0xca,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e, +0x74,0xa3,0xca,1,0x69,0x30,0x73,0x13,0x61,0x76,0x61,0x68,0xa3,0xdd,0x15,0x63, +0x6c,0x61,0x74,0x69,0x6e,0x23,0x14,0x6e,0x67,0x61,0x6c,0x69,0x41,0x16,0x61,0x69, +0x6b,0x73,0x75,0x6b,0x69,0xa5,8,5,0x6f,0xc1,0x60,0x6f,0xa2,0x69,0x75,0xa4, +0x24,0x79,1,0x70,0xa2,0x44,0x72,0x14,0x69,0x6c,0x6c,0x69,0x63,0x32,1,0x65, +0x4c,0x73,0x11,0x75,0x70,0xa2,0x61,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa2, +0x61,0x12,0x61,0x72,0x79,0xa3,0x61,0x11,0x78,0x74,4,0x61,0xa3,0x9e,0x62,0xa3, +0xa0,0x63,0xa5,9,0x64,0xa5,0x43,0x65,0x13,0x6e,0x64,0x65,0x64,3,0x61,0xa3, +0x9e,0x62,0xa3,0xa0,0x63,0xa5,9,0x64,0xa5,0x43,0x10,0x72,1,0x69,0x34,0x6f, +0x15,0x6d,0x69,0x6e,0x6f,0x61,0x6e,0xa5,0x36,0x1a,0x6f,0x74,0x73,0x79,0x6c,0x6c, +0x61,0x62,0x61,0x72,0x79,0xa3,0x7b,3,0x6d,0x5a,0x6e,0xa2,0x95,0x70,0xa2,0xa0, +0x75,0x17,0x6e,0x74,0x69,0x6e,0x67,0x72,0x6f,0x64,0xa2,0x9a,0x17,0x6e,0x75,0x6d, +0x65,0x72,0x61,0x6c,0x73,0xa3,0x9a,2,0x62,0x3a,0x6d,0xa2,0x5f,0x70,0x15,0x61, +0x74,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x14,0x69,0x6e,0x69,0x6e,0x67,2,0x64,0x46, +0x68,0x9e,0x6d,0x1d,0x61,0x72,0x6b,0x73,0x66,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f, +0x6c,0x73,0x77,0x1e,0x69,0x61,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x6d,0x61, +0x72,0x6b,0x73,0x2e,2,0x65,0x40,0x66,0xa6,0x52,0x73,0x18,0x75,0x70,0x70,0x6c, +0x65,0x6d,0x65,0x6e,0x74,0xa3,0x83,0x16,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3, +0xe0,0x17,0x61,0x6c,0x66,0x6d,0x61,0x72,0x6b,0x73,0xa3,0x52,0x11,0x6f,0x6e,0x1f, +0x69,0x6e,0x64,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73, +0xa3,0xb2,0x1b,0x74,0x72,0x6f,0x6c,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x73,0x83, +0x12,0x74,0x69,0x63,0xa2,0x84,0x1b,0x65,0x70,0x61,0x63,0x74,0x6e,0x75,0x6d,0x62, +0x65,0x72,0x73,0xa3,0xdf,1,0x6e,0x3e,0x72,0x1b,0x72,0x65,0x6e,0x63,0x79,0x73, +0x79,0x6d,0x62,0x6f,0x6c,0x73,0x75,0x15,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa2,0x98, +0x16,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa2,0x99,0x1d,0x61,0x6e,0x64,0x70,0x75, +0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x99,0x61,0xa2,0xea,0x68,0xa4, +0x14,0x6a,0x10,0x6b,0xa2,0x47,4,0x63,0x92,0x65,0xa2,0x83,0x72,0xa2,0xa1,0x73, +0xa2,0xb3,0x75,0x1f,0x6e,0x69,0x66,0x69,0x65,0x64,0x69,0x64,0x65,0x6f,0x67,0x72, +0x61,0x70,0x68,0x73,0xa2,0x47,0x18,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e, +8,0x65,0x71,0x65,0xa5,0,0x66,0xa5,0x12,0x67,0xa5,0x2e,0x68,0xa5,0x42,0x69, +0xa5,0x48,0x14,0x6f,0x6d,0x70,0x61,0x74,0xa2,0x45,1,0x66,0x96,0x69,1,0x62, +0x44,0x64,0x17,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x12,0x73,0x75, +0x70,0xa3,0x5f,0x14,0x69,0x6c,0x69,0x74,0x79,0xa2,0x45,1,0x66,0x54,0x69,0x18, +0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x19,0x73,0x75,0x70,0x70, +0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x5f,0x13,0x6f,0x72,0x6d,0x73,0xa3,0x53,0x11, +0x78,0x74,8,0x65,0xf,0x65,0xa5,0,0x66,0xa5,0x12,0x67,0xa5,0x2e,0x68,0xa5, +0x42,0x69,0xa5,0x48,0x61,0xa3,0x46,0x62,0xa3,0x5e,0x63,0xa3,0xc5,0x64,0xa3,0xd1, +0x19,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x73,0x75,0x70,0x94,0x16,0x70,0x6c,0x65, +0x6d,0x65,0x6e,0x74,0x95,1,0x74,0x50,0x79,0x14,0x6d,0x62,0x6f,0x6c,0x73,0x9a, +0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x9b, +0x14,0x72,0x6f,0x6b,0x65,0x73,0xa3,0x82,2,0x6e,0x48,0x72,0x64,0x75,0x1d,0x63, +0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0xde,0x1d, +0x61,0x64,0x69,0x61,0x6e,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x63,0x12, +0x69,0x61,0x6e,0xa3,0xa8,2,0x61,0x3a,0x65,0x4c,0x6f,0x16,0x72,0x61,0x73,0x6d, +0x69,0x61,0x6e,0xa5,0x2d,1,0x6b,0x26,0x6d,0xa3,0xa4,0x11,0x6d,0x61,0xa3,0xd4, +1,0x72,0x38,0x73,0x17,0x73,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa5,0x19,0x13, +0x6f,0x6b,0x65,0x65,0x60,0x12,0x73,0x75,0x70,0xa2,0xff,0x16,0x70,0x6c,0x65,0x6d, +0x65,0x6e,0x74,0xa3,0xff,3,0x65,0x3e,0x69,0x8e,0x6f,0xa2,0x71,0x75,0x15,0x70, +0x6c,0x6f,0x79,0x61,0x6e,0xa3,0xe1,1,0x73,0x60,0x76,0x16,0x61,0x6e,0x61,0x67, +0x61,0x72,0x69,0x3e,0x12,0x65,0x78,0x74,0xa2,0xb3,1,0x61,0xa5,0x44,0x65,0x13, +0x6e,0x64,0x65,0x64,0xa2,0xb3,0x10,0x61,0xa5,0x44,0x13,0x65,0x72,0x65,0x74,0xa3, +0x5a,2,0x61,0x3a,0x6e,0x82,0x76,0x16,0x65,0x73,0x61,0x6b,0x75,0x72,0x75,0xa5, +0x2f,0x18,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x73,0x2e,2,0x65,0x30,0x66, +0x36,0x73,0x11,0x75,0x70,0xa3,0x83,0x11,0x78,0x74,0xa3,0xe0,0x18,0x6f,0x72,0x73, +0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,0x14,0x67,0x62,0x61,0x74,0x73,0x91,1,0x67, +0x3e,0x6d,0x12,0x69,0x6e,0x6f,0xa2,0xab,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xab, +0x11,0x72,0x61,0xa5,0x1a,8,0x6d,0x5f,0x6d,0x3a,0x6e,0x48,0x73,0x7a,0x76,0xa2, +0x4b,0x77,0x12,0x69,0x64,0x65,0x43,0x11,0x65,0x64,0x32,0x12,0x69,0x61,0x6c,0x33, +2,0x61,0x40,0x62,0x37,0x6f,1,0x62,0x28,0x6e,0x10,0x65,0x21,0x13,0x72,0x65, +0x61,0x6b,0x37,0x10,0x72,0x34,0x12,0x72,0x6f,0x77,0x35,2,0x6d,0x38,0x71,0x46, +0x75,1,0x62,0x3d,0x70,0x3e,0x11,0x65,0x72,0x3f,1,0x61,0x24,0x6c,0x39,0x11, +0x6c,0x6c,0x39,1,0x72,0x3b,0x75,0x12,0x61,0x72,0x65,0x3b,0x12,0x65,0x72,0x74, +0x40,0x13,0x69,0x63,0x61,0x6c,0x41,0x63,0x58,0x65,0x92,0x66,0x96,0x69,1,0x6e, +0x36,0x73,0x10,0x6f,0x30,0x14,0x6c,0x61,0x74,0x65,0x64,0x31,0x11,0x69,0x74,0x2e, +0x12,0x69,0x61,0x6c,0x2f,2,0x61,0x36,0x69,0x48,0x6f,0x10,0x6d,0x24,0x12,0x70, +0x61,0x74,0x25,0x10,0x6e,0x22,0x15,0x6f,0x6e,0x69,0x63,0x61,0x6c,0x23,0x13,0x72, +0x63,0x6c,0x65,0x27,0x11,0x6e,0x63,0x27,2,0x69,0x3a,0x6f,0x44,0x72,0x10,0x61, +0x2c,0x14,0x63,0x74,0x69,0x6f,0x6e,0x2d,0x10,0x6e,0x28,0x11,0x61,0x6c,0x29,0x11, +0x6e,0x74,0x2b,4,0x61,0x3a,0x66,0x4c,0x68,0x5e,0x6e,0x70,0x77,0x2a,0x12,0x69, +0x64,0x65,0x2b,0x22,0x17,0x6d,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x26,0x17, +0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x27,0x24,0x17,0x61,0x6c,0x66,0x77,0x69, +0x64,0x74,0x68,0x25,0x20,1,0x61,0x30,0x65,0x14,0x75,0x74,0x72,0x61,0x6c,0x21, +0x28,0x13,0x72,0x72,0x6f,0x77,0x29,0xd,0x6e,0xc0,0xfb,0x73,0x6d,0x73,0x3a,0x74, +0x98,0x75,0xa2,0x49,0x7a,2,0x6c,0x3b,0x70,0x3d,0x73,0x39,5,0x6f,0x28,0x6f, +0x57,0x70,0x34,0x75,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x45,0x11,0x61,0x63, +1,0x65,0x32,0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x31,0x18,0x73,0x65,0x70, +0x61,0x72,0x61,0x74,0x6f,0x72,0x39,0x63,0x53,0x6b,0x55,0x6d,0x51,0x1d,0x69,0x74, +0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x27,1,0x6e,0x40, +0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x23, +0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x21,0x6e,0x8a,0x6f,0xa2,0x47,0x70, +8,0x66,0x14,0x66,0x5b,0x69,0x59,0x6f,0x4f,0x72,0x24,0x73,0x49,0x17,0x69,0x76, +0x61,0x74,0x65,0x75,0x73,0x65,0x43,0x61,0x2c,0x63,0x4d,0x64,0x47,0x65,0x4b,0x1f, +0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, +0x3d,2,0x64,0x33,0x6c,0x35,0x6f,0x36,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e, +0x67,0x6d,0x61,0x72,0x6b,0x2d,1,0x70,0x7c,0x74,0x12,0x68,0x65,0x72,3,0x6c, +0x38,0x6e,0x42,0x70,0x4c,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x57,0x14,0x65,0x74, +0x74,0x65,0x72,0x2b,0x14,0x75,0x6d,0x62,0x65,0x72,0x37,0x19,0x75,0x6e,0x63,0x74, +0x75,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x49,0x66,0x9e,0x66,0x88,0x69,0xa2,0x4b,0x6c,0xa2,0x5c, +0x6d,4,0x61,0x60,0x63,0x31,0x65,0x2f,0x6e,0x2d,0x6f,0x15,0x64,0x69,0x66,0x69, +0x65,0x72,1,0x6c,0x30,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x55,0x14,0x65,0x74, +0x74,0x65,0x72,0x29,0x17,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x51,1,0x69, +0x2e,0x6f,0x13,0x72,0x6d,0x61,0x74,0x41,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x5b,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c, +0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x59,6,0x6d,0x18,0x6d, +0x29,0x6f,0x28,0x74,0x27,0x75,0x23,0x2a,0x1c,0x77,0x65,0x72,0x63,0x61,0x73,0x65, +0x6c,0x65,0x74,0x74,0x65,0x72,0x25,0x65,0x28,0x69,0x3c,0x6c,0x25,0x19,0x74,0x74, +0x65,0x72,0x6e,0x75,0x6d,0x62,0x65,0x72,0x35,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61, +0x72,0x61,0x74,0x6f,0x72,0x3b,0x63,0x44,0x64,0xa2,0x60,0x65,0x1b,0x6e,0x63,0x6c, +0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x2f,6,0x6e,0x39,0x6e,0x46,0x6f, +0x4e,0x73,0x45,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f, +0x6c,0x53,0x20,0x12,0x74,0x72,0x6c,0x3f,0x42,0x10,0x6e,1,0x6e,0x2c,0x74,0x12, +0x72,0x6f,0x6c,0x3f,0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x4d,0x63,0x3f,0x66,0x41,0x6c,0x1d,0x6f,0x73,0x65,0x70, +0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x4b,2,0x61,0x30,0x65,0x4a, +0x69,0x12,0x67,0x69,0x74,0x33,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, +0x74,0x69,0x6f,0x6e,0x47,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62,0x65, +0x72,0x33,0,0x13,0x6e,0xc1,0xf,0x74,0x76,0x74,0x4c,0x76,0x9a,0x77,0xa2,0x48, +0x79,0xa2,0x49,0x7a,1,0x61,0x2c,0x68,0x12,0x61,0x69,0x6e,0x8b,0x11,0x69,0x6e, +0x85,2,0x61,0x36,0x65,0x3c,0x68,0x14,0x69,0x6e,0x79,0x65,0x68,0xa3,0x66,1, +0x68,0x71,0x77,0x73,1,0x68,0x28,0x74,0x10,0x68,0x77,0x16,0x6d,0x61,0x72,0x62, +0x75,0x74,0x61,0x74,0x13,0x67,0x6f,0x61,0x6c,0x3d,0x1a,0x65,0x72,0x74,0x69,0x63, +0x61,0x6c,0x74,0x61,0x69,0x6c,0xa3,0x67,0x11,0x61,0x77,0x79,1,0x65,0x32,0x75, +0x11,0x64,0x68,0x80,0x11,0x68,0x65,0x83,0x10,0x68,0x7a,1,0x62,0x34,0x77,0x16, +0x69,0x74,0x68,0x74,0x61,0x69,0x6c,0x7f,0x14,0x61,0x72,0x72,0x65,0x65,0x7d,0x6e, +0xa2,0x4c,0x70,0xa2,0x69,0x71,0xa2,0x69,0x72,0xa2,0x6f,0x73,5,0x74,0x22,0x74, +0x38,0x77,0x4c,0x79,0x16,0x72,0x69,0x61,0x63,0x77,0x61,0x77,0x6f,0x18,0x72,0x61, +0x69,0x67,0x68,0x74,0x77,0x61,0x77,0xa3,0x55,0x15,0x61,0x73,0x68,0x6b,0x61,0x66, +0x6d,0x61,0x2e,0x65,0x38,0x68,0x11,0x69,0x6e,0x6b,0x10,0x64,0x62,0x11,0x68,0x65, +0x65,1,0x65,0x2e,0x6d,0x13,0x6b,0x61,0x74,0x68,0x69,0x10,0x6e,0x67,2,0x6f, +0x2c,0x75,0x50,0x79,0x10,0x61,0x91,1,0x6a,0x28,0x6f,0x10,0x6e,0x55,0x1a,0x6f, +0x69,0x6e,0x69,0x6e,0x67,0x67,0x72,0x6f,0x75,0x70,0x21,0x10,0x6e,0x57,0x10,0x65, +0x59,0x10,0x61,1,0x66,0x5b,0x70,0x10,0x68,0x5d,1,0x65,0x38,0x6f,0x18,0x68, +0x69,0x6e,0x67,0x79,0x61,0x79,0x65,0x68,0x93,1,0x68,0x5f,0x76,0x16,0x65,0x72, +0x73,0x65,0x64,0x70,0x65,0x61,0x67,0xc1,0xc7,0x67,0xa4,0x52,0x68,0xa4,0x59,0x6b, +0xa4,0x99,0x6c,0xa4,0xb2,0x6d,2,0x61,0x2e,0x65,0xa4,0x3e,0x69,0x10,0x6d,0x53, +1,0x6c,0xa2,0xe7,0x6e,0x16,0x69,0x63,0x68,0x61,0x65,0x61,0x6e,0,0x12,0x6e, +0x76,0x73,0x51,0x73,0x3e,0x74,0x5c,0x77,0xa0,0x79,0xa2,0x42,0x7a,0x13,0x61,0x79, +0x69,0x6e,0xa3,0x54,0x10,0x61,1,0x64,0x2e,0x6d,0x12,0x65,0x6b,0x68,0xa3,0x4c, +0x11,0x68,0x65,0xa3,0x4b,3,0x61,0x38,0x65,0x3c,0x68,0x4a,0x77,0x13,0x65,0x6e, +0x74,0x79,0xa3,0x51,0x10,0x77,0xa3,0x4d,1,0x6e,0xa3,0x4e,0x74,0x10,0x68,0xa3, +0x4f,0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x50,0x11,0x61,0x77,0xa3,0x52,0x12,0x6f, +0x64,0x68,0xa3,0x53,0x6e,0x3a,0x6f,0x40,0x70,0x46,0x71,0x4a,0x72,0x12,0x65,0x73, +0x68,0xa3,0x4a,0x11,0x75,0x6e,0xa3,0x46,0x11,0x6e,0x65,0xa3,0x47,0x10,0x65,0xa3, +0x48,0x12,0x6f,0x70,0x68,0xa3,0x49,0x67,0x33,0x67,0x38,0x68,0x40,0x6b,0x5e,0x6c, +0x66,0x6d,0x11,0x65,0x6d,0xa3,0x45,0x13,0x69,0x6d,0x65,0x6c,0xa1,1,0x65,0x32, +0x75,0x14,0x6e,0x64,0x72,0x65,0x64,0xa3,0x42,0x11,0x74,0x68,0xa3,0x41,0x12,0x61, +0x70,0x68,0xa3,0x43,0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x44,0x61,0x34,0x62,0x4a, +0x64,0x50,0x66,0x12,0x69,0x76,0x65,0x9f,1,0x6c,0x2a,0x79,0x11,0x69,0x6e,0x97, +0x12,0x65,0x70,0x68,0x95,0x12,0x65,0x74,0x68,0x99,1,0x61,0x30,0x68,0x14,0x61, +0x6d,0x65,0x64,0x68,0x9d,0x13,0x6c,0x65,0x74,0x68,0x9b,0x15,0x61,0x79,0x61,0x6c, +0x61,0x6d,6,0x6e,0x2c,0x6e,0x34,0x72,0x5e,0x73,0x62,0x74,0x11,0x74,0x61,0xa3, +0x63,2,0x67,0x2e,0x6e,0x32,0x79,0x10,0x61,0xa3,0x60,0x10,0x61,0xa3,0x5d,1, +0x61,0xa3,0x5e,0x6e,0x10,0x61,0xa3,0x5f,0x10,0x61,0xa3,0x61,0x11,0x73,0x61,0xa3, +0x62,0x62,0x3c,0x6a,0x42,0x6c,0x10,0x6c,1,0x61,0xa3,0x5b,0x6c,0x10,0x61,0xa3, +0x5c,0x11,0x68,0x61,0xa3,0x59,0x10,0x61,0xa3,0x5a,0x11,0x65,0x6d,0x51,0x10,0x61, +1,0x66,0x37,0x6d,0x11,0x61,0x6c,0x39,1,0x61,0x40,0x65,0x3e,1,0x68,0x28, +0x74,0x10,0x68,0x45,0x40,0x13,0x67,0x6f,0x61,0x6c,0x43,2,0x68,0x3b,0x6d,0x5c, +0x6e,0x1a,0x69,0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,1,0x6b,0x2a, +0x70,0x10,0x61,0xa3,0x65,0x15,0x69,0x6e,0x6e,0x61,0x79,0x61,0xa3,0x64,0x1a,0x7a, +0x61,0x6f,0x6e,0x68,0x65,0x68,0x67,0x6f,0x61,0x6c,0x3d,2,0x61,0x3a,0x68,0x44, +0x6e,0x17,0x6f,0x74,0x74,0x65,0x64,0x68,0x65,0x68,0x4b,1,0x66,0x47,0x70,0x10, +0x68,0x49,0x12,0x61,0x70,0x68,0x89,0x11,0x61,0x6d,0x4c,0x12,0x61,0x64,0x68,0x4f, +0x61,0x6e,0x62,0xa2,0x54,0x64,0xa2,0x70,0x65,0x31,0x66,2,0x61,0x3e,0x65,0x4a, +0x69,0x19,0x6e,0x61,0x6c,0x73,0x65,0x6d,0x6b,0x61,0x74,0x68,0x35,0x15,0x72,0x73, +0x69,0x79,0x65,0x68,0x8f,0x86,0x10,0x68,0x33,2,0x66,0x3c,0x69,0x70,0x6c,1, +0x61,0x28,0x65,0x10,0x66,0x27,0x11,0x70,0x68,0x25,0x14,0x72,0x69,0x63,0x61,0x6e, +2,0x66,0x30,0x6e,0x36,0x71,0x11,0x61,0x66,0xa3,0x58,0x11,0x65,0x68,0xa3,0x56, +0x12,0x6f,0x6f,0x6e,0xa3,0x57,0x10,0x6e,0x23,1,0x65,0x4a,0x75,0x10,0x72,0x1f, +0x75,0x73,0x68,0x61,0x73,0x6b,0x69,0x79,0x65,0x68,0x62,0x61,0x72,0x72,0x65,0x65, +0x8d,1,0x68,0x29,0x74,0x10,0x68,0x2b,0x11,0x61,0x6c,0x2c,0x16,0x61,0x74,0x68, +0x72,0x69,0x73,0x68,0x2f,7,0x6e,0x2e,0x6e,0x2c,0x72,0x3e,0x74,0x56,0x75,0x21, +0x18,0x6f,0x6e,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x21,0x28,0x1a,0x69,0x67,0x68, +0x74,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x29,0x2a,0x19,0x72,0x61,0x6e,0x73,0x70, +0x61,0x72,0x65,0x6e,0x74,0x2b,0x63,0x23,0x64,0x40,0x6a,0x56,0x6c,0x26,0x19,0x65, +0x66,0x74,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x27,0x24,0x19,0x75,0x61,0x6c,0x6a, +0x6f,0x69,0x6e,0x69,0x6e,0x67,0x25,0x19,0x6f,0x69,0x6e,0x63,0x61,0x75,0x73,0x69, +0x6e,0x67,0x23,0,0x14,0x6e,0xc0,0xe5,0x73,0x5e,0x77,0x23,0x77,0x40,0x78,0x58, +0x7a,0x10,0x77,0x58,1,0x6a,0x75,0x73,0x13,0x70,0x61,0x63,0x65,0x59,1,0x6a, +0x5d,0x6f,0x17,0x72,0x64,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x5d,0x10,0x78,0x21,0x73, +0x4a,0x75,0x7a,0x76,1,0x66,0x7d,0x69,0x7e,0x13,0x72,0x61,0x6d,0x61,0x7e,0x14, +0x66,0x69,0x6e,0x61,0x6c,0x7d,4,0x61,0x51,0x67,0x53,0x70,0x28,0x75,0x30,0x79, +0x57,0x54,0x12,0x61,0x63,0x65,0x55,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x53, +0x15,0x6e,0x6b,0x6e,0x6f,0x77,0x6e,0x21,0x6e,0x60,0x6f,0xa2,0x41,0x70,0xa2,0x50, +0x71,0xa2,0x6e,0x72,1,0x65,0x24,0x69,0x6f,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c, +0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x6f,4,0x65,0x3e,0x6c,0x5b,0x6f, +0x46,0x73,0x45,0x75,0x46,0x14,0x6d,0x65,0x72,0x69,0x63,0x47,0x15,0x78,0x74,0x6c, +0x69,0x6e,0x65,0x5b,0x17,0x6e,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x45,0x10,0x70, +0x48,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49, +1,0x6f,0x3e,0x72,0x4c,0x1a,0x65,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69, +0x63,0x4d,0x4a,0x1b,0x73,0x74,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63, +0x4b,0x10,0x75,0x4e,0x16,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x68,0x7b,0x68, +0x50,0x69,0x86,0x6a,0xa2,0x61,0x6c,0xa2,0x65,0x6d,0x1c,0x61,0x6e,0x64,0x61,0x74, +0x6f,0x72,0x79,0x62,0x72,0x65,0x61,0x6b,0x2d,4,0x32,0x5f,0x33,0x61,0x65,0x34, +0x6c,0x6d,0x79,0x3a,0x13,0x70,0x68,0x65,0x6e,0x3b,0x19,0x62,0x72,0x65,0x77,0x6c, +0x65,0x74,0x74,0x65,0x72,0x6d,2,0x64,0x28,0x6e,0x3c,0x73,0x41,0x3c,0x18,0x65, +0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x3d,0x3e,1,0x66,0x3e,0x73,0x11,0x65, +0x70,1,0x61,0x22,0x65,0x14,0x72,0x61,0x62,0x6c,0x65,0x3f,0x18,0x69,0x78,0x6e, +0x75,0x6d,0x65,0x72,0x69,0x63,0x41,2,0x6c,0x63,0x74,0x65,0x76,0x67,1,0x66, +0x43,0x69,0x15,0x6e,0x65,0x66,0x65,0x65,0x64,0x43,0x61,0x42,0x62,0xa2,0x49,0x63, +0xa2,0x76,0x65,0xa2,0xfc,0x67,0x10,0x6c,0x38,0x11,0x75,0x65,0x39,5,0x6d,0xf, +0x6d,0x28,0x70,0x79,0x73,0x7b,0x16,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x69, +0x23,0x6b,0x38,0x6c,0x24,0x17,0x70,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x25,0x76, +0x13,0x73,0x61,0x72,0x61,0x76,1,0x70,0x2e,0x73,0x13,0x74,0x61,0x72,0x74,0x7b, +0x15,0x72,0x65,0x62,0x61,0x73,0x65,0x79,4,0x32,0x27,0x61,0x29,0x62,0x2b,0x6b, +0x2d,0x72,0x12,0x65,0x61,0x6b,2,0x61,0x36,0x62,0x3e,0x73,0x15,0x79,0x6d,0x62, +0x6f,0x6c,0x73,0x57,0x13,0x66,0x74,0x65,0x72,0x29,1,0x65,0x2a,0x6f,0x11,0x74, +0x68,0x27,0x13,0x66,0x6f,0x72,0x65,0x2b,7,0x6d,0x51,0x6d,0x33,0x6f,0x28,0x70, +0x69,0x72,0x35,1,0x6d,0x76,0x6e,1,0x64,0x3c,0x74,0x1a,0x69,0x6e,0x67,0x65, +0x6e,0x74,0x62,0x72,0x65,0x61,0x6b,0x2f,0x15,0x69,0x74,0x69,0x6f,0x6e,0x61,0x1f, +0x6c,0x6a,0x61,0x70,0x61,0x6e,0x65,0x73,0x65,0x73,0x74,0x61,0x72,0x74,0x65,0x72, +0x6b,1,0x62,0x3a,0x70,0x19,0x6c,0x65,0x78,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74, +0x51,0x18,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x33,0x61,0x6a,0x62,0x2f, +0x6a,0x6b,0x6c,0x30,0x13,0x6f,0x73,0x65,0x70,1,0x61,0x38,0x75,0x18,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x31,0x18,0x72,0x65,0x6e,0x74,0x68,0x65,0x73, +0x69,0x73,0x69,0x1b,0x72,0x72,0x69,0x61,0x67,0x65,0x72,0x65,0x74,0x75,0x72,0x6e, +0x35,2,0x62,0x3e,0x6d,0x46,0x78,0x36,0x18,0x63,0x6c,0x61,0x6d,0x61,0x74,0x69, +0x6f,0x6e,0x37,0x70,0x12,0x61,0x73,0x65,0x71,0x72,0x16,0x6f,0x64,0x69,0x66,0x69, +0x65,0x72,0x73,1,0x64,0x42,0x6e,1,0x6f,0x32,0x75,0x26,0x14,0x6d,0x65,0x72, +0x69,0x63,0x27,0x11,0x6e,0x65,0x21,1,0x65,0x2e,0x69,0x24,0x12,0x67,0x69,0x74, +0x25,0x22,0x14,0x63,0x69,0x6d,0x61,0x6c,0x23,0,0x18,0x6e,0xc4,0x6f,0x74,0xc1, +0x91,0x77,0x96,0x77,0xa2,0x4c,0x78,0xa2,0x70,0x79,0xa2,0x7a,0x7a,6,0x73,0x1e, +0x73,0x34,0x78,0x42,0x79,0x48,0x7a,0x11,0x7a,0x7a,0xa3,0x67,0x10,0x79,1,0x65, +0xa3,0xae,0x6d,0xa3,0x81,0x11,0x78,0x78,0xa3,0x66,0x11,0x79,0x79,0x21,0x61,0x30, +0x69,0x58,0x6d,0x11,0x74,0x68,0xa3,0x80,0x10,0x6e,1,0x61,0x26,0x62,0xa3,0xb1, +0x1a,0x62,0x61,0x7a,0x61,0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa3,0xb1,0x11,0x6e, +0x68,0x23,2,0x61,0x30,0x63,0x5a,0x6f,0x11,0x6c,0x65,0xa3,0x9b,1,0x6e,0x3c, +0x72,0x10,0x61,0xa2,0x92,0x15,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0x92,0x12,0x63, +0x68,0x6f,0xa3,0xbc,0x11,0x68,0x6f,0xa3,0xbc,1,0x70,0x2c,0x73,0x11,0x75,0x78, +0xa3,0x65,0x11,0x65,0x6f,0x9b,1,0x65,0x2c,0x69,0x72,0x11,0x69,0x69,0x73,0x11, +0x7a,0x69,0xa2,0xc0,0x11,0x64,0x69,0xa3,0xc0,0x74,0x66,0x75,0xa2,0xde,0x76,1, +0x61,0x48,0x69,1,0x73,0x38,0x74,0x10,0x68,0xa2,0xc5,0x13,0x6b,0x75,0x71,0x69, +0xa3,0xc5,0x10,0x70,0xa3,0x64,0x10,0x69,0xa2,0x63,0x10,0x69,0xa3,0x63,7,0x68, +0x3e,0x68,0x34,0x69,0x48,0x6e,0x86,0x6f,0x11,0x74,0x6f,0xa3,0xc4,0x10,0x61,1, +0x61,0x24,0x69,0x6d,0x6a,0x11,0x6e,0x61,0x6b,2,0x62,0x3a,0x66,0x4a,0x72,0x10, +0x68,0xa2,0x9e,0x12,0x75,0x74,0x61,0xa3,0x9e,1,0x65,0x24,0x74,0x6f,0x12,0x74, +0x61,0x6e,0x6f,0x14,0x69,0x6e,0x61,0x67,0x68,0x99,0x11,0x73,0x61,0xa3,0xc3,0x61, +0x36,0x65,0xa2,0x65,0x66,0xa2,0x71,0x67,0x11,0x6c,0x67,0x75,6,0x6c,0x28,0x6c, +0x32,0x6d,0x38,0x6e,0x44,0x76,0x10,0x74,0xa3,0x7f,1,0x65,0x89,0x75,0x97,1, +0x69,0x24,0x6c,0x67,0x10,0x6c,0x67,0x10,0x67,0xa2,0x9a,1,0x73,0x2a,0x75,0x10, +0x74,0xa3,0x9a,0x10,0x61,0xa3,0xc3,0x67,0x36,0x69,0x52,0x6b,0x10,0x72,0xa2,0x99, +0x10,0x69,0xa3,0x99,1,0x61,0x30,0x62,0x7a,0x13,0x61,0x6e,0x77,0x61,0x7b,0x12, +0x6c,0x6f,0x67,0x75,2,0x6c,0x32,0x74,0x34,0x76,0x12,0x69,0x65,0x74,0xa3,0x7f, +0x10,0x65,0x89,0x12,0x68,0x61,0x6d,0xa3,0x6a,1,0x6c,0x2a,0x6e,0x10,0x67,0xa3, +0x62,0x10,0x75,0x68,0x11,0x67,0x75,0x69,0x11,0x6e,0x67,0x99,1,0x67,0x32,0x6e, +0x14,0x6b,0x6e,0x6f,0x77,0x6e,0xa3,0x67,0x11,0x61,0x72,0x8a,0x13,0x69,0x74,0x69, +0x63,0x8b,0x71,0xc1,0x13,0x71,0xa2,0xde,0x72,0xa2,0xe3,0x73,6,0x69,0x8a,0x69, +0x72,0x6f,0xa2,0x4c,0x75,0xa2,0x75,0x79,1,0x6c,0x46,0x72,4,0x63,0x65,0x65, +0xa3,0x5f,0x69,0x2c,0x6a,0xa3,0x60,0x6e,0xa3,0x61,0x11,0x61,0x63,0x65,0x10,0x6f, +0x94,0x16,0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0x95,2,0x64,0x3c,0x67,0x4c,0x6e, +1,0x64,0xa3,0x91,0x68,0x62,0x12,0x61,0x6c,0x61,0x63,0x10,0x64,0xa2,0xa6,0x12, +0x68,0x61,0x6d,0xa3,0xa6,0x17,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa3,0x70, +2,0x67,0x3a,0x72,0x52,0x79,0x10,0x6f,0xa2,0xb0,0x12,0x6d,0x62,0x6f,0xa3,0xb0, +1,0x64,0x26,0x6f,0xa3,0xb8,0xa2,0xb7,0x12,0x69,0x61,0x6e,0xa3,0xb7,0x10,0x61, +0xa2,0x98,0x16,0x73,0x6f,0x6d,0x70,0x65,0x6e,0x67,0xa3,0x98,0x11,0x6e,0x64,0xa2, +0x71,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0x71,0x61,0x5c,0x67,0xa2,0x43,0x68,1, +0x61,0x2a,0x72,0x10,0x64,0xa3,0x97,2,0x72,0x28,0x76,0x30,0x77,0x87,0x12,0x61, +0x64,0x61,0xa3,0x97,0x12,0x69,0x61,0x6e,0x87,2,0x6d,0x40,0x72,0x58,0x75,0x10, +0x72,0xa2,0x6f,0x15,0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0x6f,1,0x61,0x26,0x72, +0xa3,0x7e,0x14,0x72,0x69,0x74,0x61,0x6e,0xa3,0x7e,1,0x61,0xa3,0x5e,0x62,0xa3, +0x85,0x11,0x6e,0x77,0xa3,0x70,0x11,0x61,0x61,1,0x63,0x2f,0x69,0x23,3,0x65, +0x3e,0x6a,0x48,0x6f,0x4e,0x75,0x10,0x6e,1,0x69,0x24,0x72,0x61,0x10,0x63,0x61, +0x13,0x6a,0x61,0x6e,0x67,0xa3,0x6e,0x11,0x6e,0x67,0xa3,0x6e,1,0x68,0x2a,0x72, +0x10,0x6f,0xa3,0x5d,0x10,0x67,0xa3,0xb6,0x6e,0xa2,0x83,0x6f,0xa4,1,0x70,5, +0x6c,0x1e,0x6c,0x44,0x72,0x4a,0x73,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61,0x68, +0x6c,0x61,0x76,0x69,0xa3,0x7b,0x11,0x72,0x64,0xa3,0x5c,0x11,0x74,0x69,0xa3,0x7d, +0x61,0x7c,0x65,0xa2,0x54,0x68,3,0x61,0x3e,0x6c,0x4e,0x6e,0x5e,0x6f,0x16,0x65, +0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x5b,0x10,0x67,0xa2,0x5a,0x12,0x73,0x70,0x61, +0xa3,0x5a,2,0x69,0xa3,0x7a,0x70,0xa3,0x7b,0x76,0xa3,0x7c,0x10,0x78,0xa3,0x5b, +2,0x68,0x3e,0x6c,0x50,0x75,0x10,0x63,0xa2,0xa5,0x14,0x69,0x6e,0x68,0x61,0x75, +0xa3,0xa5,0x17,0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0x4b,0x10,0x6d,0xa2, +0x90,0x14,0x79,0x72,0x65,0x6e,0x65,0xa3,0x90,0x11,0x72,0x6d,0xa3,0x59,6,0x6b, +0x36,0x6b,0x56,0x73,0x6e,0x75,0x74,0x79,0x11,0x69,0x61,0x1f,0x6b,0x65,0x6e,0x67, +0x70,0x75,0x61,0x63,0x68,0x75,0x65,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0xba,1,0x67, +0x2e,0x6f,0xa2,0x57,0x10,0x6f,0xa3,0x57,0x10,0x62,0xa3,0x84,0x11,0x68,0x75,0xa3, +0x96,0x12,0x73,0x68,0x75,0xa3,0x96,0x61,0x42,0x62,0x9e,0x65,0x10,0x77,1,0x61, +0xa3,0xaa,0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0x97,3,0x62,0x32,0x67,0x40,0x6e, +0x56,0x72,0x10,0x62,0xa3,0x8e,0x15,0x61,0x74,0x61,0x65,0x61,0x6e,0xa3,0x8f,0x10, +0x6d,0xa2,0xc7,0x15,0x75,0x6e,0x64,0x61,0x72,0x69,0xa3,0xc7,0x10,0x64,0xa2,0xbb, +0x16,0x69,0x6e,0x61,0x67,0x61,0x72,0x69,0xa3,0xbb,0x11,0x61,0x74,0xa3,0x8f,4, +0x67,0x3c,0x6c,0x4e,0x72,0xa2,0x8e,0x73,0xa2,0x9c,0x75,0x11,0x67,0x72,0xa3,0xc2, +1,0x61,0x2a,0x68,0x11,0x61,0x6d,0x5b,0x10,0x6d,0x5b,1,0x63,0xa2,0x6a,0x64, +6,0x70,0x41,0x70,0x3a,0x73,0x58,0x74,0x86,0x75,0x14,0x79,0x67,0x68,0x75,0x72, +0xa3,0xc2,0x11,0x65,0x72,1,0x6d,0x2c,0x73,0x12,0x69,0x61,0x6e,0x9b,0x11,0x69, +0x63,0xa3,0x59,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61,0x72,0x61,0x62, +0x69,0x61,0x6e,0xa3,0x85,0x13,0x64,0x69,0x61,0x6e,0xa3,0xb8,0x14,0x75,0x72,0x6b, +0x69,0x63,0xa3,0x58,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72, +0x61,0x62,0x69,0x61,0x6e,0xa3,0x8e,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e, +0xa3,0x4c,0x14,0x74,0x61,0x6c,0x69,0x63,0x5d,1,0x68,0x26,0x6b,0xa3,0x6d,0x12, +0x69,0x6b,0x69,0xa3,0x6d,2,0x69,0x2c,0x6b,0x30,0x79,0x10,0x61,0x5f,0x11,0x79, +0x61,0x5f,0x10,0x68,0xa3,0x58,2,0x61,0x36,0x67,0x3c,0x6d,0x10,0x61,0x84,0x12, +0x6e,0x79,0x61,0x85,0x11,0x67,0x65,0xa3,0xab,0x10,0x65,0xa3,0xab,0x68,0xc3,0x15, +0x6b,0xc2,0x2c,0x6b,0xa4,0x17,0x6c,0xa4,0xba,0x6d,8,0x6f,0x46,0x6f,0x48,0x72, +0x74,0x74,0x80,0x75,0x86,0x79,1,0x61,0x28,0x6d,0x10,0x72,0x59,0x13,0x6e,0x6d, +0x61,0x72,0x59,2,0x64,0x2e,0x6e,0x32,0x6f,0x10,0x6e,0xa3,0x72,0x10,0x69,0xa3, +0xa3,0x10,0x67,0x56,0x14,0x6f,0x6c,0x69,0x61,0x6e,0x57,0x10,0x6f,0xa2,0x95,0x10, +0x6f,0xa3,0x95,0x11,0x65,0x69,0xa3,0x73,0x11,0x6c,0x74,0xa2,0xa4,0x12,0x61,0x6e, +0x69,0xa3,0xa4,0x61,0x36,0x65,0xa2,0x67,0x69,0xa2,0xbd,0x6c,0x11,0x79,0x6d,0x55, +6,0x6e,0x38,0x6e,0x32,0x72,0x5c,0x73,0x6c,0x79,0x10,0x61,0xa3,0x55,1,0x64, +0x38,0x69,0xa2,0x79,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3,0x79,0xa2,0x54,0x12, +0x61,0x69,0x63,0xa3,0x54,0x10,0x63,0xa2,0xa9,0x12,0x68,0x65,0x6e,0xa3,0xa9,0x18, +0x61,0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xaf,0x68,0x36,0x6b,0x4c,0x6c, +0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x55,1,0x61,0x26,0x6a,0xa3,0xa0,0x13,0x6a, +0x61,0x6e,0x69,0xa3,0xa0,0x10,0x61,0xa2,0xb4,0x12,0x73,0x61,0x72,0xa3,0xb4,3, +0x64,0x78,0x65,0x94,0x6e,0xa2,0x42,0x72,1,0x63,0xa3,0x8d,0x6f,0xa2,0x56,0x13, +0x69,0x74,0x69,0x63,1,0x63,0x3c,0x68,0x19,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79, +0x70,0x68,0x73,0xa3,0x56,0x15,0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0x8d,1,0x65, +0x26,0x66,0xa3,0xb5,0x16,0x66,0x61,0x69,0x64,0x72,0x69,0x6e,0xa3,0xb5,0x17,0x74, +0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa3,0x73,0x10,0x64,0xa2,0x8c,0x17,0x65,0x6b, +0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0x8c,0x11,0x61,0x6f,0xa3,0x5c,6,0x6e,0x1a, +0x6e,0x34,0x6f,0x38,0x70,0x3e,0x74,0x11,0x68,0x69,0xa3,0x78,0x11,0x64,0x61,0x4b, +0x11,0x72,0x65,0xa3,0x77,0x11,0x65,0x6c,0xa3,0x8a,0x61,0x32,0x68,0xa2,0x44,0x69, +0x11,0x74,0x73,0xa3,0xbf,5,0x74,0x23,0x74,0x34,0x77,0x56,0x79,0x13,0x61,0x68, +0x6c,0x69,0xa3,0x4f,0x14,0x61,0x6b,0x61,0x6e,0x61,0x4c,0x19,0x6f,0x72,0x68,0x69, +0x72,0x61,0x67,0x61,0x6e,0x61,0x8d,0x10,0x69,0xa3,0xc6,0x69,0x38,0x6c,0x40,0x6e, +1,0x61,0x4d,0x6e,0x12,0x61,0x64,0x61,0x4b,0x12,0x74,0x68,0x69,0xa3,0x78,0x10, +0x69,0xa3,0x4f,4,0x61,0x40,0x69,0x52,0x6d,0x70,0x6f,0x7c,0x75,0x15,0x64,0x61, +0x77,0x61,0x64,0x69,0xa3,0x91,0x10,0x72,0x92,0x15,0x6f,0x73,0x68,0x74,0x68,0x69, +0x93,0x1d,0x74,0x61,0x6e,0x73,0x6d,0x61,0x6c,0x6c,0x73,0x63,0x72,0x69,0x70,0x74, +0xa3,0xbf,1,0x65,0x24,0x72,0x4f,0x10,0x72,0x4f,0x10,0x6a,0xa2,0x9d,0x11,0x6b, +0x69,0xa3,0x9d,4,0x61,0x5c,0x65,0x90,0x69,0xa0,0x6f,0xa2,0x5d,0x79,1,0x63, +0x34,0x64,0x10,0x69,0xa2,0x6c,0x11,0x61,0x6e,0xa3,0x6c,0x10,0x69,0xa2,0x6b,0x11, +0x61,0x6e,0xa3,0x6b,2,0x6e,0x42,0x6f,0x46,0x74,3,0x66,0xa3,0x50,0x67,0xa3, +0x51,0x69,0x24,0x6e,0x53,0x10,0x6e,0x53,0x10,0x61,0xa3,0x6a,0x50,0x10,0x6f,0x51, +0x11,0x70,0x63,0xa2,0x52,0x11,0x68,0x61,0xa3,0x52,2,0x6d,0x2e,0x6e,0x36,0x73, +0x10,0x75,0xa3,0x83,0x10,0x62,0x80,0x10,0x75,0x81,2,0x61,0xa3,0x53,0x62,0x83, +0x65,0x11,0x61,0x72,1,0x61,0xa3,0x53,0x62,0x83,0x11,0x6d,0x61,0xa3,0x8b,0x68, +0x6e,0x69,0xa2,0x95,0x6a,2,0x61,0x30,0x70,0x52,0x75,0x11,0x72,0x63,0xa3,0x94, +1,0x6d,0x38,0x76,0x10,0x61,0xa2,0x4e,0x13,0x6e,0x65,0x73,0x65,0xa3,0x4e,0x10, +0x6f,0xa3,0xad,0x11,0x61,0x6e,0xa3,0x69,6,0x6c,0x1e,0x6c,0x34,0x6d,0x3a,0x72, +0x48,0x75,0x11,0x6e,0x67,0xa3,0x4c,0x11,0x75,0x77,0xa3,0x9c,0x10,0x6e,1,0x67, +0xa3,0x4b,0x70,0xa3,0xba,0x11,0x6b,0x74,0x8d,0x61,0x3c,0x65,0xa2,0x43,0x69,0x11, +0x72,0x61,0x48,0x13,0x67,0x61,0x6e,0x61,0x49,1,0x6e,0x34,0x74,0x10,0x72,0xa2, +0xa2,0x11,0x61,0x6e,0xa3,0xa2,0x42,6,0x6f,0xe,0x6f,0x77,0x73,0xa3,0x49,0x74, +0xa3,0x4a,0x75,0x12,0x6e,0x6f,0x6f,0x77,0x62,0xa3,0xac,0x67,0x3e,0x69,0x42,0x19, +0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa3,0xb6,0x44,0x11,0x75,0x6c, +0x45,0x11,0x62,0x72,0x46,0x11,0x65,0x77,0x47,2,0x6d,0x2e,0x6e,0x4a,0x74,0x11, +0x61,0x6c,0x5d,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69, +0x63,0xa3,0x74,2,0x64,0x66,0x68,0x6a,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69, +0x6f,0x6e,0x61,0x6c,0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e, +0xa3,0x7d,0x13,0x6c,0x61,0x76,0x69,0xa3,0x7a,0x10,0x73,0xa3,0x4d,0x15,0x65,0x72, +0x69,0x74,0x65,0x64,0x23,0x64,0xc1,0xd,0x64,0xa2,0x7a,0x65,0xa2,0xc1,0x67,4, +0x65,0x82,0x6c,0x9a,0x6f,0xa2,0x46,0x72,0xa2,0x55,0x75,2,0x6a,0x3c,0x6e,0x4e, +0x72,1,0x6d,0x24,0x75,0x41,0x13,0x75,0x6b,0x68,0x69,0x41,1,0x61,0x24,0x72, +0x3f,0x13,0x72,0x61,0x74,0x69,0x3f,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64, +0x69,0xa3,0xb3,0x10,0x6f,1,0x6b,0xa3,0x48,0x72,0x38,0x13,0x67,0x69,0x61,0x6e, +0x39,0x11,0x61,0x67,0x90,0x15,0x6f,0x6c,0x69,0x74,0x69,0x63,0x91,1,0x6e,0x30, +0x74,0x10,0x68,0x3a,0x11,0x69,0x63,0x3b,1,0x67,0xa3,0xb3,0x6d,0xa3,0xaf,1, +0x61,0x32,0x65,1,0x65,0x24,0x6b,0x3d,0x10,0x6b,0x3d,0x10,0x6e,0xa2,0x89,0x12, +0x74,0x68,0x61,0xa3,0x89,4,0x65,0x46,0x69,0x6c,0x6f,0x8c,0x73,0x9a,0x75,0x11, +0x70,0x6c,0xa2,0x87,0x13,0x6f,0x79,0x61,0x6e,0xa3,0x87,1,0x73,0x38,0x76,0x10, +0x61,0x34,0x15,0x6e,0x61,0x67,0x61,0x72,0x69,0x35,0x13,0x65,0x72,0x65,0x74,0x33, +1,0x61,0x36,0x76,0x16,0x65,0x73,0x61,0x6b,0x75,0x72,0x75,0xa3,0xbe,0x10,0x6b, +0xa3,0xbe,0x11,0x67,0x72,0xa2,0xb2,0x10,0x61,0xa3,0xb2,0x11,0x72,0x74,0x33,2, +0x67,0x3a,0x6c,0x72,0x74,0x11,0x68,0x69,0x36,0x13,0x6f,0x70,0x69,0x63,0x37,0x10, +0x79,2,0x64,0xa3,0x45,0x68,0xa3,0x46,0x70,0xa2,0x47,0x1e,0x74,0x69,0x61,0x6e, +0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x47,1,0x62,0x36, +0x79,0x10,0x6d,0xa2,0xb9,0x12,0x61,0x69,0x63,0xa3,0xb9,0x10,0x61,0xa2,0x88,0x12, +0x73,0x61,0x6e,0xa3,0x88,0x61,0xa2,0xc9,0x62,0xa4,0x2e,0x63,6,0x6f,0x52,0x6f, +0x76,0x70,0x92,0x75,0xa2,0x41,0x79,1,0x70,0x3e,0x72,2,0x69,0x2a,0x6c,0x31, +0x73,0xa3,0x44,0x13,0x6c,0x6c,0x69,0x63,0x31,0x10,0x72,1,0x69,0x34,0x6f,0x15, +0x6d,0x69,0x6e,0x6f,0x61,0x6e,0xa3,0xc1,0x11,0x6f,0x74,0x7f,1,0x6d,0x30,0x70, +0x10,0x74,0x2e,0x11,0x69,0x63,0x2f,0x12,0x6d,0x6f,0x6e,0x21,1,0x6d,0x28,0x72, +0x10,0x74,0x7f,0x10,0x6e,0xa3,0xc1,0x16,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa3, +0x65,0x61,0x32,0x68,0xa2,0x41,0x69,0x11,0x72,0x74,0xa3,0x43,3,0x6b,0x4c,0x6e, +0x50,0x72,0x76,0x75,0x1d,0x63,0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e, +0x69,0x61,0x6e,0xa3,0x9f,0x10,0x6d,0xa3,0x76,1,0x61,0x24,0x73,0x71,0x1d,0x64, +0x69,0x61,0x6e,0x61,0x62,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x71,0x10,0x69, +0xa2,0x68,0x11,0x61,0x6e,0xa3,0x68,3,0x61,0x32,0x65,0x44,0x6f,0x52,0x72,0x10, +0x73,0xa3,0xbd,1,0x6b,0x26,0x6d,0xa3,0x42,0x11,0x6d,0x61,0xa3,0x76,0x10,0x72, +0x2c,0x13,0x6f,0x6b,0x65,0x65,0x2d,0x16,0x72,0x61,0x73,0x6d,0x69,0x61,0x6e,0xa3, +0xbd,6,0x68,0x4a,0x68,0x48,0x6e,0x4e,0x72,0x76,0x76,1,0x65,0x2a,0x73,0x10, +0x74,0xa3,0x75,0x13,0x73,0x74,0x61,0x6e,0xa3,0x75,0x11,0x6f,0x6d,0xa3,0xa1,0x11, +0x61,0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79, +0x70,0x68,0x73,0xa3,0x9c,1,0x61,0x3e,0x6d,2,0x65,0x2a,0x69,0xa3,0x74,0x6e, +0x27,0x13,0x6e,0x69,0x61,0x6e,0x27,0x10,0x62,0x24,0x11,0x69,0x63,0x25,0x64,0x30, +0x66,0x44,0x67,0x11,0x68,0x62,0xa3,0x9f,0x10,0x6c,1,0x61,0x26,0x6d,0xa3,0xa7, +0x10,0x6d,0xa3,0xa7,0x11,0x61,0x6b,0xa3,0x93,6,0x6c,0x3c,0x6c,0x52,0x6f,0x56, +0x72,0x66,0x75,1,0x67,0x30,0x68,1,0x64,0x79,0x69,0x10,0x64,0x79,0x10,0x69, +0x8e,0x13,0x6e,0x65,0x73,0x65,0x8f,0x11,0x69,0x73,0xa1,0x11,0x70,0x6f,0x2a,0x13, +0x6d,0x6f,0x66,0x6f,0x2b,0x10,0x61,1,0x68,0x2e,0x69,0x7c,0x12,0x6c,0x6c,0x65, +0x7d,0xa2,0x41,0x11,0x6d,0x69,0xa3,0x41,0x61,0x48,0x65,0x9c,0x68,1,0x61,0x2a, +0x6b,0x10,0x73,0xa3,0xa8,0x15,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa3,0xa8,3,0x6c, +0x3a,0x6d,0x48,0x73,0x54,0x74,1,0x61,0x24,0x6b,0x9f,0x10,0x6b,0x9f,0x10,0x69, +0x9c,0x13,0x6e,0x65,0x73,0x65,0x9d,0x10,0x75,0xa2,0x82,0x10,0x6d,0xa3,0x82,0x10, +0x73,0xa2,0x86,0x13,0x61,0x76,0x61,0x68,0xa3,0x86,0x11,0x6e,0x67,0x28,0x12,0x61, +0x6c,0x69,0x29,3,0x6c,0x42,0x6e,0x90,0x74,0xa2,0x46,0x76,0x24,0x17,0x6f,0x77, +0x65,0x6c,0x6a,0x61,0x6d,0x6f,0x25,0x22,1,0x65,0x54,0x76,0x28,1,0x73,0x38, +0x74,0x2a,0x17,0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x2b,0x16,0x79,0x6c,0x6c, +0x61,0x62,0x6c,0x65,0x29,0x18,0x61,0x64,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x23, +1,0x61,0x21,0x6f,0x1a,0x74,0x61,0x70,0x70,0x6c,0x69,0x63,0x61,0x62,0x6c,0x65, +0x21,0x26,0x1a,0x72,0x61,0x69,0x6c,0x69,0x6e,0x67,0x6a,0x61,0x6d,0x6f,0x27,1, +0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,1,0x6e,0x2c,0x79, +0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22, +0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,2, +0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65, +0x25,0x20,0x10,0x6f,0x21,0xb,0x72,0x39,0x76,0xc,0x76,0x33,0x78,0x2a,0x7a,0x11, +0x77,0x6a,0x43,0x10,0x78,0x21,0x72,0x28,0x73,0x50,0x74,0x31,1,0x65,0x24,0x69, +0x39,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f, +0x72,0x39,1,0x6d,0x35,0x70,0x18,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b, +0x35,0x6c,0x1f,0x6c,0x3c,0x6f,0x4a,0x70,1,0x70,0x37,0x72,0x14,0x65,0x70,0x65, +0x6e,0x64,0x37,0x28,1,0x66,0x2b,0x76,0x2c,0x10,0x74,0x2f,0x13,0x74,0x68,0x65, +0x72,0x21,0x63,0x4c,0x65,0x64,0x67,1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66, +0x74,0x65,0x72,0x7a,0x77,0x6a,0x41,0x10,0x7a,0x41,2,0x6e,0x23,0x6f,0x24,0x72, +0x25,0x14,0x6e,0x74,0x72,0x6f,0x6c,0x23,2,0x62,0x34,0x6d,0x4e,0x78,0x26,0x13, +0x74,0x65,0x6e,0x64,0x27,0x3a,1,0x61,0x24,0x67,0x3d,0x11,0x73,0x65,0x3a,0x12, +0x67,0x61,0x7a,0x3d,0x3e,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x3f,9,0x6e, +0x4a,0x6e,0x34,0x6f,0x44,0x73,0x60,0x75,0x94,0x78,0x10,0x78,0x21,0x10,0x75,0x2a, +0x14,0x6d,0x65,0x72,0x69,0x63,0x2b,1,0x6c,0x2c,0x74,0x12,0x68,0x65,0x72,0x21, +0x14,0x65,0x74,0x74,0x65,0x72,0x2d,3,0x63,0x36,0x65,0x46,0x70,0x31,0x74,0x32, +0x12,0x65,0x72,0x6d,0x33,0x3c,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3d,0x2e, +0x10,0x70,0x2f,0x10,0x70,0x34,0x12,0x70,0x65,0x72,0x35,0x61,0x46,0x63,0x52,0x65, +0x64,0x66,0x72,0x6c,2,0x65,0x2d,0x66,0x3b,0x6f,0x28,0x12,0x77,0x65,0x72,0x29, +0x10,0x74,0x22,0x12,0x65,0x72,0x6d,0x23,1,0x6c,0x24,0x72,0x37,0x24,0x12,0x6f, +0x73,0x65,0x25,0x10,0x78,0x38,0x13,0x74,0x65,0x6e,0x64,0x39,0x10,0x6f,0x26,0x13, +0x72,0x6d,0x61,0x74,0x27,0,0x10,0x6c,0x88,0x72,0x40,0x72,0x36,0x73,0x5e,0x77, +0x7a,0x78,0x8a,0x7a,0x11,0x77,0x6a,0x4b,1,0x65,0x24,0x69,0x3b,0x1e,0x67,0x69, +0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x3b,1,0x69, +0x24,0x71,0x3f,0x18,0x6e,0x67,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x3f,0x17,0x73, +0x65,0x67,0x73,0x70,0x61,0x63,0x65,0x4d,0x10,0x78,0x21,0x6c,0x36,0x6d,0x3c,0x6e, +0x76,0x6f,0x13,0x74,0x68,0x65,0x72,0x21,1,0x65,0x23,0x66,0x35,3,0x62,0x37, +0x69,0x28,0x6c,0x29,0x6e,0x2b,0x10,0x64,1,0x6c,0x34,0x6e,0x11,0x75,0x6d,0x2a, +0x12,0x6c,0x65,0x74,0x37,0x14,0x65,0x74,0x74,0x65,0x72,0x29,2,0x65,0x36,0x6c, +0x39,0x75,0x2c,0x14,0x6d,0x65,0x72,0x69,0x63,0x2d,0x14,0x77,0x6c,0x69,0x6e,0x65, +0x39,0x66,0x3f,0x66,0x40,0x67,0x4e,0x68,0x70,0x6b,0x10,0x61,0x26,0x15,0x74,0x61, +0x6b,0x61,0x6e,0x61,0x27,0x10,0x6f,0x24,0x13,0x72,0x6d,0x61,0x74,0x25,1,0x61, +0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a,0x49,0x10,0x7a, +0x49,1,0x65,0x24,0x6c,0x3d,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65, +0x72,0x3d,0x61,0x86,0x63,0x92,0x64,0x94,0x65,2,0x62,0x44,0x6d,0x5e,0x78,0x2e, +0x13,0x74,0x65,0x6e,0x64,0x32,0x15,0x6e,0x75,0x6d,0x6c,0x65,0x74,0x2f,0x42,1, +0x61,0x24,0x67,0x45,0x11,0x73,0x65,0x42,0x12,0x67,0x61,0x7a,0x45,0x46,0x16,0x6f, +0x64,0x69,0x66,0x69,0x65,0x72,0x47,0x15,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x10, +0x72,0x31,1,0x6f,0x24,0x71,0x41,0x18,0x75,0x62,0x6c,0x65,0x71,0x75,0x6f,0x74, +0x65,0x41,2,0x63,0x32,0x6e,0x3c,0x6f,0x22,0x12,0x70,0x65,0x6e,0x23,0x24,0x13, +0x6c,0x6f,0x73,0x65,0x25,0x20,0x12,0x6f,0x6e,0x65,0x21,6,0x6f,0x65,0x6f,0x4a, +0x72,0x5c,0x74,0x64,0x76,0x1d,0x69,0x73,0x75,0x61,0x6c,0x6f,0x72,0x64,0x65,0x72, +0x6c,0x65,0x66,0x74,0x3d,0x18,0x76,0x65,0x72,0x73,0x74,0x72,0x75,0x63,0x6b,0x2d, +0x13,0x69,0x67,0x68,0x74,0x2f,0x11,0x6f,0x70,0x30,0x12,0x61,0x6e,0x64,2,0x62, +0x32,0x6c,0x62,0x72,0x13,0x69,0x67,0x68,0x74,0x3b,0x14,0x6f,0x74,0x74,0x6f,0x6d, +0x32,0x12,0x61,0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x35,0x12, +0x65,0x66,0x74,0x3f,0x12,0x65,0x66,0x74,0x36,0x17,0x61,0x6e,0x64,0x72,0x69,0x67, +0x68,0x74,0x39,0x62,0x2c,0x6c,0x5c,0x6e,0x10,0x61,0x21,0x14,0x6f,0x74,0x74,0x6f, +0x6d,0x22,0x12,0x61,0x6e,0x64,1,0x6c,0x2e,0x72,0x13,0x69,0x67,0x68,0x74,0x27, +0x12,0x65,0x66,0x74,0x25,0x12,0x65,0x66,0x74,0x28,0x17,0x61,0x6e,0x64,0x72,0x69, +0x67,0x68,0x74,0x2b,0xd,0x6e,0xaa,0x72,0x70,0x72,0x92,0x73,0xa2,0x46,0x74,0xa2, +0x54,0x76,1,0x69,0x60,0x6f,0x12,0x77,0x65,0x6c,0x62,1,0x64,0x3a,0x69,0x19, +0x6e,0x64,0x65,0x70,0x65,0x6e,0x64,0x65,0x6e,0x74,0x67,0x17,0x65,0x70,0x65,0x6e, +0x64,0x65,0x6e,0x74,0x65,1,0x72,0x2e,0x73,0x13,0x61,0x72,0x67,0x61,0x61,0x12, +0x61,0x6d,0x61,0x5f,0x1d,0x65,0x67,0x69,0x73,0x74,0x65,0x72,0x73,0x68,0x69,0x66, +0x74,0x65,0x72,0x57,0x1e,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x6d,0x6f,0x64,0x69, +0x66,0x69,0x65,0x72,0x59,0x12,0x6f,0x6e,0x65,1,0x6c,0x2c,0x6d,0x12,0x61,0x72, +0x6b,0x5d,0x14,0x65,0x74,0x74,0x65,0x72,0x5b,0x6e,0x3c,0x6f,0x7c,0x70,0x18,0x75, +0x72,0x65,0x6b,0x69,0x6c,0x6c,0x65,0x72,0x55,1,0x6f,0x4c,0x75,1,0x6b,0x3c, +0x6d,0x12,0x62,0x65,0x72,0x50,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x53,0x11,0x74, +0x61,0x4f,0x16,0x6e,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x4d,0x13,0x74,0x68,0x65,0x72, +0x21,0x67,0x3e,0x67,0x4a,0x69,0x64,0x6a,0x82,0x6d,0x1d,0x6f,0x64,0x69,0x66,0x79, +0x69,0x6e,0x67,0x6c,0x65,0x74,0x74,0x65,0x72,0x4b,0x1c,0x65,0x6d,0x69,0x6e,0x61, +0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x45,0x1e,0x6e,0x76,0x69,0x73,0x69,0x62, +0x6c,0x65,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x47,0x14,0x6f,0x69,0x6e,0x65,0x72, +0x49,0x61,0xa2,0xba,0x62,0xa2,0xc0,0x63,1,0x61,0xa2,0xa2,0x6f,0x16,0x6e,0x73, +0x6f,0x6e,0x61,0x6e,0x74,0x2a,8,0x6b,0x67,0x6b,0x48,0x6d,0x52,0x70,0x5c,0x73, +0xa2,0x42,0x77,0x19,0x69,0x74,0x68,0x73,0x74,0x61,0x63,0x6b,0x65,0x72,0x43,0x14, +0x69,0x6c,0x6c,0x65,0x72,0x35,0x14,0x65,0x64,0x69,0x61,0x6c,0x37,1,0x6c,0x52, +0x72,0x10,0x65,1,0x63,0x2e,0x66,0x13,0x69,0x78,0x65,0x64,0x3d,0x19,0x65,0x64, +0x69,0x6e,0x67,0x72,0x65,0x70,0x68,0x61,0x3b,0x18,0x61,0x63,0x65,0x68,0x6f,0x6c, +0x64,0x65,0x72,0x39,0x10,0x75,1,0x62,0x3e,0x63,0x1b,0x63,0x65,0x65,0x64,0x69, +0x6e,0x67,0x72,0x65,0x70,0x68,0x61,0x41,0x15,0x6a,0x6f,0x69,0x6e,0x65,0x64,0x3f, +0x64,0x4c,0x66,0x52,0x68,0x5a,0x69,0x1e,0x6e,0x69,0x74,0x69,0x61,0x6c,0x70,0x6f, +0x73,0x74,0x66,0x69,0x78,0x65,0x64,0x33,0x12,0x65,0x61,0x64,0x2d,0x13,0x69,0x6e, +0x61,0x6c,0x2f,0x18,0x65,0x61,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,0x1d,0x6e, +0x74,0x69,0x6c,0x6c,0x61,0x74,0x69,0x6f,0x6e,0x6d,0x61,0x72,0x6b,0x29,0x16,0x76, +0x61,0x67,0x72,0x61,0x68,0x61,0x23,1,0x69,0x4a,0x72,0x10,0x61,0x1f,0x68,0x6d, +0x69,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x6e,0x75,0x6d,0x62,0x65,0x72,0x27,0x12, +0x6e,0x64,0x75,0x25,2,0x72,0x38,0x74,0x46,0x75,0x26,0x15,0x70,0x72,0x69,0x67, +0x68,0x74,0x27,0x20,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x21,1,0x72,0x24,0x75, +0x25,0x22,0x18,0x61,0x6e,0x73,0x66,0x6f,0x72,0x6d,0x65,0x64,1,0x72,0x32,0x75, +0x15,0x70,0x72,0x69,0x67,0x68,0x74,0x25,0x15,0x6f,0x74,0x61,0x74,0x65,0x64,0x23, +0xd,0x6e,0xc1,0x86,0x73,0xa8,0x73,0x4c,0x74,0xa2,0x76,0x75,0xa2,0x83,0x7a,0xd8, +0x70,0,2,0x6c,0xd9,0x20,0,0x70,0xd9,0x40,0,0x73,0xc3,0,0xfe,0xf, +0,0,0,7,0x6f,0x3c,0x6f,0xff,8,0,0,0,0x70,0x3a,0x75,0x6e, +0x79,0x13,0x6d,0x62,0x6f,0x6c,0xff,0xf,0,0,0,0x11,0x61,0x63,1,0x65, +0x34,0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0,0x18,0x73,0x65,0x70,0x61, +0x72,0x61,0x74,0x6f,0x72,0xc3,0,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0xe1, +0,0,0x63,0xff,2,0,0,0,0x65,0x38,0x6b,0xff,4,0,0,0, +0x6d,0xff,1,0,0,0,0x16,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x70, +0,0x1d,0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72, +0x31,1,0x6e,0x40,0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74, +0x74,0x65,0x72,0x25,0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x23,0x6e,0xa2, +0x69,0x6f,0xa2,0x89,0x70,0xfe,0x30,0xf8,0,0,9,0x69,0x33,0x69,0xff,0x10, +0,0,0,0x6f,0xfd,0x80,0,0,0x72,0x54,0x73,0xf9,0,0,0x75,0x12, +0x6e,0x63,0x74,0xfe,0x30,0xf8,0,0,0x15,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff, +0x30,0xf8,0,0,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xdd,0,0, +0x61,0x48,0x63,0xfd,0x40,0,0,0x64,0xe9,0,0,0x65,0xfd,0x20,0,0, +0x66,0xff,0x20,0,0,0,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65, +0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x40,0,0xbe,0,3,0x64,0xa7,0, +0x6c,0xab,0,0x6f,0x30,0x75,0x13,0x6d,0x62,0x65,0x72,0xbf,0,0xb2,0,0x1b, +0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa1,1,0x70,0x92, +0x74,0x12,0x68,0x65,0x72,0xe6,0x80,1,3,0x6c,0x40,0x6e,0x4a,0x70,0x56,0x73, +0x14,0x79,0x6d,0x62,0x6f,0x6c,0xff,8,0,0,0,0x14,0x65,0x74,0x74,0x65, +0x72,0x61,0x14,0x75,0x6d,0x62,0x65,0x72,0xb3,0,0x19,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0xfd,0x80,0,0,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xf9,0,0,0x66,0xc0,0xc4,0x66,0xa2,0x47, +0x69,0xa2,0x64,0x6c,0xa2,0x79,0x6d,0xa4,0xc0,4,0x61,0x6c,0x63,0xa5,0,0x65, +0xa3,0x80,0x6e,0xa1,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c,0x38,0x73, +0x14,0x79,0x6d,0x62,0x6f,0x6c,0xff,4,0,0,0,0x14,0x65,0x74,0x74,0x65, +0x72,0x41,1,0x72,0x3c,0x74,0x16,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff,1, +0,0,0,0x10,0x6b,0xa5,0xc0,1,0x69,0x32,0x6f,0x13,0x72,0x6d,0x61,0x74, +0xdb,0,0,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, +0x6f,0x6e,0xff,0x20,0,0,0,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70, +0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x10,0,0,0,0x9c, +7,0x6d,0x18,0x6d,0x41,0x6f,0x28,0x74,0x31,0x75,0x25,0x60,0x1c,0x77,0x65,0x72, +0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x29,0x63,0x3d,0x65,0x28,0x69, +0x42,0x6c,0x29,0x13,0x74,0x74,0x65,0x72,0x9c,0x15,0x6e,0x75,0x6d,0x62,0x65,0x72, +0xab,0,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x20, +0,0x63,0x46,0x64,0xa2,0x96,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67, +0x6d,0x61,0x72,0x6b,0xa3,0x80,0xe6,0x80,1,7,0x6e,0x57,0x6e,0x52,0x6f,0x5e, +0x73,0xe1,0,0,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62, +0x6f,0x6c,0xff,2,0,0,0,0x22,0x12,0x74,0x72,0x6c,0xd9,0x80,0,0xdc, +0,0,1,0x6d,0x62,0x6e,1,0x6e,0x30,0x74,0x12,0x72,0x6f,0x6c,0xd9,0x80, +0,0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, +0x6f,0x6e,0xfd,0x40,0,0,0x19,0x62,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72, +0x6b,0xa5,0xc0,0x61,0x58,0x63,0xd9,0x80,0,0x66,0xdb,0,0,0x6c,0x1d,0x6f, +0x73,0x65,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x20,0, +0,0x18,0x73,0x65,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,2,0x61,0x32,0x65, +0x50,0x69,0x12,0x67,0x69,0x74,0xa7,0,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74, +0x75,0x61,0x74,0x69,0x6f,0x6e,0xe9,0,0,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e, +0x75,0x6d,0x62,0x65,0x72,0xa7,0 }; -const char PropNameData::nameGroups[23100]={ +const char PropNameData::nameGroups[23338]={ 2,'A','l','p','h','a',0,'A','l','p','h','a','b','e','t','i','c',0, 4,'N',0,'N','o',0,'F',0,'F','a','l','s','e',0,4,'Y',0,'Y','e','s',0,'T',0,'T','r','u','e',0, 2,'N','R',0,'N','o','t','_','R','e','o','r','d','e','r','e','d',0, @@ -1176,6 +1184,10 @@ const char PropNameData::nameGroups[23100]={ 2,'R','G','I','_','E','m','o','j','i','_','Z','W','J','_','S','e','q','u','e','n','c','e',0, 'R','G','I','_','E','m','o','j','i','_','Z','W','J','_','S','e','q','u','e','n','c','e',0, 2,'R','G','I','_','E','m','o','j','i',0,'R','G','I','_','E','m','o','j','i',0, +2,'I','D','S','U',0,'I','D','S','_','U','n','a','r','y','_','O','p','e','r','a','t','o','r',0, +2,'I','D','_','C','o','m','p','a','t','_','M','a','t','h','_','S','t','a','r','t',0,'I','D','_','C','o','m','p','a','t','_', +'M','a','t','h','_','S','t','a','r','t',0,2,'I','D','_','C','o','m','p','a','t','_','M','a','t','h','_','C','o','n','t','i', +'n','u','e',0,'I','D','_','C','o','m','p','a','t','_','M','a','t','h','_','C','o','n','t','i','n','u','e',0, 2,'b','c',0,'B','i','d','i','_','C','l','a','s','s',0,2,'L',0,'L','e','f','t','_','T','o','_','R','i','g','h','t',0, 2,'R',0,'R','i','g','h','t','_','T','o','_','L','e','f','t',0, 2,'E','N',0,'E','u','r','o','p','e','a','n','_','N','u','m','b','e','r',0, @@ -1568,9 +1580,11 @@ const char PropNameData::nameGroups[23100]={ 'e','n','d','e','d','_','A',0,2,'K','a','k','t','o','v','i','k','_','N','u','m','e','r','a','l','s',0, 'K','a','k','t','o','v','i','k','_','N','u','m','e','r','a','l','s',0, 2,'K','a','w','i',0,'K','a','w','i',0,2,'N','a','g','_','M','u','n','d','a','r','i',0, -'N','a','g','_','M','u','n','d','a','r','i',0,2,'c','c','c',0,'C','a','n','o','n','i','c','a','l','_','C','o','m','b','i', -'n','i','n','g','_','C','l','a','s','s',0,2,'d','t',0,'D','e','c','o','m','p','o','s','i','t','i','o','n','_','T','y','p', -'e',0,3,'N','o','n','e',0,'N','o','n','e',0,'n','o','n','e',0, +'N','a','g','_','M','u','n','d','a','r','i',0,2,'C','J','K','_','E','x','t','_','I',0,'C','J','K','_','U','n','i','f','i', +'e','d','_','I','d','e','o','g','r','a','p','h','s','_','E','x','t','e','n','s','i','o','n','_','I',0, +2,'c','c','c',0,'C','a','n','o','n','i','c','a','l','_','C','o','m','b','i','n','i','n','g','_','C','l','a','s','s',0, +2,'d','t',0,'D','e','c','o','m','p','o','s','i','t','i','o','n','_','T','y','p','e',0, +3,'N','o','n','e',0,'N','o','n','e',0,'n','o','n','e',0, 3,'C','a','n',0,'C','a','n','o','n','i','c','a','l',0,'c','a','n',0, 3,'C','o','m',0,'C','o','m','p','a','t',0,'c','o','m',0, 3,'E','n','c',0,'C','i','r','c','l','e',0,'e','n','c',0, @@ -1739,7 +1753,11 @@ const char PropNameData::nameGroups[23100]={ 's','i','s',0,2,'C','J',0,'C','o','n','d','i','t','i','o','n','a','l','_','J','a','p','a','n','e','s','e','_','S','t','a', 'r','t','e','r',0,2,'H','L',0,'H','e','b','r','e','w','_','L','e','t','t','e','r',0, 2,'E','B',0,'E','_','B','a','s','e',0,2,'E','M',0,'E','_','M','o','d','i','f','i','e','r',0, -2,'Z','W','J',0,'Z','W','J',0,2,'n','t',0,'N','u','m','e','r','i','c','_','T','y','p','e',0, +2,'Z','W','J',0,'Z','W','J',0,2,'A','K',0,'A','k','s','a','r','a',0, +2,'A','P',0,'A','k','s','a','r','a','_','P','r','e','b','a','s','e',0, +2,'A','S',0,'A','k','s','a','r','a','_','S','t','a','r','t',0, +2,'V','F',0,'V','i','r','a','m','a','_','F','i','n','a','l',0, +2,'V','I',0,'V','i','r','a','m','a',0,2,'n','t',0,'N','u','m','e','r','i','c','_','T','y','p','e',0, 2,'N','o','n','e',0,'N','o','n','e',0,2,'D','e',0,'D','e','c','i','m','a','l',0, 2,'D','i',0,'D','i','g','i','t',0,2,'N','u',0,'N','u','m','e','r','i','c',0, 2,'s','c',0,'S','c','r','i','p','t',0,2,'Z','y','y','y',0,'C','o','m','m','o','n',0, diff --git a/thirdparty/icu4c/common/putil.cpp b/thirdparty/icu4c/common/putil.cpp index ab904af20a..ab25f3b996 100644 --- a/thirdparty/icu4c/common/putil.cpp +++ b/thirdparty/icu4c/common/putil.cpp @@ -1175,6 +1175,21 @@ uprv_tzname(int n) if (ret != nullptr && uprv_strcmp(TZDEFAULT, gTimeZoneBuffer) != 0) { int32_t tzZoneInfoTailLen = uprv_strlen(TZZONEINFOTAIL); const char *tzZoneInfoTailPtr = uprv_strstr(gTimeZoneBuffer, TZZONEINFOTAIL); + // MacOS14 has the realpath as something like + // /usr/share/zoneinfo.default/Australia/Melbourne + // which will not have "/zoneinfo/" in the path. + // Therefore if we fail, we fall back to read the link which is + // /var/db/timezone/zoneinfo/Australia/Melbourne + // We also fall back to reading the link if the realpath leads to something like + // /usr/share/zoneinfo/posixrules + if (tzZoneInfoTailPtr == nullptr || + uprv_strcmp(tzZoneInfoTailPtr + tzZoneInfoTailLen, "posixrules") == 0) { + ssize_t size = readlink(TZDEFAULT, gTimeZoneBuffer, sizeof(gTimeZoneBuffer)-1); + if (size > 0) { + gTimeZoneBuffer[size] = 0; + tzZoneInfoTailPtr = uprv_strstr(gTimeZoneBuffer, TZZONEINFOTAIL); + } + } if (tzZoneInfoTailPtr != nullptr) { tzZoneInfoTailPtr += tzZoneInfoTailLen; skipZoneIDPrefix(&tzZoneInfoTailPtr); diff --git a/thirdparty/icu4c/common/rbbi.cpp b/thirdparty/icu4c/common/rbbi.cpp index 73716ab406..599279fb72 100644 --- a/thirdparty/icu4c/common/rbbi.cpp +++ b/thirdparty/icu4c/common/rbbi.cpp @@ -1125,6 +1125,7 @@ static icu::UStack *gLanguageBreakFactories = nullptr; static const icu::UnicodeString *gEmptyString = nullptr; static icu::UInitOnce gLanguageBreakFactoriesInitOnce {}; static icu::UInitOnce gRBBIInitOnce {}; +static icu::ICULanguageBreakFactory *gICULanguageBreakFactory = nullptr; /** * Release all static memory held by breakiterator. @@ -1153,37 +1154,41 @@ static void U_CALLCONV rbbiInit() { ucln_common_registerCleanup(UCLN_COMMON_RBBI, rbbi_cleanup); } -static void U_CALLCONV initLanguageFactories() { - UErrorCode status = U_ZERO_ERROR; +static void U_CALLCONV initLanguageFactories(UErrorCode& status) { U_ASSERT(gLanguageBreakFactories == nullptr); gLanguageBreakFactories = new UStack(_deleteFactory, nullptr, status); if (gLanguageBreakFactories != nullptr && U_SUCCESS(status)) { - ICULanguageBreakFactory *builtIn = new ICULanguageBreakFactory(status); - gLanguageBreakFactories->push(builtIn, status); + LocalPointer<ICULanguageBreakFactory> factory(new ICULanguageBreakFactory(status), status); + if (U_SUCCESS(status)) { + gICULanguageBreakFactory = factory.orphan(); + gLanguageBreakFactories->push(gICULanguageBreakFactory, status); #ifdef U_LOCAL_SERVICE_HOOK - LanguageBreakFactory *extra = (LanguageBreakFactory *)uprv_svc_hook("languageBreakFactory", &status); - if (extra != nullptr) { - gLanguageBreakFactories->push(extra, status); - } + LanguageBreakFactory *extra = (LanguageBreakFactory *)uprv_svc_hook("languageBreakFactory", &status); + if (extra != nullptr) { + gLanguageBreakFactories->push(extra, status); + } #endif + } } ucln_common_registerCleanup(UCLN_COMMON_RBBI, rbbi_cleanup); } +void ensureLanguageFactories(UErrorCode& status) { + umtx_initOnce(gLanguageBreakFactoriesInitOnce, &initLanguageFactories, status); +} static const LanguageBreakEngine* -getLanguageBreakEngineFromFactory(UChar32 c) +getLanguageBreakEngineFromFactory(UChar32 c, const char* locale) { - umtx_initOnce(gLanguageBreakFactoriesInitOnce, &initLanguageFactories); - if (gLanguageBreakFactories == nullptr) { - return nullptr; - } + UErrorCode status = U_ZERO_ERROR; + ensureLanguageFactories(status); + if (U_FAILURE(status)) return nullptr; int32_t i = gLanguageBreakFactories->size(); const LanguageBreakEngine *lbe = nullptr; while (--i >= 0) { LanguageBreakFactory *factory = (LanguageBreakFactory *)(gLanguageBreakFactories->elementAt(i)); - lbe = factory->getEngineFor(c); + lbe = factory->getEngineFor(c, locale); if (lbe != nullptr) { break; } @@ -1199,7 +1204,7 @@ getLanguageBreakEngineFromFactory(UChar32 c) // //------------------------------------------------------------------------------- const LanguageBreakEngine * -RuleBasedBreakIterator::getLanguageBreakEngine(UChar32 c) { +RuleBasedBreakIterator::getLanguageBreakEngine(UChar32 c, const char* locale) { const LanguageBreakEngine *lbe = nullptr; UErrorCode status = U_ZERO_ERROR; @@ -1215,14 +1220,14 @@ RuleBasedBreakIterator::getLanguageBreakEngine(UChar32 c) { int32_t i = fLanguageBreakEngines->size(); while (--i >= 0) { lbe = (const LanguageBreakEngine *)(fLanguageBreakEngines->elementAt(i)); - if (lbe->handles(c)) { + if (lbe->handles(c, locale)) { return lbe; } } // No existing dictionary took the character. See if a factory wants to // give us a new LanguageBreakEngine for this character. - lbe = getLanguageBreakEngineFromFactory(c); + lbe = getLanguageBreakEngineFromFactory(c, locale); // If we got one, use it and push it on our stack. if (lbe != nullptr) { @@ -1259,6 +1264,18 @@ RuleBasedBreakIterator::getLanguageBreakEngine(UChar32 c) { return fUnhandledBreakEngine; } +#ifndef U_HIDE_DRAFT_API +void U_EXPORT2 RuleBasedBreakIterator::registerExternalBreakEngine( + ExternalBreakEngine* toAdopt, UErrorCode& status) { + LocalPointer<ExternalBreakEngine> engine(toAdopt, status); + if (U_FAILURE(status)) return; + ensureLanguageFactories(status); + if (U_FAILURE(status)) return; + gICULanguageBreakFactory->addExternalEngine(engine.orphan(), status); +} +#endif /* U_HIDE_DRAFT_API */ + + void RuleBasedBreakIterator::dumpCache() { fBreakCache->dumpCache(); } diff --git a/thirdparty/icu4c/common/rbbi_cache.cpp b/thirdparty/icu4c/common/rbbi_cache.cpp index 02ca555a89..f7a283f69e 100644 --- a/thirdparty/icu4c/common/rbbi_cache.cpp +++ b/thirdparty/icu4c/common/rbbi_cache.cpp @@ -158,12 +158,13 @@ void RuleBasedBreakIterator::DictionaryCache::populateDictionary(int32_t startPo // We now have a dictionary character. Get the appropriate language object // to deal with it. - const LanguageBreakEngine *lbe = fBI->getLanguageBreakEngine(c); + const LanguageBreakEngine *lbe = fBI->getLanguageBreakEngine( + c, fBI->getLocaleID(ULOC_REQUESTED_LOCALE, status)); // Ask the language object if there are any breaks. It will add them to the cache and // leave the text pointer on the other side of its range, ready to search for the next one. if (lbe != nullptr) { - foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBreaks, fBI->fIsPhraseBreaking, status); + foundBreakCount += lbe->findBreaks(text, current, rangeEnd, fBreaks, fBI->fIsPhraseBreaking, status); } // Reload the loop variables for the next go-round diff --git a/thirdparty/icu4c/common/rbbirb.cpp b/thirdparty/icu4c/common/rbbirb.cpp index 7177254ec4..92cccc1a33 100644 --- a/thirdparty/icu4c/common/rbbirb.cpp +++ b/thirdparty/icu4c/common/rbbirb.cpp @@ -66,7 +66,6 @@ RBBIRuleBuilder::RBBIRuleBuilder(const UnicodeString &rules, fForwardTable = nullptr; fRuleStatusVals = nullptr; fChainRules = false; - fLBCMNoChain = false; fLookAheadHardBreak = false; fUSetNodes = nullptr; fRuleStatusVals = nullptr; diff --git a/thirdparty/icu4c/common/rbbirb.h b/thirdparty/icu4c/common/rbbirb.h index d983a184b6..96d3aa643d 100644 --- a/thirdparty/icu4c/common/rbbirb.h +++ b/thirdparty/icu4c/common/rbbirb.h @@ -159,9 +159,6 @@ public: UBool fChainRules; // True for chained Unicode TR style rules. // False for traditional regexp rules. - UBool fLBCMNoChain; // True: suppress chaining of rules on - // chars with LineBreak property == CM. - UBool fLookAheadHardBreak; // True: Look ahead matches cause an // immediate break, no continuing for the // longest match. diff --git a/thirdparty/icu4c/common/rbbiscan.cpp b/thirdparty/icu4c/common/rbbiscan.cpp index 455ace78b8..844b063909 100644 --- a/thirdparty/icu4c/common/rbbiscan.cpp +++ b/thirdparty/icu4c/common/rbbiscan.cpp @@ -547,8 +547,6 @@ UBool RBBIRuleScanner::doParseActions(int32_t action) UnicodeString opt(fRB->fRules, fOptionStart, fScanIndex-fOptionStart); if (opt == UNICODE_STRING("chain", 5)) { fRB->fChainRules = true; - } else if (opt == UNICODE_STRING("LBCMNoChain", 11)) { - fRB->fLBCMNoChain = true; } else if (opt == UNICODE_STRING("forward", 7)) { fRB->fDefaultTree = &fRB->fForwardTree; } else if (opt == UNICODE_STRING("reverse", 7)) { diff --git a/thirdparty/icu4c/common/rbbitblb.cpp b/thirdparty/icu4c/common/rbbitblb.cpp index 0c2bcff4e5..8b40136fc7 100644 --- a/thirdparty/icu4c/common/rbbitblb.cpp +++ b/thirdparty/icu4c/common/rbbitblb.cpp @@ -458,21 +458,6 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree, RBBINode *endMarkNod // We've got a node that can end a match. - // !!LBCMNoChain implementation: If this node's val correspond to - // the Line Break $CM char class, don't chain from it. - // TODO: Remove this. !!LBCMNoChain is deprecated, and is not used - // by any of the standard ICU rules. - if (fRB->fLBCMNoChain) { - UChar32 c = this->fRB->fSetBuilder->getFirstChar(endNode->fVal); - if (c != -1) { - // c == -1 occurs with sets containing only the {eof} marker string. - ULineBreak cLBProp = (ULineBreak)u_getIntPropertyValue(c, UCHAR_LINE_BREAK); - if (cLBProp == U_LB_COMBINING_MARK) { - continue; - } - } - } - // Now iterate over the nodes that can start a match, looking for ones // with the same char class as our ending node. RBBINode *startNode; diff --git a/thirdparty/icu4c/common/ubidi_props_data.h b/thirdparty/icu4c/common/ubidi_props_data.h index 5dcd1d7c78..f85dc09675 100644 --- a/thirdparty/icu4c/common/ubidi_props_data.h +++ b/thirdparty/icu4c/common/ubidi_props_data.h @@ -9,11 +9,11 @@ #ifdef INCLUDED_FROM_UBIDI_PROPS_C -static const UVersionInfo ubidi_props_dataVersion={0xf,0,0,0}; +static const UVersionInfo ubidi_props_dataVersion={0xf,1,0,0}; -static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={0x10,0x6bc0,0x65d0,0x28,0x620,0x8cc,0x10ac0,0x10d24,0,0,0,0,0,0,0,0x6702b6}; +static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={0x10,0x6ba0,0x65b0,0x28,0x620,0x8cc,0x10ac0,0x10d24,0,0,0,0,0,0,0,0x6702b6}; -static const uint16_t ubidi_props_trieIndex[13024]={ +static const uint16_t ubidi_props_trieIndex[13008]={ 0x387,0x38f,0x397,0x39f,0x3b7,0x3bf,0x3c7,0x3cf,0x3a7,0x3af,0x3a7,0x3af,0x3a7,0x3af,0x3a7,0x3af, 0x3a7,0x3af,0x3a7,0x3af,0x3d5,0x3dd,0x3e5,0x3ed,0x3f5,0x3fd,0x3f9,0x401,0x409,0x411,0x40c,0x414, 0x3a7,0x3af,0x3a7,0x3af,0x41c,0x424,0x3a7,0x3af,0x3a7,0x3af,0x3a7,0x3af,0x42a,0x432,0x43a,0x442, @@ -38,8 +38,8 @@ static const uint16_t ubidi_props_trieIndex[13024]={ 0x7e8,0x7f0,0x7f8,0x7ff,0x806,0x80e,0x812,0x7e0,0x67c,0x67c,0x67c,0x81a,0x820,0x67c,0x67c,0x826, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x82e,0x3a7,0x3a7,0x3a7,0x836,0x3a7,0x3a7,0x3a7,0x3f5, 0x83e,0x846,0x849,0x3a7,0x851,0x67c,0x67c,0x67f,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x858,0x85e, -0x86e,0x866,0x3a7,0x3a7,0x876,0x61f,0x3a7,0x3ce,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x67c,0x835, -0x3dc,0x3a7,0x87e,0x886,0x3a7,0x88e,0x896,0x3a7,0x3a7,0x3a7,0x3a7,0x89a,0x3a7,0x3a7,0x674,0x3cd, +0x86e,0x866,0x3a7,0x3a7,0x876,0x61f,0x3a7,0x3ce,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x67c,0x87e, +0x3dc,0x3a7,0x85e,0x882,0x3a7,0x88a,0x892,0x3a7,0x3a7,0x3a7,0x3a7,0x896,0x3a7,0x3a7,0x674,0x3cd, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, @@ -96,10 +96,10 @@ static const uint16_t ubidi_props_trieIndex[13024]={ 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x87e,0x67c,0x595,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x8a1,0x3a7,0x3a7,0x8a6,0x8ae,0x3a7,0x3a7,0x5cb,0x67c,0x673,0x3a7,0x3a7,0x8b6,0x3a7,0x3a7,0x3a7, -0x8be,0x8c5,0x645,0x8cd,0x3a7,0x3a7,0x5a1,0x8d5,0x3a7,0x8dd,0x8e4,0x3a7,0x501,0x8e9,0x3a7,0x51a, -0x3a7,0x8f1,0x8f9,0x51c,0x3a7,0x8fd,0x51b,0x905,0x3a7,0x3a7,0x3a7,0x90b,0x3a7,0x3a7,0x3a7,0x912, +0x3a7,0x3a7,0x3a7,0x3a7,0x85e,0x67c,0x595,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x89d,0x3a7,0x3a7,0x8a2,0x8aa,0x3a7,0x3a7,0x5cb,0x67c,0x673,0x3a7,0x3a7,0x8b2,0x3a7,0x3a7,0x3a7, +0x8ba,0x8c1,0x645,0x8c9,0x3a7,0x3a7,0x5a1,0x8d1,0x3a7,0x8d9,0x8e0,0x3a7,0x501,0x8e5,0x3a7,0x51a, +0x3a7,0x8ed,0x8f5,0x51c,0x3a7,0x8f9,0x51b,0x901,0x3a7,0x3a7,0x3a7,0x907,0x3a7,0x3a7,0x3a7,0x90e, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, @@ -139,9 +139,9 @@ static const uint16_t ubidi_props_trieIndex[13024]={ 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x926,0x91a,0x91e,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6, -0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x92e,0x936,0x4a6,0x4a6,0x4a6,0x93b,0x93f, -0x947,0x94f,0x953,0x95b,0x4a6,0x4a6,0x4a6,0x95f,0x967,0x397,0x96f,0x977,0x3a7,0x3a7,0x3a7,0x97f, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x922,0x916,0x91a,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6, +0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x92a,0x932,0x4a6,0x4a6,0x4a6,0x937,0x93b, +0x943,0x94b,0x94f,0x957,0x4a6,0x4a6,0x4a6,0x95b,0x963,0x397,0x96b,0x973,0x3a7,0x3a7,0x3a7,0x97b, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0xe9c,0xe9c,0xedc,0xf1c,0xe9c,0xe9c,0xe9c,0xe9c,0xe9c,0xe9c,0xf54,0xf94,0xfd4,0xfe4,0x1024,0x1030, @@ -178,68 +178,68 @@ static const uint16_t ubidi_props_trieIndex[13024]={ 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd89, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x987,0x3a7,0x67c,0x67c,0x98f,0x61f,0x3a7,0x514, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x997,0x3a7,0x3a7,0x3a7,0x99e,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x983,0x3a7,0x67c,0x67c,0x98b,0x61f,0x3a7,0x514, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x993,0x3a7,0x3a7,0x3a7,0x99a,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x9a6,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, -0x9ae,0x9b2,0x43c,0x43c,0x43c,0x43c,0x9c2,0x9ba,0x43c,0x9ca,0x43c,0x43c,0x9d2,0x9d8,0x43c,0x43c, -0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x9e8,0x9e0,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, -0x43c,0x43c,0x43c,0x9f0,0x43c,0x9f8,0x4a6,0xa00,0x43c,0xa08,0xa0f,0xa15,0xa1d,0xa21,0xa29,0x43c, -0x51b,0xa31,0xa38,0xa3f,0x41e,0xa47,0x569,0x3a7,0x501,0xa4e,0x3a7,0xa54,0x41e,0xa59,0xa61,0x3a7, -0x3a7,0xa66,0x51b,0x3a7,0x3a7,0x3a7,0x836,0xa6e,0x41e,0x5a3,0x57e,0xa75,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0xa31,0xa7d,0x3a7,0x3a7,0xa85,0xa8d,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xa91,0xa99,0x3a7, -0x3a7,0xaa1,0x57e,0xaa9,0x3a7,0xaaf,0x3a7,0x3a7,0x60f,0xab7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xabc,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xac3,0xacb,0x3a7,0x3a7,0x3a7,0xace,0x57e,0xad6, -0xada,0xae2,0x3a7,0xae9,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xaf0,0x3a7,0x3a7,0xafe,0xaf8,0x3a7,0x3a7,0x3a7,0xb06,0xb0e,0x3a7,0xb12,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x5a5,0x41e,0x99e,0xb1a,0x3a7,0x3a7,0x3a7,0xb27,0xb22,0x3a7, +0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x9a2,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, +0x9aa,0x9ae,0x43c,0x43c,0x43c,0x43c,0x9be,0x9b6,0x43c,0x9c6,0x43c,0x43c,0x9ce,0x9d4,0x43c,0x43c, +0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x9e4,0x9dc,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, +0x43c,0x43c,0x43c,0x9ec,0x43c,0x9f4,0x4a6,0x9fc,0x43c,0xa04,0xa0b,0xa11,0xa19,0xa1d,0xa25,0x43c, +0x51b,0xa2d,0xa34,0xa3b,0x41e,0xa43,0x569,0x3a7,0x501,0xa4a,0x3a7,0xa50,0x41e,0xa55,0xa5d,0x3a7, +0x3a7,0xa62,0x51b,0x3a7,0x3a7,0x3a7,0x836,0xa6a,0x41e,0x5a3,0x57e,0xa71,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0xa2d,0xa79,0x3a7,0x3a7,0xa81,0xa89,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xa8d,0xa95,0x3a7, +0x3a7,0xa9d,0x57e,0xaa5,0x3a7,0xaab,0x3a7,0x3a7,0x60f,0xab3,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0xab8,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xabf,0xac7,0x3a7,0x3a7,0x3a7,0xaca,0x57e,0xad2, +0xad6,0xade,0x3a7,0xae5,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0xaec,0x3a7,0x3a7,0xafa,0xaf4,0x3a7,0x3a7,0x3a7,0xb02,0xb0a,0x3a7,0xb0e,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x5a5,0x41e,0x99a,0xb16,0x3a7,0x3a7,0x3a7,0xb23,0xb1e,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xb2f,0xb37,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xb3d, -0x3a7,0xb43,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0xb2b,0xb33,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xb39, +0x3a7,0xb3f,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0xa55,0x3a7,0xb49,0x3a7,0x3a7,0xb51,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0xa51,0x3a7,0xb45,0x3a7,0x3a7,0xb4d,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x535,0xb59,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x535,0xb55,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3f5,0xb61,0x500,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0xb69,0xb71,0xb77,0x3a7,0xb7d,0x67c,0x67c,0xb85,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x67c,0x67c,0xb8d,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xb93, -0x3a7,0xb9a,0x3a7,0xb96,0x3a7,0xb9d,0x3a7,0xba5,0xba9,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3f5,0xbb1,0x3f5,0xbb8,0xbbf,0xbc7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3f5,0xb5d,0x500,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0xb65,0xb6d,0xb73,0x3a7,0xb79,0x67c,0x67c,0xb81,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x67c,0x67c,0xb89,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xb8f, +0x3a7,0xb96,0x3a7,0xb92,0x3a7,0xb99,0x3a7,0xba1,0xba5,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3f5,0xbad,0x3f5,0xbb4,0xbbb,0xbc3,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xbcf,0xbd7,0x3a7,0x3a7,0xa55,0x3a7,0x3a7, -0x3a7,0x3a7,0xb43,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xa81,0x3a7, -0xbdc,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0xbe4,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0xbec, -0x43c,0xbf4,0xbf4,0xbfb,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, -0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x91e,0x4a6,0x4a6,0x43c, -0x43c,0x4a6,0x4a6,0xc03,0x43c,0x43c,0x43c,0x43c,0x43c,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6, -0xc0b,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x67c,0xc13,0x67c,0x67c,0x67f,0xc18,0xc1c, -0x858,0xc24,0x3c9,0x3a7,0xc2a,0x3a7,0xc2f,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x783,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xbcb,0xbd3,0x3a7,0x3a7,0xa51,0x3a7,0x3a7, +0x3a7,0x3a7,0xb3f,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xa7d,0x3a7, +0xbd8,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0xbe0,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0xbe8, +0x43c,0xbf0,0xbf0,0xbf7,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c, +0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x91a,0x4a6,0x4a6,0x43c, +0x43c,0x4a6,0x4a6,0xbff,0x43c,0x43c,0x43c,0x43c,0x43c,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6,0x4a6, +0xc07,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x43c,0x67c,0xc0f,0x67c,0x67c,0x67f,0xc14,0xc18, +0x858,0xc20,0x3c9,0x3a7,0xc26,0x3a7,0xc2b,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x783,0x3a7,0x3a7,0x3a7, 0x3a7,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c, -0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0xc37, -0x98f,0x67c,0x67c,0x67c,0xc3e,0x67c,0x67c,0xc45,0xc4d,0xc13,0x67c,0xc55,0x67c,0xc5d,0xc62,0x3a7, -0x3a7,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67f,0xc6a,0xc73,0xc77,0xc7f, -0xc6f,0x67c,0x67c,0x67c,0x67c,0xc87,0x67c,0x792,0xc8f,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0xc33, +0x98b,0x67c,0x67c,0x67c,0xc3a,0x67c,0x67c,0xc41,0xc49,0xc0f,0x67c,0xc51,0x67c,0xc59,0xc5e,0x3a7, +0x3a7,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67c,0x67f,0xc66,0xc6f,0xc73,0xc7b, +0xc6b,0x67c,0x67c,0x67c,0x67c,0xc83,0x67c,0x792,0xc8b,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xc96,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xc92,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, 0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7, -0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xc96,0xca6,0xc9e,0xc9e,0xc9e,0xca7,0xca7,0xca7, -0xca7,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0xcaf,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7, -0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7, -0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7, -0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7, -0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0xca7,0x386,0x386,0x386,0x12,0x12,0x12,0x12, +0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0x3a7,0xc92,0xca2,0xc9a,0xc9a,0xc9a,0xca3,0xca3,0xca3, +0xca3,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0x3f5,0xcab,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3, +0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3, +0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3, +0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3, +0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0xca3,0x386,0x386,0x386,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,8,7,8,9,7,0x12,0x12,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,7,7,7,8,9,0xa,0xa,4, 4,4,0xa,0xa,0x310a,0xf20a,0xa,3,6,3,6,6,2,2,2,2, @@ -551,15 +551,14 @@ static const uint16_t ubidi_props_trieIndex[13024]={ 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0,0,0,0,0xa,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0, 0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xa,0,0,0,0,0,0xa,0xa, 0,0,0,0,0,0xa,0xa,0xa,9,0xa,0xa,0xa,0xa,0,0,0, 0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a, 0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0xb1,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xa,0xa,0,0,0,0xa,0xa,0xa,0xa,0,0,0,0, +0,0,0,0,0,0,0,0xa,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, @@ -935,13 +934,13 @@ static const UBiDiProps ubidi_props_singleton={ ubidi_props_trieIndex+3612, nullptr, 3612, - 9412, + 9396, 0x1a0, 0xe9c, 0x0, 0x0, 0x110000, - 0x32dc, + 0x32cc, nullptr, 0, false, false, 0, nullptr }, { 2,2,0,0 } diff --git a/thirdparty/icu4c/common/ucase.cpp b/thirdparty/icu4c/common/ucase.cpp index 392e1266ae..4fd23fc935 100644 --- a/thirdparty/icu4c/common/ucase.cpp +++ b/thirdparty/icu4c/common/ucase.cpp @@ -317,43 +317,6 @@ ucase_addCaseClosure(UChar32 c, const USetAdder *sa) { } } -namespace { - -/** - * Add the simple case closure mapping, - * except if there is not actually an scf relationship between the two characters. - * TODO: Unicode should probably add the corresponding scf mappings. - * See https://crbug.com/v8/13377 and Unicode-internal PAG issue #23. - * If & when those scf mappings are added, we should be able to remove all of these exceptions. - */ -void addOneSimpleCaseClosure(UChar32 c, UChar32 t, const USetAdder *sa) { - switch (c) { - case 0x0390: - if (t == 0x1FD3) { return; } - break; - case 0x03B0: - if (t == 0x1FE3) { return; } - break; - case 0x1FD3: - if (t == 0x0390) { return; } - break; - case 0x1FE3: - if (t == 0x03B0) { return; } - break; - case 0xFB05: - if (t == 0xFB06) { return; } - break; - case 0xFB06: - if (t == 0xFB05) { return; } - break; - default: - break; - } - sa->add(sa->set, t); -} - -} // namespace - U_CFUNC void U_EXPORT2 ucase_addSimpleCaseClosure(UChar32 c, const USetAdder *sa) { uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); @@ -397,7 +360,7 @@ ucase_addSimpleCaseClosure(UChar32 c, const USetAdder *sa) { pe=pe0; UChar32 mapping; GET_SLOT_VALUE(excWord, idx, pe, mapping); - addOneSimpleCaseClosure(c, mapping, sa); + sa->add(sa->set, mapping); } } if(HAS_SLOT(excWord, UCASE_EXC_DELTA)) { @@ -405,7 +368,7 @@ ucase_addSimpleCaseClosure(UChar32 c, const USetAdder *sa) { int32_t delta; GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta); UChar32 mapping = (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; - addOneSimpleCaseClosure(c, mapping, sa); + sa->add(sa->set, mapping); } /* get the closure string pointer & length */ @@ -448,7 +411,7 @@ ucase_addSimpleCaseClosure(UChar32 c, const USetAdder *sa) { for(int32_t idx=0; idx<closureLength;) { UChar32 mapping; U16_NEXT_UNSAFE(closure, idx, mapping); - addOneSimpleCaseClosure(c, mapping, sa); + sa->add(sa->set, mapping); } } } diff --git a/thirdparty/icu4c/common/ucase_props_data.h b/thirdparty/icu4c/common/ucase_props_data.h index 7e6de63fb7..92b59520cc 100644 --- a/thirdparty/icu4c/common/ucase_props_data.h +++ b/thirdparty/icu4c/common/ucase_props_data.h @@ -9,9 +9,9 @@ #ifdef INCLUDED_FROM_UCASE_CPP -static const UVersionInfo ucase_props_dataVersion={0xf,0,0,0}; +static const UVersionInfo ucase_props_dataVersion={0xf,1,0,0}; -static const int32_t ucase_props_indexes[UCASE_IX_TOP]={0x10,0x76f2,0x66c8,0x683,0x172,0,0,0,0,0,0,0,0,0,0,3}; +static const int32_t ucase_props_indexes[UCASE_IX_TOP]={0x10,0x76ec,0x66c8,0x680,0x172,0,0,0,0,0,0,0,0,0,0,3}; static const uint16_t ucase_props_trieIndex[13148]={ 0x355,0x35d,0x365,0x36d,0x37b,0x383,0x38b,0x393,0x39b,0x3a3,0x3aa,0x3b2,0x3ba,0x3c2,0x3ca,0x3d2, @@ -509,9 +509,9 @@ static const uint16_t ucase_props_trieIndex[13148]={ 0x39b9,0x3a29,0x3a99,0x3b09,0x3b7b,0x3beb,0x3c5b,0x3ccb,0x3d3b,0x3dab,0x3e1b,0x3e8b,0x411,0x411,0x3ef9,0x3f79, 0x3fe9,0,0x4069,0x40e9,0xfc12,0xfc12,0xdb12,0xdb12,0x419b,4,0x4209,4,4,4,0x4259,0x42d9, 0x4349,0,0x43c9,0x4449,0xd512,0xd512,0xd512,0xd512,0x44fb,4,4,4,0x411,0x411,0x4569,0x4619, -0,0,0x46e9,0x4769,0xfc12,0xfc12,0xce12,0xce12,0,4,4,4,0x411,0x411,0x4819,0x48c9, -0x4999,0x391,0x4a19,0x4a99,0xfc12,0xfc12,0xc812,0xc812,0xfc92,4,4,4,0,0,0x4b49,0x4bc9, -0x4c39,0,0x4cb9,0x4d39,0xc012,0xc012,0xc112,0xc112,0x4deb,4,4,0,0,0,0,0, +0,0,0x46d9,0x4759,0xfc12,0xfc12,0xce12,0xce12,0,4,4,4,0x411,0x411,0x4809,0x48b9, +0x4979,0x391,0x49f9,0x4a79,0xfc12,0xfc12,0xc812,0xc812,0xfc92,4,4,4,0,0,0x4b29,0x4ba9, +0x4c19,0,0x4c99,0x4d19,0xc012,0xc012,0xc112,0xc112,0x4dcb,4,4,0,0,0,0,0, 0,0,0,0,0,0,0,4,4,4,4,4,0,0,0,0, 0,0,0,0,4,4,0,0,0,0,0,0,4,0,0,4, 0,0,4,4,4,4,4,0,0,0,0,0,0,0,0,0, @@ -525,8 +525,8 @@ static const uint16_t ucase_props_trieIndex[13148]={ 0x64,0x44,0x64,0x64,0x64,0x64,0x64,0x64,0x44,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,2, 0,0,1,2,2,2,1,1,2,2,2,1,0,2,0,0, -0,2,2,2,2,2,0,0,0,0,0,0,2,0,0x4e5a,0, -2,0,0x4e9a,0x4eda,2,2,0,1,2,2,0xe12,2,1,0,0,0, +0,2,2,2,2,2,0,0,0,0,0,0,2,0,0x4e3a,0, +2,0,0x4e7a,0x4eba,2,2,0,1,2,2,0xe12,2,1,0,0,0, 0,1,0,0,1,1,2,2,0,0,0,0,0,2,1,1, 0x21,0x21,0,0,0,0,0xf211,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0x812,0x812,0x812,0x812,0x812,0x812,0x812,0x812, @@ -541,13 +541,13 @@ static const uint16_t ucase_props_trieIndex[13148]={ 0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, 0x1812,0x1812,0x1812,0x1812,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, 0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811,0xe811, -0xe811,0xe811,0xe811,0xe811,0x92,0xff91,0x4f1a,0x4f3a,0x4f5a,0x4f79,0x4f99,0x92,0xff91,0x92,0xff91,0x92, -0xff91,0x4fba,0x4fda,0x4ffa,0x501a,1,0x92,0xff91,1,0x92,0xff91,1,1,1,1,1, -0x25,5,0x503a,0x503a,0x92,0xff91,0x92,0xff91,1,0,0,0,0,0,0,0x92, +0xe811,0xe811,0xe811,0xe811,0x92,0xff91,0x4efa,0x4f1a,0x4f3a,0x4f59,0x4f79,0x92,0xff91,0x92,0xff91,0x92, +0xff91,0x4f9a,0x4fba,0x4fda,0x4ffa,1,0x92,0xff91,1,0x92,0xff91,1,1,1,1,1, +0x25,5,0x501a,0x501a,0x92,0xff91,0x92,0xff91,1,0,0,0,0,0,0,0x92, 0xff91,0x92,0xff91,0x44,0x44,0x44,0x92,0xff91,0,0,0,0,0,0,0,0, -0,0,0,0,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059, -0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0x5059, -0x5059,0x5059,0x5059,0x5059,0x5059,0x5059,0,0x5059,0,0,0,0,0,0x5059,0,0, +0,0,0,0,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039, +0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0x5039, +0x5039,0x5039,0x5039,0x5039,0x5039,0x5039,0,0x5039,0,0,0,0,0,0x5039,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0x64,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, @@ -562,7 +562,7 @@ static const uint16_t ucase_props_trieIndex[13148]={ 0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x507a,0x50b9,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x505a,0x5099,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0,0x44,4,4,4,0, 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0,4,0x92,0xff91,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, @@ -573,11 +573,11 @@ static const uint16_t ucase_props_trieIndex[13148]={ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,1,1,0x92,0xff91, 0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -5,1,1,1,1,1,1,1,1,0x92,0xff91,0x92,0xff91,0x50fa,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,4,4,4,0x92,0xff91,0x511a,1,0, +5,1,1,1,1,1,1,1,1,0x92,0xff91,0x92,0xff91,0x50da,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,4,4,4,0x92,0xff91,0x50fa,1,0, 0x92,0xff91,0x92,0xff91,0x1811,1,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x513a,0x515a,0x517a,0x519a,0x513a,1,0x51ba,0x51da,0x51fa,0x521a,0x92,0xff91,0x92,0xff91, -0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0xe812,0x523a,0x525a,0x92,0xff91,0x92,0xff91,0, +0x92,0xff91,0x511a,0x513a,0x515a,0x517a,0x511a,1,0x519a,0x51ba,0x51da,0x51fa,0x92,0xff91,0x92,0xff91, +0x92,0xff91,0x92,0xff91,0x92,0xff91,0x92,0xff91,0xe812,0x521a,0x523a,0x92,0xff91,0x92,0xff91,0, 0,0,0,0,0x92,0xff91,0,1,0,1,0x92,0xff91,0x92,0xff91,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,5,5,5,0x92,0xff91,0,5,5,1,0,0,0,0,0, @@ -607,17 +607,17 @@ static const uint16_t ucase_props_trieIndex[13148]={ 0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0, 0,0,0,4,4,0,0x64,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0x5279,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x5259,1,1,1,1, 1,1,1,4,5,5,5,5,1,1,1,1,1,1,1,1, -1,5,4,4,0,0,0,0,0x5299,0x52c9,0x52f9,0x5329,0x5359,0x5389,0x53b9,0x53e9, -0x5419,0x5449,0x5479,0x54a9,0x54d9,0x5509,0x5539,0x5569,0x5b99,0x5bc9,0x5bf9,0x5c29,0x5c59,0x5c89,0x5cb9,0x5ce9, -0x5d19,0x5d49,0x5d79,0x5da9,0x5dd9,0x5e09,0x5e39,0x5e69,0x5e99,0x5ec9,0x5ef9,0x5f29,0x5f59,0x5f89,0x5fb9,0x5fe9, -0x6019,0x6049,0x6079,0x60a9,0x60d9,0x6109,0x6139,0x6169,0x5599,0x55c9,0x55f9,0x5629,0x5659,0x5689,0x56b9,0x56e9, -0x5719,0x5749,0x5779,0x57a9,0x57d9,0x5809,0x5839,0x5869,0x5899,0x58c9,0x58f9,0x5929,0x5959,0x5989,0x59b9,0x59e9, -0x5a19,0x5a49,0x5a79,0x5aa9,0x5ad9,0x5b09,0x5b39,0x5b69,0,0,0,0,0,4,0,0, +1,5,4,4,0,0,0,0,0x5279,0x52a9,0x52d9,0x5309,0x5339,0x5369,0x5399,0x53c9, +0x53f9,0x5429,0x5459,0x5489,0x54b9,0x54e9,0x5519,0x5549,0x5b79,0x5ba9,0x5bd9,0x5c09,0x5c39,0x5c69,0x5c99,0x5cc9, +0x5cf9,0x5d29,0x5d59,0x5d89,0x5db9,0x5de9,0x5e19,0x5e49,0x5e79,0x5ea9,0x5ed9,0x5f09,0x5f39,0x5f69,0x5f99,0x5fc9, +0x5ff9,0x6029,0x6059,0x6089,0x60b9,0x60e9,0x6119,0x6149,0x5579,0x55a9,0x55d9,0x5609,0x5639,0x5669,0x5699,0x56c9, +0x56f9,0x5729,0x5759,0x5789,0x57b9,0x57e9,0x5819,0x5849,0x5879,0x58a9,0x58d9,0x5909,0x5939,0x5969,0x5999,0x59c9, +0x59f9,0x5a29,0x5a59,0x5a89,0x5ab9,0x5ae9,0x5b19,0x5b49,0,0,0,0,0,4,0,0, 4,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x6199,0x6219,0x6299,0x6319,0x63c9,0x6479,0x6519,0, -0,0,0,0,0,0,0,0,0,0,0,0x65b9,0x6639,0x66b9,0x6739,0x67b9, +0,0,0,0,0,0,0,0,0x6179,0x61f9,0x6279,0x62f9,0x63a9,0x6459,0x64e9,0, +0,0,0,0,0,0,0,0,0,0,0,0x6589,0x6609,0x6689,0x6709,0x6789, 0,0,0,0,0,0,0x64,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,4, @@ -838,7 +838,7 @@ static const uint16_t ucase_props_trieIndex[13148]={ 0,0,0,0,0,0,0,0,0,0,0,0 }; -static const uint16_t ucase_props_exceptions[1667]={ +static const uint16_t ucase_props_exceptions[1664]={ 0xc850,0x20,2,0x130,0x131,0x4810,0x20,0x841,0x6b,1,0x212a,0x841,0x73,1,0x17f,0x5c50, 0x20,2,0x130,0x131,0x844,0x4b,1,0x212a,0x844,0x53,1,0x17f,0x806,0x3bc,0x39c,0x841, 0xe5,1,0x212b,0x8c0,1,0x2220,0x73,0x73,0x53,0x53,0x53,0x73,0x1e9e,0x844,0xc5,1, @@ -909,41 +909,40 @@ static const uint16_t ucase_props_exceptions[1667]={ 0x3b7,0x3b9,0x397,0x399,0x880,0x2220,0x3ae,0x3b9,0x389,0x399,0x389,0x345,0x880,0x2220,0x3b7,0x342, 0x397,0x342,0x397,0x342,0x880,0x3330,0x3b7,0x342,0x3b9,0x397,0x342,0x399,0x397,0x342,0x345,0xc90, 9,0x220,0x3b7,0x3b9,0x397,0x399,0x880,0x3330,0x3b9,0x308,0x300,0x399,0x308,0x300,0x399,0x308, -0x300,0x8c0,1,0x3330,0x3b9,0x308,0x301,0x399,0x308,0x301,0x399,0x308,0x301,0x390,0x880,0x2220, -0x3b9,0x342,0x399,0x342,0x399,0x342,0x880,0x3330,0x3b9,0x308,0x342,0x399,0x308,0x342,0x399,0x308, -0x342,0x880,0x3330,0x3c5,0x308,0x300,0x3a5,0x308,0x300,0x3a5,0x308,0x300,0x8c0,1,0x3330,0x3c5, -0x308,0x301,0x3a5,0x308,0x301,0x3a5,0x308,0x301,0x3b0,0x880,0x2220,0x3c1,0x313,0x3a1,0x313,0x3a1, -0x313,0x880,0x2220,0x3c5,0x342,0x3a5,0x342,0x3a5,0x342,0x880,0x3330,0x3c5,0x308,0x342,0x3a5,0x308, -0x342,0x3a5,0x308,0x342,0x880,0x2220,0x1f7c,0x3b9,0x1ffa,0x399,0x1ffa,0x345,0x890,9,0x220,0x3c9, -0x3b9,0x3a9,0x399,0x880,0x2220,0x3ce,0x3b9,0x38f,0x399,0x38f,0x345,0x880,0x2220,0x3c9,0x342,0x3a9, -0x342,0x3a9,0x342,0x880,0x3330,0x3c9,0x342,0x3b9,0x3a9,0x342,0x399,0x3a9,0x342,0x345,0xc90,9, -0x220,0x3c9,0x3b9,0x3a9,0x399,0xc50,0x1d5d,1,0x3a9,0xc50,0x20bf,1,0x4b,0xc50,0x2046,1, -0xc5,0xc10,0x29f7,0xc10,0xee6,0xc10,0x29e7,0xc10,0x2a2b,0xc10,0x2a28,0xc10,0x2a1c,0xc10,0x29fd,0xc10, -0x2a1f,0xc10,0x2a1e,0xc10,0x2a3f,0xc10,0x1c60,0x841,0xa64b,1,0x1c88,0x844,0xa64a,1,0x1c88,0xc10, -0x8a04,0xc10,0xa528,0xc10,0xa544,0xc10,0xa54f,0xc10,0xa54b,0xc10,0xa541,0xc10,0xa512,0xc10,0xa52a,0xc10, -0xa515,0x810,0x3a0,0xc10,0xa543,0xc10,0x8a38,0xc10,0x3a0,0x806,0x13a0,0x13a0,0x806,0x13a1,0x13a1,0x806, -0x13a2,0x13a2,0x806,0x13a3,0x13a3,0x806,0x13a4,0x13a4,0x806,0x13a5,0x13a5,0x806,0x13a6,0x13a6,0x806,0x13a7, -0x13a7,0x806,0x13a8,0x13a8,0x806,0x13a9,0x13a9,0x806,0x13aa,0x13aa,0x806,0x13ab,0x13ab,0x806,0x13ac,0x13ac, -0x806,0x13ad,0x13ad,0x806,0x13ae,0x13ae,0x806,0x13af,0x13af,0x806,0x13b0,0x13b0,0x806,0x13b1,0x13b1,0x806, -0x13b2,0x13b2,0x806,0x13b3,0x13b3,0x806,0x13b4,0x13b4,0x806,0x13b5,0x13b5,0x806,0x13b6,0x13b6,0x806,0x13b7, -0x13b7,0x806,0x13b8,0x13b8,0x806,0x13b9,0x13b9,0x806,0x13ba,0x13ba,0x806,0x13bb,0x13bb,0x806,0x13bc,0x13bc, -0x806,0x13bd,0x13bd,0x806,0x13be,0x13be,0x806,0x13bf,0x13bf,0x806,0x13c0,0x13c0,0x806,0x13c1,0x13c1,0x806, -0x13c2,0x13c2,0x806,0x13c3,0x13c3,0x806,0x13c4,0x13c4,0x806,0x13c5,0x13c5,0x806,0x13c6,0x13c6,0x806,0x13c7, -0x13c7,0x806,0x13c8,0x13c8,0x806,0x13c9,0x13c9,0x806,0x13ca,0x13ca,0x806,0x13cb,0x13cb,0x806,0x13cc,0x13cc, -0x806,0x13cd,0x13cd,0x806,0x13ce,0x13ce,0x806,0x13cf,0x13cf,0x806,0x13d0,0x13d0,0x806,0x13d1,0x13d1,0x806, -0x13d2,0x13d2,0x806,0x13d3,0x13d3,0x806,0x13d4,0x13d4,0x806,0x13d5,0x13d5,0x806,0x13d6,0x13d6,0x806,0x13d7, -0x13d7,0x806,0x13d8,0x13d8,0x806,0x13d9,0x13d9,0x806,0x13da,0x13da,0x806,0x13db,0x13db,0x806,0x13dc,0x13dc, -0x806,0x13dd,0x13dd,0x806,0x13de,0x13de,0x806,0x13df,0x13df,0x806,0x13e0,0x13e0,0x806,0x13e1,0x13e1,0x806, -0x13e2,0x13e2,0x806,0x13e3,0x13e3,0x806,0x13e4,0x13e4,0x806,0x13e5,0x13e5,0x806,0x13e6,0x13e6,0x806,0x13e7, -0x13e7,0x806,0x13e8,0x13e8,0x806,0x13e9,0x13e9,0x806,0x13ea,0x13ea,0x806,0x13eb,0x13eb,0x806,0x13ec,0x13ec, -0x806,0x13ed,0x13ed,0x806,0x13ee,0x13ee,0x806,0x13ef,0x13ef,0x880,0x2220,0x66,0x66,0x46,0x46,0x46, -0x66,0x880,0x2220,0x66,0x69,0x46,0x49,0x46,0x69,0x880,0x2220,0x66,0x6c,0x46,0x4c,0x46, -0x6c,0x880,0x3330,0x66,0x66,0x69,0x46,0x46,0x49,0x46,0x66,0x69,0x880,0x3330,0x66,0x66, -0x6c,0x46,0x46,0x4c,0x46,0x66,0x6c,0x8c0,1,0x2220,0x73,0x74,0x53,0x54,0x53,0x74, -0xfb06,0x8c0,1,0x2220,0x73,0x74,0x53,0x54,0x53,0x74,0xfb05,0x880,0x2220,0x574,0x576,0x544, -0x546,0x544,0x576,0x880,0x2220,0x574,0x565,0x544,0x535,0x544,0x565,0x880,0x2220,0x574,0x56b,0x544, -0x53b,0x544,0x56b,0x880,0x2220,0x57e,0x576,0x54e,0x546,0x54e,0x576,0x880,0x2220,0x574,0x56d,0x544, -0x53d,0x544,0x56d +0x300,0x882,0x390,0x3330,0x3b9,0x308,0x301,0x399,0x308,0x301,0x399,0x308,0x301,0x880,0x2220,0x3b9, +0x342,0x399,0x342,0x399,0x342,0x880,0x3330,0x3b9,0x308,0x342,0x399,0x308,0x342,0x399,0x308,0x342, +0x880,0x3330,0x3c5,0x308,0x300,0x3a5,0x308,0x300,0x3a5,0x308,0x300,0x882,0x3b0,0x3330,0x3c5,0x308, +0x301,0x3a5,0x308,0x301,0x3a5,0x308,0x301,0x880,0x2220,0x3c1,0x313,0x3a1,0x313,0x3a1,0x313,0x880, +0x2220,0x3c5,0x342,0x3a5,0x342,0x3a5,0x342,0x880,0x3330,0x3c5,0x308,0x342,0x3a5,0x308,0x342,0x3a5, +0x308,0x342,0x880,0x2220,0x1f7c,0x3b9,0x1ffa,0x399,0x1ffa,0x345,0x890,9,0x220,0x3c9,0x3b9,0x3a9, +0x399,0x880,0x2220,0x3ce,0x3b9,0x38f,0x399,0x38f,0x345,0x880,0x2220,0x3c9,0x342,0x3a9,0x342,0x3a9, +0x342,0x880,0x3330,0x3c9,0x342,0x3b9,0x3a9,0x342,0x399,0x3a9,0x342,0x345,0xc90,9,0x220,0x3c9, +0x3b9,0x3a9,0x399,0xc50,0x1d5d,1,0x3a9,0xc50,0x20bf,1,0x4b,0xc50,0x2046,1,0xc5,0xc10, +0x29f7,0xc10,0xee6,0xc10,0x29e7,0xc10,0x2a2b,0xc10,0x2a28,0xc10,0x2a1c,0xc10,0x29fd,0xc10,0x2a1f,0xc10, +0x2a1e,0xc10,0x2a3f,0xc10,0x1c60,0x841,0xa64b,1,0x1c88,0x844,0xa64a,1,0x1c88,0xc10,0x8a04,0xc10, +0xa528,0xc10,0xa544,0xc10,0xa54f,0xc10,0xa54b,0xc10,0xa541,0xc10,0xa512,0xc10,0xa52a,0xc10,0xa515,0x810, +0x3a0,0xc10,0xa543,0xc10,0x8a38,0xc10,0x3a0,0x806,0x13a0,0x13a0,0x806,0x13a1,0x13a1,0x806,0x13a2,0x13a2, +0x806,0x13a3,0x13a3,0x806,0x13a4,0x13a4,0x806,0x13a5,0x13a5,0x806,0x13a6,0x13a6,0x806,0x13a7,0x13a7,0x806, +0x13a8,0x13a8,0x806,0x13a9,0x13a9,0x806,0x13aa,0x13aa,0x806,0x13ab,0x13ab,0x806,0x13ac,0x13ac,0x806,0x13ad, +0x13ad,0x806,0x13ae,0x13ae,0x806,0x13af,0x13af,0x806,0x13b0,0x13b0,0x806,0x13b1,0x13b1,0x806,0x13b2,0x13b2, +0x806,0x13b3,0x13b3,0x806,0x13b4,0x13b4,0x806,0x13b5,0x13b5,0x806,0x13b6,0x13b6,0x806,0x13b7,0x13b7,0x806, +0x13b8,0x13b8,0x806,0x13b9,0x13b9,0x806,0x13ba,0x13ba,0x806,0x13bb,0x13bb,0x806,0x13bc,0x13bc,0x806,0x13bd, +0x13bd,0x806,0x13be,0x13be,0x806,0x13bf,0x13bf,0x806,0x13c0,0x13c0,0x806,0x13c1,0x13c1,0x806,0x13c2,0x13c2, +0x806,0x13c3,0x13c3,0x806,0x13c4,0x13c4,0x806,0x13c5,0x13c5,0x806,0x13c6,0x13c6,0x806,0x13c7,0x13c7,0x806, +0x13c8,0x13c8,0x806,0x13c9,0x13c9,0x806,0x13ca,0x13ca,0x806,0x13cb,0x13cb,0x806,0x13cc,0x13cc,0x806,0x13cd, +0x13cd,0x806,0x13ce,0x13ce,0x806,0x13cf,0x13cf,0x806,0x13d0,0x13d0,0x806,0x13d1,0x13d1,0x806,0x13d2,0x13d2, +0x806,0x13d3,0x13d3,0x806,0x13d4,0x13d4,0x806,0x13d5,0x13d5,0x806,0x13d6,0x13d6,0x806,0x13d7,0x13d7,0x806, +0x13d8,0x13d8,0x806,0x13d9,0x13d9,0x806,0x13da,0x13da,0x806,0x13db,0x13db,0x806,0x13dc,0x13dc,0x806,0x13dd, +0x13dd,0x806,0x13de,0x13de,0x806,0x13df,0x13df,0x806,0x13e0,0x13e0,0x806,0x13e1,0x13e1,0x806,0x13e2,0x13e2, +0x806,0x13e3,0x13e3,0x806,0x13e4,0x13e4,0x806,0x13e5,0x13e5,0x806,0x13e6,0x13e6,0x806,0x13e7,0x13e7,0x806, +0x13e8,0x13e8,0x806,0x13e9,0x13e9,0x806,0x13ea,0x13ea,0x806,0x13eb,0x13eb,0x806,0x13ec,0x13ec,0x806,0x13ed, +0x13ed,0x806,0x13ee,0x13ee,0x806,0x13ef,0x13ef,0x880,0x2220,0x66,0x66,0x46,0x46,0x46,0x66,0x880, +0x2220,0x66,0x69,0x46,0x49,0x46,0x69,0x880,0x2220,0x66,0x6c,0x46,0x4c,0x46,0x6c,0x880, +0x3330,0x66,0x66,0x69,0x46,0x46,0x49,0x46,0x66,0x69,0x880,0x3330,0x66,0x66,0x6c,0x46, +0x46,0x4c,0x46,0x66,0x6c,0x882,0xfb06,0x2220,0x73,0x74,0x53,0x54,0x53,0x74,0x8c0,1, +0x2220,0x73,0x74,0x53,0x54,0x53,0x74,0xfb05,0x880,0x2220,0x574,0x576,0x544,0x546,0x544,0x576, +0x880,0x2220,0x574,0x565,0x544,0x535,0x544,0x565,0x880,0x2220,0x574,0x56b,0x544,0x53b,0x544,0x56b, +0x880,0x2220,0x57e,0x576,0x54e,0x546,0x54e,0x576,0x880,0x2220,0x574,0x56d,0x544,0x53d,0x544,0x56d }; static const uint16_t ucase_props_unfold[370]={ diff --git a/thirdparty/icu4c/common/ucasemap.cpp b/thirdparty/icu4c/common/ucasemap.cpp index 1d8a8b6c2f..f6a0106aec 100644 --- a/thirdparty/icu4c/common/ucasemap.cpp +++ b/thirdparty/icu4c/common/ucasemap.cpp @@ -679,14 +679,18 @@ void toUpper(uint32_t options, // Adding one only to the final vowel in a longer sequence // (which does not occur in normal writing) would require lookahead. // Set the same flag as for preserving an existing dialytika. - if ((data & HAS_VOWEL) != 0 && (state & AFTER_VOWEL_WITH_ACCENT) != 0 && - (upper == 0x399 || upper == 0x3A5)) { - data |= HAS_DIALYTIKA; + if ((data & HAS_VOWEL) != 0 && + (state & (AFTER_VOWEL_WITH_PRECOMPOSED_ACCENT | AFTER_VOWEL_WITH_COMBINING_ACCENT)) != + 0 && + (upper == 0x399 || upper == 0x3A5)) { + data |= (state & AFTER_VOWEL_WITH_PRECOMPOSED_ACCENT) != 0 ? HAS_DIALYTIKA + : HAS_COMBINING_DIALYTIKA; } int32_t numYpogegrammeni = 0; // Map each one to a trailing, spacing, capital iota. if ((data & HAS_YPOGEGRAMMENI) != 0) { numYpogegrammeni = 1; } + const UBool hasPrecomposedAccent = (data & HAS_ACCENT) != 0; // Skip combining diacritics after this Greek letter. int32_t nextNextIndex = nextIndex; while (nextIndex < srcLength) { @@ -704,7 +708,8 @@ void toUpper(uint32_t options, } } if ((data & HAS_VOWEL_AND_ACCENT_AND_DIALYTIKA) == HAS_VOWEL_AND_ACCENT) { - nextState |= AFTER_VOWEL_WITH_ACCENT; + nextState |= hasPrecomposedAccent ? AFTER_VOWEL_WITH_PRECOMPOSED_ACCENT + : AFTER_VOWEL_WITH_COMBINING_ACCENT; } // Map according to Greek rules. UBool addTonos = false; @@ -715,7 +720,7 @@ void toUpper(uint32_t options, !isFollowedByCasedLetter(src, nextIndex, srcLength)) { // Keep disjunctive "or" with (only) a tonos. // We use the same "word boundary" conditions as for the Final_Sigma test. - if (i == nextIndex) { + if (hasPrecomposedAccent) { upper = 0x389; // Preserve the precomposed form. } else { addTonos = true; diff --git a/thirdparty/icu4c/common/ucasemap_imp.h b/thirdparty/icu4c/common/ucasemap_imp.h index 71d0e9033f..bc83c6bd78 100644 --- a/thirdparty/icu4c/common/ucasemap_imp.h +++ b/thirdparty/icu4c/common/ucasemap_imp.h @@ -263,7 +263,8 @@ static const uint32_t HAS_EITHER_DIALYTIKA = HAS_DIALYTIKA | HAS_COMBINING_DIALY // State bits. static const uint32_t AFTER_CASED = 1; -static const uint32_t AFTER_VOWEL_WITH_ACCENT = 2; +static const uint32_t AFTER_VOWEL_WITH_COMBINING_ACCENT = 2; +static const uint32_t AFTER_VOWEL_WITH_PRECOMPOSED_ACCENT = 4; uint32_t getLetterData(UChar32 c); diff --git a/thirdparty/icu4c/common/uchar_props_data.h b/thirdparty/icu4c/common/uchar_props_data.h index f4d3932574..0324223975 100644 --- a/thirdparty/icu4c/common/uchar_props_data.h +++ b/thirdparty/icu4c/common/uchar_props_data.h @@ -9,9 +9,9 @@ #ifdef INCLUDED_FROM_UCHAR_C -static const UVersionInfo dataVersion={0xf,0,0,0}; +static const UVersionInfo dataVersion={0xf,1,0,0}; -static const uint16_t propsTrie_index[23016]={ +static const uint16_t propsTrie_index[23156]={ 0x495,0x49d,0x4a5,0x4ad,0x4c5,0x4cd,0x4d5,0x4dd,0x4e5,0x4ed,0x4f3,0x4fb,0x503,0x50b,0x513,0x51b, 0x521,0x529,0x531,0x539,0x53c,0x544,0x54c,0x554,0x55c,0x564,0x560,0x568,0x570,0x578,0x57d,0x585, 0x58d,0x595,0x599,0x5a1,0x5a9,0x5b1,0x5b9,0x5c1,0x5bd,0x5c5,0x5ca,0x5d2,0x5d8,0x5e0,0x5e8,0x5f0, @@ -51,53 +51,57 @@ static const uint16_t propsTrie_index[23016]={ 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x934,0x934, -0xc2e,0x600,0xc31,0x600,0xc39,0xc3f,0xc47,0xc4f,0xc54,0x600,0x600,0xc58,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc5f,0x600,0xc66,0xc6c,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc74,0x600,0x600,0x600,0xc7c,0x600, +0xc2e,0xc35,0xc37,0x600,0xc3f,0xc45,0xc4d,0xc55,0xc5a,0x600,0x600,0xc5e,0x600,0x600,0x600,0xc64, +0xc6b,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc72,0x600,0xc79,0xc7f,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc87,0x600,0x600,0x600,0xc8f,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0xc7e,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc85,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0xc91,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc98,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0xc8c,0x600,0x600,0x600,0xc93,0xc9b,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0xc9f,0x600,0x600,0x600,0xca6,0xcae,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xca0,0x600,0x600,0xca8,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0xcb3,0xcb8,0x600,0x600,0xcc0,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcac,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcc4,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcc9,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcc7,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcaf,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcd1,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xcb2,0x600,0x600,0x600, +0x600,0x600,0x600,0xcd7,0xcdf,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xce5, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0xcb8,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0xcec,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0xcf1,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0xcc0,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0xcc5,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0xcf6,0x600,0x600,0x600,0xc32,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0xcca,0x600,0x600,0x600,0xccf,0x600,0x600,0x600,0x600,0x600,0x600, +0xcd3,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0xcfc,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0xd04,0xd0b,0xd0f,0x600,0x600,0x600,0xccb,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0xcd7,0xcde,0xce2,0x600,0x600,0x600,0xce9,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0xd1e,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0xd16,0x934,0xd26,0x9ad,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0xd2b,0xd33,0x4e5,0xd43,0xd3b,0x600,0x600,0xd4b,0xd53,0xd63,0x4e5,0xd68,0xd70,0xd76,0xd7d,0xd5b, +0xd85,0xd8d,0x600,0xd95,0xda5,0xda8,0xd9d,0xdb0,0x655,0xdb8,0xdbf,0x8f6,0x6a3,0xdcf,0xdc7,0xdd7, +0x600,0xddf,0xde7,0xdef,0x600,0xdf7,0xdff,0xe07,0xe0f,0xe17,0xe1b,0xe23,0x535,0x535,0x600,0xe2b, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0xcf7,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0xcef,0x934,0xcff,0x9ad,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0xd04,0xd0c,0x4e5,0xd1c,0xd14,0x600,0x600,0xd24,0xd2c,0xd3c,0x4e5,0xd41,0xd49,0xd4f,0xd56,0xd34, -0xd5e,0xd66,0x600,0xd6e,0xd7e,0xd81,0xd76,0xd89,0x655,0xd91,0xd98,0x8f6,0x6a3,0xda8,0xda0,0xdb0, -0x600,0xdb8,0xdc0,0xdc8,0x600,0xdd0,0xdd8,0xde0,0xde8,0xdf0,0xdf4,0xdfc,0x535,0x535,0x600,0xe04, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, @@ -115,33 +119,29 @@ static const uint16_t propsTrie_index[23016]={ 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe0c,0xe18,0xe10, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe33,0xe3f,0xe37, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20, -0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0x600,0x600,0x600,0xe30,0x600,0xcea,0xe37,0xe3c, -0x600,0x600,0x600,0xe44,0x600,0x600,0x901,0x4b5,0xe5a,0xe4a,0xe52,0x600,0x600,0xe62,0xe6a,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe6f,0x938,0x600,0xe77,0x600,0xe7d,0xe81, -0xe89,0xe91,0xe98,0xea0,0x600,0x600,0x600,0xea6,0xebe,0x4a5,0xec6,0xece,0xed3,0x916,0xeae,0xeb6, -0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20, -0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20,0xe20, +0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47, +0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0x600,0x600,0x600,0xe57,0x600,0xccc,0xe5e,0xe63, +0x600,0x600,0x600,0xe6b,0x600,0x600,0x901,0x4b5,0xe81,0xe71,0xe79,0x600,0x600,0xe89,0xe91,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe96,0x938,0x600,0xe9e,0x600,0xea4,0xea8, +0xeb0,0xeb8,0xebf,0xec7,0x600,0x600,0x600,0xecd,0xee5,0x4a5,0xeed,0xef5,0xefa,0x916,0xed5,0xedd, +0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47, +0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47,0xe47, 0x12d4,0x12d4,0x1314,0x1354,0x1394,0x13cc,0x140c,0x144c,0x1484,0x14c4,0x14f0,0x1530,0x1570,0x1580,0x15c0,0x15f4, 0x1634,0x1664,0x16a4,0x16e4,0x16f4,0x1728,0x1760,0x17a0,0x17e0,0x1820,0x1854,0x1880,0x18c0,0x18f8,0x1914,0x1954, 0xa80,0xac0,0xb00,0xb40,0xb80,0xbab,0xbeb,0xa40,0xc0e,0xa40,0xa40,0xa40,0xa40,0xc4e,0x1db,0x1db, @@ -180,132 +180,132 @@ static const uint16_t propsTrie_index[23016]={ 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0xedb,0xee2,0xeea,0x4b5,0x600,0x600,0x600,0xef2,0xf02,0xefa,0xf19,0xf0a,0xf11,0xf21,0xf25,0xf29, -0x4b5,0x4b5,0x4b5,0x4b5,0x8f6,0x600,0xf31,0xf39,0x600,0xf41,0xf49,0xf4d,0xf55,0x600,0xf5d,0x4b5, -0x58d,0x597,0xf65,0x600,0xf69,0xf71,0xf81,0xf79,0x600,0xf89,0x600,0xf90,0xfa0,0xf98,0x4b5,0x4b5, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xb88,0x902,0xfa8,0xfb8,0xfb0,0x4b5,0x4b5, -0xfc8,0xfc0,0xfcb,0xfd3,0x916,0xfdb,0x4b5,0xfe3,0xfeb,0xff3,0x4b5,0x4b5,0x600,0x1003,0x100b,0xffb, -0x101b,0x1022,0x1013,0x102a,0x1032,0x4b5,0x1042,0x103a,0x600,0x1045,0x104d,0x1055,0x105d,0x1065,0x4b5,0x4b5, -0x600,0x600,0x106d,0x4b5,0x58d,0x1075,0x535,0x107d,0x600,0x1085,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x108d,0x600,0x1095,0x4b5,0x109a,0x10a2,0x10aa,0x10b1,0xfdf,0x10b9,0xfdf,0x10c1,0xb88, -0x10d1,0x636,0x10d9,0x10c9,0x98f,0x10e1,0x10e9,0x10ef,0x1107,0x10f7,0x10ff,0x110b,0x98f,0x111b,0x1113,0x1123, -0x113b,0x112b,0x1133,0x4b5,0x1142,0x114a,0x658,0x1152,0x1162,0x1168,0x1170,0x115a,0x4b5,0x4b5,0x4b5,0x4b5, -0x600,0x1178,0x1180,0x1099,0x600,0x1188,0x1190,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x1198,0x11a0,0x4b5, -0x600,0x11a8,0x11b0,0x11b8,0x600,0x11c8,0x11c0,0x4b5,0x870,0x11d0,0x11d8,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x600,0x11e0,0x4b5,0x4b5,0x4b5,0x58d,0x535,0x11e8,0x11f8,0x11fe,0x11f0,0x4b5,0x4b5,0x120e,0x1212,0x1206, -0x122a,0x121a,0x1222,0x600,0x1238,0x1232,0x600,0x8f7,0x1248,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x1256,0x125b,0x1240,0x1250,0x126b,0x1263,0x4b5,0x4b5,0x127a,0x127e,0x1272,0x128e,0x1286,0x11c0,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x1292,0x12a2,0x12a7,0x129a,0x4b5,0x4b5,0x12af,0x12bf,0x12b7, +0xf02,0xf09,0xf11,0x4b5,0x600,0x600,0x600,0xf19,0xf29,0xf21,0xf40,0xf31,0xf38,0xf48,0xbbd,0xf50, +0x4b5,0x4b5,0x4b5,0x4b5,0x8f6,0x600,0xf58,0xf60,0x600,0xf68,0xf70,0xf74,0xf7c,0x600,0xf84,0x4b5, +0x58d,0x597,0xf8c,0x600,0xf90,0xf98,0xfa8,0xfa0,0x600,0xfb0,0x600,0xfb7,0xfc7,0xfbf,0x4b5,0x4b5, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xb88,0x902,0xfcf,0xfdf,0xfd7,0x4b5,0x4b5, +0xfef,0xfe7,0xff2,0xffa,0x916,0x1002,0x4b5,0x100a,0x1012,0x101a,0x4b5,0x4b5,0x600,0x102a,0x1032,0x1022, +0x1042,0x1049,0x103a,0x1051,0x1059,0x4b5,0x1069,0x1061,0x600,0x106c,0x1074,0x107c,0x1084,0x108c,0x4b5,0x4b5, +0x600,0x600,0x1094,0x4b5,0x58d,0x109c,0x535,0x10a4,0x600,0x10ac,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x4b5,0x4b5,0x4b5,0x10b4,0x600,0x10bc,0x4b5,0x10c1,0x10c9,0x10d1,0x10d8,0x1006,0x10e0,0x1006,0x10e8,0xb88, +0x10f8,0x636,0x1100,0x10f0,0x98f,0x1108,0x1110,0x1116,0x112e,0x111e,0x1126,0x1132,0x98f,0x1142,0x113a,0x114a, +0x1162,0x1152,0x115a,0x4b5,0x1169,0x1171,0x658,0x1179,0x1189,0x118f,0x1197,0x1181,0x4b5,0x4b5,0x4b5,0x4b5, +0x600,0x119f,0x11a7,0x10c0,0x600,0x11af,0x11b7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x11bf,0x11c7,0x4b5, +0x600,0x11cf,0x11d7,0x11df,0x600,0x11ef,0x11e7,0x4b5,0x870,0x11f7,0x11ff,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x600,0x1207,0x4b5,0x4b5,0x4b5,0x58d,0x535,0x120f,0x121f,0x1225,0x1217,0x4b5,0x4b5,0x1235,0x1239,0x122d, +0x1251,0x1241,0x1249,0x600,0x125f,0x1259,0x600,0x8f7,0x126f,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x127d,0x1282,0x1267,0x1277,0x1292,0x128a,0x4b5,0x4b5,0x12a1,0x12a5,0x1299,0x12b5,0x12ad,0x11e7,0x4b5,0x4b5, +0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x12b9,0x12c9,0x12ce,0x12c1,0x4b5,0x4b5,0x12d6,0x12e6,0x12de, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x901,0x4b5,0x4b5,0x4b5, -0x12cf,0x12d7,0x12df,0x12c7,0x600,0x600,0x600,0x600,0x600,0x600,0x12e7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x12f6,0x12fe,0x1306,0x12ee,0x600,0x600,0x600,0x600,0x600,0x600,0x130e,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0xfdf,0x600,0x600,0x12ef,0x600,0x600,0x600,0x600,0x600, +0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x1006,0x600,0x600,0x1316,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x12f7,0x12ff,0x4b5,0x4b5, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x131e,0x1326,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x11d8,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, +0x11ff,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x8f7, -0x916,0xda4,0x600,0x916,0x1307,0x130c,0x600,0x131c,0x1324,0x132c,0x1314,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x916,0xdcb,0x600,0x916,0x132e,0x1333,0x600,0x1343,0x134b,0x1353,0x133b,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x58d,0x535,0x1334,0x4b5,0x4b5,0x4b5,0x600,0x600,0x133c,0x1341,0x1347,0x4b5,0x4b5,0x134f,0x600,0x600, +0x58d,0x535,0x135b,0x4b5,0x4b5,0x4b5,0x600,0x600,0x1363,0x1368,0x136e,0x4b5,0x4b5,0x1376,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1357,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x137e,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x902,0x4b5,0x106d,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x600,0x600,0x600,0x600,0x902,0x4b5,0x1094,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x135d,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x1365,0x136a,0x1371,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe10,0x4b5, +0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x1384,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x138c,0x1391,0x1398,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xe37,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600,0x600,0x1377,0x137c,0x1384,0x4b5,0x4b5,0x4b5, +0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600,0x600,0x139e,0x13a3,0x13ab,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x55c,0x1394,0x139b,0x934,0x934,0x934,0x138c,0x4b5,0x934,0x934,0x934, -0x934,0x934,0x934,0x934,0xbb7,0x934,0x13a2,0x934,0x13a9,0x13b1,0x13b7,0x934,0xade,0x934,0x934,0x13bf, -0x4b5,0x4b5,0x4b5,0x13c7,0x13c7,0x934,0x934,0xadb,0x13cf,0x4b5,0x4b5,0x4b5,0x4b5,0x13df,0x13e6,0x13eb, -0x13f1,0x13f9,0x1401,0x1409,0x13e3,0x1411,0x1419,0x1421,0x1426,0x13f8,0x13df,0x13e6,0x13e2,0x13f1,0x142e,0x13e0, -0x1431,0x13e3,0x1439,0x1441,0x1449,0x1450,0x143c,0x1444,0x144c,0x1453,0x143f,0x145b,0x13d7,0x934,0x934,0x934, -0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x55c,0x146b,0x55c, -0x1472,0x1479,0x1463,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x55c,0x13bb,0x13c2,0x934,0x934,0x934,0x13b3,0x4b5,0x934,0x934,0x934, +0x934,0x934,0x934,0x934,0xbb7,0x934,0x13c9,0x934,0x13d0,0x13d8,0x13de,0x934,0xade,0x934,0x934,0x13e6, +0x4b5,0x4b5,0x4b5,0x13ee,0x13ee,0x934,0x934,0xadb,0x13f6,0x4b5,0x4b5,0x4b5,0x4b5,0x1406,0x140d,0x1412, +0x1418,0x1420,0x1428,0x1430,0x140a,0x1438,0x1440,0x1448,0x144d,0x141f,0x1406,0x140d,0x1409,0x1418,0x1455,0x1407, +0x1458,0x140a,0x1460,0x1468,0x1470,0x1477,0x1463,0x146b,0x1473,0x147a,0x1466,0x1482,0x13fe,0x934,0x934,0x934, +0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x55c,0x1492,0x55c, +0x1499,0x14a0,0x148a,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x1488,0x1490,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x1480,0x1498,0x9d4, -0x14a8,0x14a0,0x4b5,0x4b5,0x4b5,0x600,0x14b8,0x14b0,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0xfdf,0x14c0,0x600,0x14c8,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0xfdf,0x14d0,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x14d8,0x600,0x600,0x600, -0x600,0x600,0x600,0x14e0,0x4b5,0x58d,0x14f0,0x14e8,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x14af,0x14b7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x14a7,0x14bf,0x9d4, +0x14cf,0x14c7,0x4b5,0x4b5,0x4b5,0x600,0x14df,0x14d7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x4b5,0x1006,0x14e7,0x600,0x14ef,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x4b5,0x4b5,0x4b5,0x1006,0x14f7,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x14ff,0x600,0x600,0x600, +0x600,0x600,0x600,0x1507,0x4b5,0x58d,0x1517,0x150f,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x14f8,0x1508,0x1500,0x4b5,0x4b5,0x1518,0x1510,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x1528,0x1530,0x1538, -0x1540,0x1548,0x1550,0x4b5,0x1520,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x934,0x1558,0x934, -0x934,0xbaf,0x13a0,0x1560,0xbb7,0x1568,0x934,0x934,0x934,0x934,0xbb9,0x4b5,0x1570,0x1578,0x157c,0x1584, -0x158c,0x4b5,0x4b5,0x4b5,0x4b5,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x1594,0x934,0x934,0x934, +0x151f,0x152f,0x1527,0x4b5,0x4b5,0x153f,0x1537,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x154f,0x1557,0x155f, +0x1567,0x156f,0x1577,0x4b5,0x1547,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x934,0x157f,0x934, +0x934,0xbaf,0x13c7,0x1587,0xbb7,0x158f,0x934,0x934,0x934,0x934,0xbb9,0x4b5,0x1597,0x159f,0x15a3,0x15ab, +0x15b3,0x4b5,0x4b5,0x4b5,0x4b5,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x15bb,0x934,0x934,0x934, 0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934, -0x934,0x934,0x934,0x157d,0x159c,0x934,0x934,0x934,0x15a4,0x934,0x934,0x15ab,0x15b3,0x1558,0x934,0x15bb, -0x934,0x15c3,0x15c8,0x4b5,0x4b5,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0xbaf, -0x15d0,0x15d9,0x15dd,0x15e5,0x15d5,0x934,0x934,0x934,0x934,0x15ed,0x934,0xade,0x11bc,0x4b5,0x4b5,0x4b5, +0x934,0x934,0x934,0x15a4,0x15c3,0x934,0x934,0x934,0x15cb,0x934,0x934,0x15d2,0x15da,0x157f,0x934,0x15e2, +0x934,0x15ea,0x15ef,0x4b5,0x4b5,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0x934,0xbaf, +0x15f7,0x1600,0x1604,0x160c,0x15fc,0x934,0x934,0x934,0x934,0x1614,0x934,0xade,0x11e3,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x15f5,0x600,0x600, -0x15fc,0x600,0x600,0x600,0x1604,0x600,0x160c,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x161c,0x600,0x600, +0x1623,0x600,0x600,0x600,0x162b,0x600,0x1633,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xc90,0x600,0x600, -0x1614,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x161c,0x1624,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xca3,0x600,0x600, +0x163b,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1643,0x164b,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0xccf,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0xc32,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x162b,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1652,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1632,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1659,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x1639,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0x600,0x600,0x600,0x600,0x1660,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x4b5,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x901,0x600,0x600,0x600,0x600,0x600,0x600,0xf69,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x901,0x600,0x600,0x600,0x600,0x600,0x600,0xf90,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1641,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1668,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1649,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, -0x600,0x600,0x1651,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xf69,0x4b5, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1670,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, +0xf90,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, +0x600,0x600,0x1674,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0xf90,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x67d,0x600,0x600,0x600,0x600,0x600,0x600,0x600, 0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x1314,0x4b5, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x133b,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0x1661,0x1659,0x1659,0x1659,0x4b5,0x4b5,0x4b5,0x4b5,0x55c,0x55c,0x55c,0x55c,0x55c,0x55c,0x55c, -0x1669,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, +0x4b5,0x1684,0x167c,0x167c,0x167c,0x4b5,0x4b5,0x4b5,0x4b5,0x55c,0x55c,0x55c,0x55c,0x55c,0x55c,0x55c, +0x168c,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, -0x4b5,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0x1671,0x494,0x494,0x494,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0x4b5,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0x1694,0x494,0x494,0x494,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf,0xc,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18, 0x17,0x13,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17, @@ -765,7 +765,7 @@ static const uint16_t propsTrie_index[23016]={ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0,0,0,0,0x1b,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,6,6, +0x1b,0x1b,0x1b,0x1b,0x1b,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,6,6, 6,6,8,8,0x13,4,4,4,4,4,0x1b,0x1b,0x7ca,0xa4a,0xcca,4, 5,0x17,0x1b,0x1b,0xc,0x17,0x17,0x17,0x1b,4,5,0x54a,0x14,0x15,0x14,0x15, 0x14,0x15,0x14,0x15,0x14,0x15,0x1b,0x1b,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15, @@ -778,7 +778,7 @@ static const uint16_t propsTrie_index[23016]={ 5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,0,0x1b,0x1b,0x58b,0x5cb,0x60b,0x64b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +0,0,0,0x1b,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1b,0xa8b,0xacb,0xb0b, @@ -793,664 +793,673 @@ static const uint16_t propsTrie_index[23016]={ 5,5,5,5,5,0x705,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,0x585,5,5,0x705,5,5,5,0x7885, 5,0x605,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0x5c5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x785,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -0x5c5,5,5,5,5,5,5,5,0x685,5,0x645,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x785,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0x5c5,5,5,5,5,5,5,5, +0x685,5,0x645,5,5,5,5,5,5,5,5,5,5,5,5,5, +0x7b85,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,0x7985,0x7c5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,0x7985,0x7c5,5,5,5, +5,5,5,0x7845,5,5,5,5,5,5,5,5,0x605,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,0x7845,5,5,5,5, -5,5,5,5,0x605,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,0x685,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -0x1e45,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -0x7985,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x7a85,5, +5,5,5,5,5,0x685,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0x1e45,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x5c5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,0x5c5,5,0x745,5,0x6c5,5,5, +5,5,0x5c5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0x7985,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x7c5,5,0x7845,0xa45,0xcc5,5,5,5,5,5,5,0xf45,5,5,5, +5,5,5,5,5,5,5,5,5,5,0x7905,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x605,0x605,0x605,0x605,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,0x5c5,5,0x745,5,0x6c5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0x7c5,5,0x7845, +0xa45,0xcc5,5,5,5,5,5,5,0xf45,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0x605,0x605,0x605, +0x605,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x645, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,0x645,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0x585,5,5,5,5,5,5,5,0x585,5,5, +5,0x585,5,5,5,5,5,5,5,0x585,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0x585,5,5,5,5,5, +5,5,5,5,5,5,0x585,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0x785,0xa45,5,5,5,5, -5,5,5,5,5,5,5,5,0x585,0x5c5,0x605,5,0x5c5,5,5,5, +5,5,5,5,5,5,0x785,0xa45,5,5,5,5,5,5,5,5, +5,5,5,5,0x585,0x5c5,0x605,5,0x5c5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0x705,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x7c5,5, 5,5,5,5,5,5,5,5,5,5,5,5,0x745,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,0x705,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x785,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x1e45,5, +5,5,0x545,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0x785,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0x1e45,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,0x8005,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,0x79c5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,0x645,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 0x7885,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,0x5c5,5,5,5,5,0x5c5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0x5c5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,0x7845,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x6c5,5, -5,5,5,5,0x1e45,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x785,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -0x6c5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0x545,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,5,5,5,5, +5,0x7845,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,4,5,5,5,5,5,5,5,5,5,5,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,4,0x17,0x17,0x17, +5,5,0x6c5,5,5,5,5,5,0x1e45,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,0x6c5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,4,5,5, +5,5,5,5,5,5,5,5,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,4,0x17,0x17,0x17,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,1,2,1,2,1,2,1,2,4,4,6,6, -1,2,1,2,1,2,1,2,1,2,1,2,1,2,5,6, -7,7,7,0x17,6,6,6,6,6,6,6,6,6,6,0x17,4, -5,5,5,5,5,5,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x54a, -6,6,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0, +1,2,1,2,1,2,1,2,4,4,6,6,1,2,1,2, +1,2,1,2,1,2,1,2,1,2,5,6,7,7,7,0x17, +6,6,6,6,6,6,6,6,6,6,0x17,4,5,5,5,5, +5,5,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x54a,6,6,0x17,0x17, +0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0x1a,0x1a,0x1a,0x1a, 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, -0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,4,4,4,4,4,4,4,4, +0x1a,0x1a,0x1a,4,4,4,4,4,4,4,4,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4, +4,1,2,5,4,4,2,5,5,5,5,5,0x1a,0x1a,1,2, +1,2,1,2,1,2,1,2,1,2,1,2,2,2,1,2, +1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, +4,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2, +1,2,1,2,1,2,1,2,4,0x1a,0x1a,1,2,1,2,5, +1,2,1,2,2,2,1,2,1,2,1,2,1,2,1,2, +1,2,1,1,1,1,1,2,1,1,1,1,1,2,1,2, +1,2,1,2,1,2,1,2,1,1,1,1,2,1,2,0, +0,0,0,0,1,2,0,2,0,2,1,2,1,2,0,0, +0,0,0,0,5,5,6,5,5,5,6,5,5,5,5,6, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,8,8,6,6,8,0x1b,0x1b,0x1b,0x1b, +6,0,0,0,0x34cb,0x344b,0x3ccb,0x37cb,0x35cb,0x3fcb,0x1b,0x1b,0x19,0x1b,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0x17,0x17,0x17,0x17,0,0,0,0, +0,0,0,0,8,8,8,8,6,6,0,0,0,0,0,0, +0,0,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,8,8,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,8,8,8,8,8,8,8,8,8,8,8,8, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,5,5,5,5,5,5,0x17,0x17,0x17,5,0x17,5,5,6, +5,5,5,5,5,5,6,6,6,6,6,6,6,6,0x17,0x17, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,6,6,6,6,6,6,6,6,6,6,6,8,8, +0,0,0,0,0,0,0,0,0,0,0,0x17,8,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,4,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0x17,0x17,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, +8,8,6,6,6,6,8,8,6,6,8,8,5,5,5,5, +5,6,4,5,5,5,5,5,5,5,5,5,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,5,5,5,0,5,5,5,5, +5,5,5,5,5,6,6,6,6,6,6,8,8,6,6,8, +8,6,6,0,0,0,0,0,0,0,0,0,5,5,5,6, +5,5,5,5,5,5,5,5,6,8,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0x17,0x17,0x17,0x17,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,4,5,5,5, +5,5,5,0x1b,0x1b,0x1b,5,8,6,8,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,6,5,6,6, +6,5,5,6,6,5,5,5,5,5,6,6,5,6,5,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,4,4,1,2,5,4,4,2,5,5,5,5,5, -0x1a,0x1a,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -2,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, -1,2,1,2,4,2,2,2,2,2,2,2,2,1,2,1, -2,1,1,2,1,2,1,2,1,2,1,2,4,0x1a,0x1a,1, -2,1,2,5,1,2,1,2,2,2,1,2,1,2,1,2, -1,2,1,2,1,2,1,1,1,1,1,2,1,1,1,1, -1,2,1,2,1,2,1,2,1,2,1,2,1,1,1,1, -2,1,2,0,0,0,0,0,1,2,0,2,0,2,1,2, -1,2,0,0,0,0,0,0,5,5,6,5,5,5,6,5, -5,5,5,6,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,8,8,6,6,8, -0x1b,0x1b,0x1b,0x1b,6,0,0,0,0x34cb,0x344b,0x3ccb,0x37cb,0x35cb,0x3fcb,0x1b,0x1b, -0x19,0x1b,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0x17,0x17,0x17,0x17, -0,0,0,0,0,0,0,0,8,8,8,8,6,6,0,0, -0,0,0,0,0,0,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0,0,0,0,0,0,8,8,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,8,8,8,8,8,8,8,8, -8,8,8,8,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,5,5,5,5,5,5,0x17,0x17,0x17,5, -0x17,5,5,6,5,5,5,5,5,5,6,6,6,6,6,6, -6,6,0x17,0x17,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6, -6,6,8,8,0,0,0,0,0,0,0,0,0,0,0,0x17, -8,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,4, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0x17,0x17, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,6,8,8,6,6,6,6,8,8,6,6,8,8, -5,5,5,5,5,6,4,5,5,5,5,5,5,5,5,5, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,5,5,5,5,5,0, -5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,8, -8,6,6,8,8,6,6,0,0,0,0,0,0,0,0,0, -5,5,5,6,5,5,5,5,5,5,5,5,6,8,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0x17,0x17,0x17,0x17, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -4,5,5,5,5,5,5,0x1b,0x1b,0x1b,5,8,6,8,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -6,5,6,6,6,5,5,6,6,5,5,5,5,5,6,6, -5,6,5,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,5,5,4,0x17,0x17, -5,5,5,5,5,5,5,5,5,5,5,8,6,6,8,8, -0x17,0x17,5,4,4,8,6,0,0,0,0,0,0,0,0,0, -0,5,5,5,5,5,5,0,0,5,5,5,5,5,5,0, -0,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,0, +0,0,0,0,0,0,0,5,5,4,0x17,0x17,5,5,5,5, +5,5,5,5,5,5,5,8,6,6,8,8,0x17,0x17,5,4, +4,8,6,0,0,0,0,0,0,0,0,0,0,5,5,5, +5,5,5,0,0,5,5,5,5,5,5,0,0,5,5,5, +5,5,5,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,0,5,5,5,5,5,5,5,0,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,0x1a,4,4,4,4, -2,2,2,2,2,2,2,2,2,4,0x1a,0x1a,0,0,0,0, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -5,5,5,8,8,6,8,8,6,8,8,0x17,8,6,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, -5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, -5,5,5,5,5,5,5,0,0,0,0,5,5,5,5,5, +2,2,2,2,2,2,2,0x1a,4,4,4,4,2,2,2,2, +2,2,2,2,2,4,0x1a,0x1a,0,0,0,0,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,5,5,5,8, +8,6,8,8,6,8,8,0x17,8,6,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,0,0,0,5,5,5,5, +5,5,5,0,0,0,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, -0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, -5,5,5,5,5,5,5,5,5,5,5,0x605,5,5,5,5, -5,5,5,0x7c5,5,5,5,5,0x5c5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,0x6c5,5,0x6c5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,0x7c5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x18,5,5,5,5,5,5,5,5,5,5,5,5,5,0, -5,5,5,5,5,0,5,0,5,5,0,5,5,0,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,2,2,2,2,2,2,2,0, -0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2, -0,0,0,0,0,5,6,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, -0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0x15,0x14,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0,0,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, -0,0,0,0x1b,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -0x19,0x1b,0x1b,0x1b,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x14,0x15,0x17,0,0, -0,0,0,0,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,0x17,0x13,0x13,0x16,0x16,0x14,0x15,0x14,0x15,0x14,0x15,0x14, -0x15,0x14,0x15,0x14,0x15,0x17,0x17,0x14,0x15,0x17,0x17,0x17,0x17,0x16,0x16,0x16, -0x17,0x17,0x17,0,0x17,0x17,0x17,0x17,0x13,0x14,0x15,0x14,0x15,0x14,0x15,0x17, -0x17,0x17,0x18,0x13,0x18,0x18,0x18,0,0x17,0x19,0x17,0x17,0,0,0,0, -5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5, +0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,5,5,5,5, +5,5,5,5,5,5,5,0x605,5,5,5,5,5,5,5,0x7c5, +5,5,5,5,0x5c5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x6c5,5,0x6c5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x7c5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0x18,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5, +5,0,5,0,5,5,0,5,5,0,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,2,2,2,2,2,2,2,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0, +0,5,6,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, +0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,0x15,0x14,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0x1b, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,0x19,0x1b,0x1b,0x1b, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x14,0x15,0x17,0,0,0,0,0,0, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, +0x17,0x13,0x13,0x16,0x16,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14, +0x15,0x17,0x17,0x14,0x15,0x17,0x17,0x17,0x17,0x16,0x16,0x16,0x17,0x17,0x17,0, +0x17,0x17,0x17,0x17,0x13,0x14,0x15,0x14,0x15,0x14,0x15,0x17,0x17,0x17,0x18,0x13, +0x18,0x18,0x18,0,0x17,0x19,0x17,0x17,0,0,0,0,5,5,5,5, +5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,0,0x10,0,0,5,5,5,5,5,5, -0,0,5,5,5,5,5,5,0,0,5,5,5,5,5,5, -0,0,5,5,5,0,0,0,0x19,0x19,0x18,0x1a,0x1b,0x19,0x19,0, -0x1b,0x18,0x18,0x18,0x18,0x1b,0x1b,0,0,0,0,0,0,0,0,0, -0,0x10,0x10,0x10,0x1b,0x1b,0,0,0,0x17,0x17,0x17,0x19,0x17,0x17,0x17, -0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0x17,0x17,0x18,0x18,0x18,0x17,0x1a,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,0x14,0x18,0x15,0x18,0x14,0x15,0x17,0x14,0x15,0x17,0x17,5,5, -5,5,5,5,5,5,5,5,4,5,5,5,5,5,5,5, +5,0,0,0x10,0,0,5,5,5,5,5,5,0,0,5,5, +5,5,5,5,0,0,5,5,5,5,5,5,0,0,5,5, +5,0,0,0,0x19,0x19,0x18,0x1a,0x1b,0x19,0x19,0,0x1b,0x18,0x18,0x18, +0x18,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0x10,0x10,0x10, +0x1b,0x1b,0,0,0,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18, +0x17,0x13,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17, +0x18,0x18,0x18,0x17,0x1a,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0x14, +0x18,0x15,0x18,0x14,0x15,0x17,0x14,0x15,0x17,0x17,5,5,5,5,5,5, +5,5,5,5,4,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,4,4,5,5,5,5, -5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5, +5,5,5,5,5,5,4,4,5,5,5,5,5,5,5,5, +5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,0,5,5,0,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,0,0,0,0,0,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0x984b,0xa04b, -0xa84b,0xb04b,0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0,0,0,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x17,0x17,0,0,0,0,0x58b, -0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b, -0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0x7ca,0x7ca,0x7ca,0x7ca,0x7ca,0xcca,0x11ca,0x11ca, -0x11ca,0x11ca,0x1e4a,0x880a,0x980a,0x980a,0x980a,0x980a,0x980a,0x784a,0x984a,0x68a,0x11ca,0x344b,0x344b,0x388b, -0x3ccb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x54b,0x34cb, -0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0,0,0,0x34ca,0x344a,0x58a,0x68a,0x11ca,0x980a,0x984a,0x988a,0x68a,0x7ca,0x11ca,0x1e4a, -0x980a,0x784a,0x984a,0x68a,0x7ca,0x11ca,0x1e4a,0x980a,0x784a,0x788a,0x988a,0x7ca,0x58a,0x58a,0x58a,0x5ca, -0x5ca,0x5ca,0x5ca,0x68a,0x1b,0,0,0,0,0,0,0,0,0,0,0, +5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, +0,0,0,0,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0x984b,0xa04b,0xa84b,0xb04b,0xb84b,0x788b, +0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x17,0x17,0x17,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b, +0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b, +0x900b,0x980b,0xa00b,0xa80b,0x7ca,0x7ca,0x7ca,0x7ca,0x7ca,0xcca,0x11ca,0x11ca,0x11ca,0x11ca,0x1e4a,0x880a, +0x980a,0x980a,0x980a,0x980a,0x980a,0x784a,0x984a,0x68a,0x11ca,0x344b,0x344b,0x388b,0x3ccb,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x54b,0x34cb,0x1b,0x1b,0x1b,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0, +0x34ca,0x344a,0x58a,0x68a,0x11ca,0x980a,0x984a,0x988a,0x68a,0x7ca,0x11ca,0x1e4a,0x980a,0x784a,0x984a,0x68a, +0x7ca,0x11ca,0x1e4a,0x980a,0x784a,0x788a,0x988a,0x7ca,0x58a,0x58a,0x58a,0x5ca,0x5ca,0x5ca,0x5ca,0x68a, +0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,6,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,6,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b, -0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b, -0,0,0,0,0x58b,0x68b,0x7cb,0x11cb,0,0,0,0,0,0,0,0, -0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0x1bca,5,5,5,5,5,5,5,5,0xb80a,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0,0x17,5,5,5,5,0,0,0,0,5,5,5,5, -5,5,5,5,0x17,0x58a,0x5ca,0x7ca,0xa4a,0x1e4a,0,0,0,0,0,0, -0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,5,5,5,5,5,5,5,5,5,5,5,5, +5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +6,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b, +0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0,0,0,0, +0x58b,0x68b,0x7cb,0x11cb,0,0,0,0,0,0,0,0,0,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, -0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0,0,0,0,2,2,2,2, -2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0x17, -1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1, -2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,0,2,2,2,2,2,2,2,0,2,2,0,0,0, -1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1, -1,1,1,0,1,1,0,2,2,2,2,2,2,2,2,2, -5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -4,0,4,4,4,4,4,4,4,4,4,0,0,0,0,0, -4,4,4,4,4,4,0,4,4,4,4,4,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +5,0x1bca,5,5,5,5,5,5,5,5,0xb80a,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,5,5,0,0,0,5,0,0,5, -5,5,5,5,5,5,0,0,5,0,5,5,5,5,5,5, +5,5,5,5,5,5,6,6,6,6,6,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0,0x17,0x58b,0x5cb,0x60b,0x7cb,0xa4b,0x1e4b,0x784b,0x788b,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0x17, +5,5,5,5,0,0,0,0,5,5,5,5,5,5,5,5, +0x17,0x58a,0x5ca,0x7ca,0xa4a,0x1e4a,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,0x1b,0x1b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x7cb,0xa4b,0,0,0,0, -0,0,0,0x58b,0x5cb,0x60b,0x64b,0x64b,0x68b,0x7cb,0xa4b,0x1e4b,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, -5,5,0,0,0,0,0,0x58b,0x68b,0x7cb,0xa4b,0x1e4b,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, +0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0,0,0,0,2,2,2,2,2,2,2,2, +5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0x58b,0x7cb,0xa4b,0x1e4b,0x5cb,0x60b,0,0,0,0x17,5,5,5,5, +0,0,0,0,0,0,0,0,0,0,0,0x17,1,1,1,1, +1,1,1,1,1,1,1,0,1,1,1,1,2,2,0,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2, +2,2,2,2,2,2,0,2,2,0,0,0,1,1,1,1, +1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0, +1,1,0,2,2,2,2,2,2,2,2,2,5,5,5,5, +5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,4, +4,4,4,4,4,4,4,0,0,0,0,0,4,4,4,4, +4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,0,5,5,0,0,0,5,0,0,5,5,5,5,5, +5,5,0,0,5,0,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0x17, +0x58b,0x5cb,0x60b,0x7cb,0xa4b,0x1e4b,0x784b,0x788b,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x1b, +0x1b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x7cb,0xa4b,0,0,0,0,0,0,0,0x58b, +0x5cb,0x60b,0x64b,0x64b,0x68b,0x7cb,0xa4b,0x1e4b,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,5,5,0,0, +0,0,0,0x58b,0x68b,0x7cb,0xa4b,0x1e4b,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x58b,0x7cb, +0xa4b,0x1e4b,0x5cb,0x60b,0,0,0,0x17,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,0,0,0,0,0,0x17,0xa04b,0xa84b,0xb04b,0xb84b,0x788b,0x808b,0x888b,0x908b, +0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x78cb,0x80cb,0x88cb,0x90cb,0x98cb,0xa0cb,0xa8cb,0xb0cb,0xb8cb,0x36cb,0x354b, +0x34cb,0x348b,0x46cb,0x344b,0x4ecb,0x388b,0x3ccb,0x454b,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +0,0,0,0,0x5ecb,0x344b,5,5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b, +0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0,0,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b, +0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0x984b,0x30b,0x34b,0x38b,0x3cb,0x7cb,0xa4b,0x1e4b,0x784b, +0x344b,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x17,0,0,0,0,0,0,0,5,6,6,6,0,6,6,0, +0,0,0,0,6,6,6,6,5,5,5,5,0,5,5,5, +0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0,0,6,6,6,0, +0,0,0,6,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,0,0,0,0x17,0xa04b,0xa84b,0xb04b,0xb84b, -0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x78cb,0x80cb,0x88cb,0x90cb,0x98cb,0xa0cb,0xa8cb, -0xb0cb,0xb8cb,0x36cb,0x354b,0x34cb,0x348b,0x46cb,0x344b,0x4ecb,0x388b,0x3ccb,0x454b,5,5,5,5, +5,0x58b,0x11cb,0x17,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0,0,0,0,0x5ecb,0x344b,5,5,0x58b,0x5cb,0x60b,0x64b, -0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0,0,0x1e4b,0x800b, -0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0x984b,0x30b,0x34b,0x38b,0x3cb, -0x7cb,0xa4b,0x1e4b,0x784b,0x344b,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,5,6,6,6, -0,6,6,0,0,0,0,0,6,6,6,6,5,5,5,5, -0,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, -6,6,6,0,0,0,0,6,5,5,5,5,5,5,5,5, +5,0x58b,0x7cb,0xa4b,5,5,5,5,5,6,6,0,0,0,0,0x58b, +0x68b,0x7cb,0xa4b,0x1e4b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,0x1b,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0x58b,0x11cb,0x17,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0x58b,0x7cb,0xa4b,5,5,5,5,5,6,6,0, -0,0,0,0x58b,0x68b,0x7cb,0xa4b,0x1e4b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -0x1b,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0,0,0,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,0,0,0x58b,0x5cb,0x60b,0x64b, -0x7cb,0xa4b,0x1e4b,0x784b,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b, -0x7cb,0xa4b,0x1e4b,0x784b,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,0,0,0,0,0,0x17,0x17,0x17, -0x17,0,0,0,0,0,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b, -0x64b,0x7cb,0xa4b,0x1e4b,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,0,0,0,0,0,0,0,0x58b,0x68b, -0x7cb,0x11cb,0x1e4b,0x784b,5,5,5,5,6,6,6,6,0,0,0,0, -0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, -0,0,0,0,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0xa4b,0xccb, -0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x344b, -0x34cb,0x348b,0x388b,0,5,5,5,5,5,5,5,5,5,5,0,6, -6,0x13,0,0,5,5,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,6,6,6,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0x784b, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x7cb,0xa4b,0xccb,0x1e4b,0x344b,5, -0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6, -6,6,6,6,6,0x58b,0x7cb,0xa4b,0x1e4b,0x17,0x17,0x17,0x17,0x17,0,0, -0,0,0,0,5,5,6,6,6,6,0x17,0x17,0x17,0x17,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x784b,0x49,0x89,0xc9,0x109,0x149,0x189, -0x1c9,0x209,0x249,0x289,6,5,5,6,6,5,0,0,0,0,0,0, -0,0,0,6,8,6,8,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,6,6,6,6,6,6,6,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0,0,0,0,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb, -0xa4b,0xccb,0xf4b,0x11cb,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,8,8,8,6,6,6,6,8,8,6,6,0x17, -0x17,0x10,0x17,0x17,0x17,0x17,6,0,0,0,0,0,0,0,0,0, -0,0x10,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, -5,5,5,6,6,6,6,6,8,6,6,6,6,6,6,6, -6,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0x17,0x17, -5,8,8,5,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,5, +5,5,5,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0x784b, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, -0x17,0x17,5,0,0,0,0,0,0,0,0,0,8,5,5,5, -5,0x17,0x17,0x17,0x17,6,6,6,6,0x17,8,6,0x49,0x89,0xc9,0x109, -0x149,0x189,0x1c9,0x209,0x249,0x289,5,0x17,5,0x17,0x17,0x17,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,8, -8,8,6,6,6,6,6,6,6,6,6,8,0,0x58b,0x5cb,0x60b, -0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b, -0x784b,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,8,8,8,6,6,6,8,8, -6,8,6,6,0x17,0x17,0x17,0x17,0x17,0x17,6,5,5,6,0,0, +5,5,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17,0,0,0, +0,0,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, -5,0,5,5,5,5,0,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5, -5,0x17,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,8,8,8,6,6,6,6,6, -6,6,6,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0,0,0,0,0,0,5,5,8,8,0,0,6,6, -6,6,6,6,6,0,0,0,6,6,6,6,6,0,0,0, -0,0,0,0,0,0,0,0,6,6,8,8,0,5,5,5, -5,5,5,5,5,0,0,5,5,0,0,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5, -5,0,5,5,0,5,5,5,5,5,0,6,6,5,8,8, -6,8,8,8,8,0,0,8,8,0,0,8,8,8,0,0, -5,0,0,0,0,0,0,8,0,0,0,0,0,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,8,8,8,6,6,6,6,6,6,6,6, -8,8,6,6,6,8,6,5,5,5,5,0x17,0x17,0x17,0x17,0x17, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0,0x17,6,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -8,8,8,6,6,6,6,6,6,8,6,8,8,8,8,6, -6,8,6,6,5,5,0x17,5,0,0,0,0,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,8, -8,8,6,6,6,6,0,0,8,8,8,8,6,6,8,6, -6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5,6,6,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -8,8,8,6,6,6,6,6,6,6,6,8,8,6,8,6, -6,0x17,0x17,0x17,5,0,0,0,0,0,0,0,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0, +5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,0,0,0,0,0,0,0,0x58b,0x68b,0x7cb,0x11cb,0x1e4b,0x784b, +5,5,5,5,6,6,6,6,0,0,0,0,0,0,0,0, 0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, +0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb, +0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x344b,0x34cb,0x348b,0x388b,0, +5,5,5,5,5,5,5,5,5,5,0,6,6,0x13,0,0, +5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,6,8,6,8,8, -6,6,6,6,6,6,8,6,5,0x17,0,0,0,0,0,0, -8,8,6,6,6,6,8,6,6,6,6,6,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0xa4b,0x17,0x17,0x17,0x1b, -5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0, +0,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,0x58b,0x5cb,0x60b,0x64b,0x68b,0x7cb,0xa4b,0xccb,0x1e4b,0x344b,5,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6, +6,0x58b,0x7cb,0xa4b,0x1e4b,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0, +5,5,6,6,6,6,0x17,0x17,0x17,0x17,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,6, -6,6,6,6,6,6,6,6,8,6,6,0x17,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b, -0x16cb,0x194b,0x1bcb,0,0,0,0,0,0,0,0,0,0,0,0,5, -8,5,8,6,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, -5,5,5,5,5,5,5,0,0,5,0,0,5,5,5,5, -5,5,5,5,0,5,5,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,8,8,8,8,8,8,0,8, -8,0,0,6,6,8,6,5,6,5,0x17,5,8,0,0,0, +5,5,5,5,5,0x58b,0x5cb,0x60b,0x64b,0x7cb,0xa4b,0x1e4b,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x784b,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289, +6,5,5,6,6,5,0,0,0,0,0,0,0,0,0,6, +8,6,8,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +6,6,6,6,6,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0, +0,0,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +8,8,8,6,6,6,6,8,8,6,6,0x17,0x17,0x10,0x17,0x17, +0x17,0x17,6,0,0,0,0,0,0,0,0,0,0,0x10,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0,0,0,0,0,0,5,5,5,5,5,5,5,6, +6,6,6,6,8,6,6,6,6,6,6,6,6,0,0x49,0x89, +0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0x17,0x17,5,8,8,5, 0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,8,8,8,6,6,6,6, -0,0,6,6,8,8,8,8,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6, -6,8,5,6,6,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,6, -0,0,0,0,0,0,0,0,5,6,6,6,6,6,6,8, -8,6,6,6,5,5,5,5,5,6,6,6,6,6,6,6, -6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,0x17,0x17,0x17,0,0,0,0,0, +5,5,5,5,5,5,5,5,6,6,6,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,6,0x17,0x17,5,0, +0,0,0,0,0,0,0,0,8,5,5,5,5,0x17,0x17,0x17, +0x17,6,6,6,6,0x17,8,6,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,5,0x17,5,0x17,0x17,0x17,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,8,8,8,6,6, +6,6,6,6,6,6,6,8,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b, +0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0x784b,0,0,0, 0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6, -6,6,6,6,6,6,6,8,6,6,0x17,0x17,0x17,5,0x17,0x17, -5,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0, +5,5,5,5,8,8,8,6,6,6,8,8,6,8,6,6, +0x17,0x17,0x17,0x17,0x17,0x17,6,5,5,6,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0,0,0, -0x17,0x17,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,8,6,6,6,6, -6,6,6,0,6,6,6,6,6,6,8,6,6,6,6,6, -6,6,6,6,0,8,6,6,6,6,6,6,6,8,6,6, -8,6,6,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0,0,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,6, -0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0,0,0,0,0,0,5,5,5,5,5,5,5,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,5,0,5,5, 5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,0, -0,0,6,0,6,6,0,6,5,5,5,5,5,5,5,5, -5,5,8,8,8,8,8,0,6,6,0,8,8,6,8,6, -5,0,0,0,0,0,0,0,5,5,5,5,5,5,0,5, -5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,6,6,8,8,0x17, -0x17,0,0,0,0,0,0,0,6,8,6,0x17,0x17,0x17,0x17,0x17, -0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0,0,0,0,0,0,6,6,5,8,5,5,5,5, -5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -8,8,6,6,6,6,6,0,0,0,8,8,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x19,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x17,0xcd0b,0xcc0b,0xcb0b,0xd00b, -0xca0b,0xcf0b,0xcb4b,0xd04b,0xc90b,0x37cb,0x37cb,0x364b,0x35cb,0xc94b,0x3fcb,0x350b,0x34cb,0x344b,0x344b,0x3ccb, -0xcd0b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x19,0x19,0x34ca,0x354a,0x34ca,0x34ca, -0x344a,0x348a,0x388a,0xf4a,0x11ca,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0,0x17,0x17,0x17,0x17, -0x17,0,0,0,0,0,0,0,0,0,0,0,0x5ca,0x60a,0x64a,0x68a, -0x6ca,0x70a,0x74a,0x78a,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x64a,0x68a,0x6ca,0x70a,0x74a, -0x78a,0x58a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a,0x64a,0x68a,0x5ca, -0x60a,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a,0x60a,0x64a,0x68a,0xc08a,0xc18a, -0x58a,0x5ca,0x60a,0x60a,0x64a,0x68a,0x60a,0x60a,0x64a,0x64a,0x64a,0x64a,0x6ca,0x70a,0x70a,0x70a, -0x74a,0x74a,0x78a,0x78a,0x78a,0x78a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x58a,0x5ca,0x60a,0x64a,0x64a, -0x68a,0x68a,0x5ca,0x60a,0x58a,0x5ca,0x348a,0x388a,0x454a,0x348a,0x388a,0x35ca,5,5,5,5, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,5,0,5,5,5,5,5,5,5,5,5,5,0x17,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,8,8,8,6,6,6,6,6,6,6,6,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,5,5,8,8,0,0,6,6,6,6,6,6, +6,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0, +0,0,0,0,6,6,8,8,0,5,5,5,5,5,5,5, +5,0,0,5,5,0,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,5,5,5,5,5,5,5,0,5,5, +0,5,5,5,5,5,0,6,6,5,8,8,6,8,8,8, +8,0,0,8,8,0,0,8,8,8,0,0,5,0,0,0, +0,0,0,8,0,0,0,0,0,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,8,8,8,6,6,6,6,6,6,6,6,8,8,6,6, +6,8,6,5,5,5,5,0x17,0x17,0x17,0x17,0x17,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0x17,0x17,0,0x17,6,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,6, +6,6,6,6,6,8,6,8,8,8,8,6,6,8,6,6, +5,5,0x17,5,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,8,8,8,6,6, +6,6,0,0,8,8,8,8,6,6,8,6,6,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,5,5,5,5,6,6,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,8,8,8,6, +6,6,6,6,6,6,6,8,8,6,8,6,6,0x17,0x17,0x17, +5,0,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,0x17,0x17,0, +5,5,5,5,5,5,5,6,8,6,8,8,6,6,6,6, +6,6,8,6,5,0x17,0,0,0,0,0,0,8,8,6,6, +6,6,8,6,6,6,6,6,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0xa4b,0x17,0x17,0x17,0x1b,5,5,5,5, +5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0x10,0x10,0x10,0x10, -0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,6,5,5,5, -5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +5,5,5,5,5,5,5,5,8,8,8,6,6,6,6,6, +6,6,6,6,8,6,6,0x17,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0, +0,0,0,0,0,0,0,0,0,0,0,5,8,5,8,6, +0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, 0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, -6,6,6,6,6,0x17,0,0,0,0,0,0,0,0,0,0, +5,5,5,0,0,5,0,0,5,5,5,5,5,5,5,5, +0,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,8,8,8,8,8,8,0,8,8,0,0,6, +6,8,6,5,6,5,0x17,5,8,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,0,0,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,8,8,8,6,6,6,6,0,0,6,6, +8,8,8,8,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,6,6,6,6,6,6,8,5,6, +6,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,6,0,0,0,0, +0,0,0,0,5,6,6,6,6,6,6,8,8,6,6,6, +5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6, +6,6,6,8,6,6,0x17,0x17,0x17,5,0x17,0x17,5,0x17,0x17,0x17, +0x17,0x17,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x70b,0x74b,0x78b,0x7cb, +0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b,0,0,0,0x17,0x17,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,8,6,6,6,6,6,6,6,0, +6,6,6,6,6,6,8,6,6,6,6,6,6,6,6,6, +0,8,6,6,6,6,6,6,6,8,6,6,8,6,6,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,0,6,6,6,6,6,6, +6,6,6,6,6,6,6,6,6,6,5,6,0,0,0,0, +0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,5,5,5,5,5,5,5,0,5,5,0,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,6,6,6,6,6,6,0,0,0,6,0, +6,6,0,6,5,5,5,5,5,5,5,5,5,5,8,8, +8,8,8,0,6,6,0,8,8,6,8,6,5,0,0,0, +0,0,0,0,5,5,5,5,5,5,0,5,5,0,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,6,6,8,8,0x17,0x17,0,0,0, +0,0,0,0,6,8,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x17,0x17,0x17,0x17,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0, +0,0,0,0,6,6,5,8,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,8,8,6,6, +6,6,6,0,0,0,8,8,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x17,0xcd0b,0xcc0b,0xcb0b,0xd00b,0xca0b,0xcf0b,0xcb4b,0xd04b, +0xc90b,0x37cb,0x37cb,0x364b,0x35cb,0xc94b,0x3fcb,0x350b,0x34cb,0x344b,0x344b,0x3ccb,0xcd0b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x19,0x19,0x34ca,0x354a,0x34ca,0x34ca,0x344a,0x348a,0x388a,0xf4a, +0x11ca,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0,0x17,0x17,0x17,0x17,0x17,0,0,0, +0,0,0,0,0,0,0,0,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a, +0x60a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a, +0x64a,0x68a,0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a,0x64a,0x68a,0x5ca,0x60a,0x60a,0x64a,0x68a, +0x6ca,0x70a,0x74a,0x78a,0x58a,0x5ca,0x60a,0x60a,0x64a,0x68a,0xc08a,0xc18a,0x58a,0x5ca,0x60a,0x60a, +0x64a,0x68a,0x60a,0x60a,0x64a,0x64a,0x64a,0x64a,0x6ca,0x70a,0x70a,0x70a,0x74a,0x74a,0x78a,0x78a, +0x78a,0x78a,0x5ca,0x60a,0x64a,0x68a,0x6ca,0x58a,0x5ca,0x60a,0x64a,0x64a,0x68a,0x68a,0x5ca,0x60a, +0x58a,0x5ca,0x348a,0x388a,0x454a,0x348a,0x388a,0x35ca,5,5,5,5,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x17,0x17,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,6,5,5,5,5,5,5,6, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,0,0, +0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, +0x249,0x289,0,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0,0,6,6,6,6, +6,0x17,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6, +6,6,6,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b,0x1b,0x1b,4,4,4,4, +0x17,0x1b,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0x7cb,0x1e4b,0x788b,0x790b,0x798b,0x7a0b,0x7a8b,0,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -6,6,6,6,6,6,6,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b,0x1b,0x1b, -4,4,4,4,0x17,0x1b,0,0,0,0,0,0,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0x7cb,0x1e4b,0x788b,0x790b,0x798b, -0x7a0b,0x7a8b,0,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,0,0,0,0,0,5,5,5, -0x54b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b, -0x94b,0x98b,0x9cb,0xa0b,0x58b,0x5cb,0x60b,0x17,0x17,0x17,0x17,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,6, -5,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +5,5,5,5,0,0,0,0,0,5,5,5,0x54b,0x58b,0x5cb,0x60b, +0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b, +0x58b,0x5cb,0x60b,0x17,0x17,0x17,0x17,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,0,0,0,0,6,5,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -8,8,8,8,0,0,0,0,0,0,0,6,6,6,6,4, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,0x17,4, -6,0,0,0,0,0,0,0,0,0,0,0,8,8,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +0,0,0,0,0,0,0,6,6,6,6,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,0x17,4,6,0,0,0, +0,0,0,0,0,0,0,0,8,8,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,4,4,4,4,0,4,4,4,4,4,4,4, -0,4,4,0,5,5,5,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,5,5,5,0,0,5,0,0, -0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,0,0,0,0,0,5,5,5,5, -5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,0,0,0x1b,6,6,0x17, -0x10,0x10,0x10,0x10,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0, +4,4,4,4,0,4,4,4,4,4,4,4,0,4,4,0, +5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,5,5,0,0,5,0,0,0,0,0,0, +0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,0,0,0,0,0,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,0,0,0x1b,6,6,0x17,0x10,0x10,0x10,0x10, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,0,0, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0, -0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,8,8,6,6,6,0x1b,0x1b, -0x1b,8,8,8,8,8,8,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,6, -6,6,6,6,6,6,6,0x1b,0x1b,6,6,6,6,6,6,6, +0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6, +6,6,6,6,6,6,6,6,6,6,0,0,6,6,6,6, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0, +0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,6, -6,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x54b,0x58b,0x5cb,0x60b, -0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b, -0,0,0,0,0,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b, -0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x58b,0x5cb, -0x60b,0x64b,0x68b,0x58b,0x68b,0,0,0,0,0,0,0,0x249,0x289,0x49,0x89, -0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209, -0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,1,1,1,1, +0x1b,0x1b,0x1b,0x1b,0x1b,8,8,6,6,6,0x1b,0x1b,0x1b,8,8,8, +8,8,8,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,6,6,6,6,6, +6,6,6,0x1b,0x1b,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,6,6,0x1b,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x54b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b, +0x74b,0x78b,0x7cb,0x80b,0x84b,0x88b,0x8cb,0x90b,0x94b,0x98b,0x9cb,0xa0b,0,0,0,0, +0,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b, +0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x58b,0x5cb,0x60b,0x64b,0x68b,0x58b, +0x68b,0,0,0,0,0,0,0,0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189, +0x1c9,0x209,0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0x49,0x89, +0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, -2,0,2,2,2,2,2,2,2,2,2,2,1,1,1,1, +1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,2,2,2,2,2,2,2,0,2,2, +2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, +1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,1,0,1,1, +0,0,1,0,0,1,1,0,0,1,1,1,1,0,1,1, +1,1,1,1,1,1,2,2,2,2,0,2,0,2,2,2, +2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +2,2,2,2,1,1,0,1,1,1,1,0,0,1,1,1, +1,1,1,1,1,0,1,1,1,1,1,1,1,0,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -1,0,1,1,0,0,1,0,0,1,1,0,0,1,1,1, -1,0,1,1,1,1,1,1,1,1,2,2,2,2,0,2, -0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2, -2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,2,2,2,2,1,1,0,1,1,1,1,0, -0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1, +2,2,2,2,2,2,2,2,1,1,0,1,1,1,1,0, +1,1,1,1,1,0,1,0,0,0,1,1,1,1,1,1, 1,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,1,1,0,1, -1,1,1,0,1,1,1,1,1,0,1,0,0,0,1,1, -1,1,1,1,1,0,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,2,2,2,2,2,2,0,0,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x18,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0x18, -2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x18, +2,2,2,2,2,2,0,0,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0x18,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,0x18,2,2,2,2, +2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x18,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,0x18,2,2,2,2,2,2,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,0x18, -2,2,2,2,2,2,1,2,0,0,0x49,0x89,0xc9,0x109,0x149,0x189, -0x1c9,0x209,0x249,0x289,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6, -6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,0x1b,0x1b,0x1b,0x1b,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, -6,6,6,6,6,6,6,0,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,6,0,0,6,6,6,6,6, -2,2,2,2,2,2,2,2,2,2,5,2,2,2,2,2, -2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0, -0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -6,6,0,6,6,0,6,6,6,6,6,0,0,0,0,0, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,5,0x1b, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, -6,6,6,6,6,6,6,4,4,4,4,4,4,4,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0x19, -5,5,5,5,5,5,5,5,5,5,5,4,6,6,6,6, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0, -5,5,5,5,5,5,5,0,5,5,5,5,0,5,5,0, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, -5,5,5,5,5,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b, -6,6,6,6,6,6,6,0,0,0,0,0,0,0,0,0, -2,2,2,2,6,6,6,6,6,6,6,4,0,0,0,0, -0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0x17,0x17, -1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,0x18,2,2,2,2,2,2,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,2,2,2,0x18,2,2,2,2, +2,2,1,2,0,0,0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0x249,0x289, +0x49,0x89,0xc9,0x109,0x149,0x189,0x1c9,0x209,0,6,6,6,6,6,6,6, +6,6,6,6,6,6,6,6,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0x1b, +0x1b,0x1b,0x1b,6,6,6,6,6,6,6,6,6,6,6,6,6, +6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,6,6,6,6,6, +6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6, +6,6,6,6,6,0,0,6,6,6,6,6,2,2,2,2, +2,2,2,2,2,2,5,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0, +0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,6,6,0,6, +6,0,6,6,6,6,6,0,0,0,0,0,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,5,0x1b,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,0,0,0,6,6,6,6, +6,6,6,4,4,4,4,4,4,4,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,6,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,6,6,6,6,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0x19,5,5,5,5, +5,5,5,5,5,5,5,4,6,6,6,6,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0,0,5,5,5,5, +5,5,5,0,5,5,5,5,0,5,5,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5, +5,0,0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,6,6,6,6, +6,6,6,0,0,0,0,0,0,0,0,0,2,2,2,2, +6,6,6,6,6,6,6,4,0,0,0,0,0x49,0x89,0xc9,0x109, +0x149,0x189,0x1c9,0x209,0x249,0x289,0,0,0,0,0x17,0x17,1,1,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b, -0x78cb,0x794b,0x814b,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x1b,0x34cb,0x344b,0x3ccb, -0x19,0x58b,0x5cb,0x788b,0x78cb,0,0,0,0,0,0,0,0,0,0,0, -0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b, -0x984b,0xa04b,0xa84b,0xb04b,0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x78cb,0x80cb, -0x984b,0xa04b,0xa84b,0xb04b,0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x1b,0x5cb, -0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0x900b,0xa00b,0x804b,0x788b,0x344b,0x354b,0,0, -0,0x58b,0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b, -0x16cb,0x194b,0x1bcb,0x1e4b,0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x18,0x18,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -0,5,5,0,5,0,0,5,0,5,5,5,5,5,5,5, -5,5,5,0,5,5,5,5,0,5,0,5,0,0,0,0, -0,0,5,0,0,0,0,5,0,5,0,5,0,5,5,5, -0,5,5,0,5,0,0,5,0,5,0,5,0,5,0,5, -0,5,5,0,5,0,0,5,5,5,5,0,5,5,5,5, -5,5,5,0,5,5,5,5,0,5,5,5,5,0,5,0, -5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, -0,5,5,5,0,5,5,5,5,5,0,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, +2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x58b,0x5cb,0x60b, +0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x78cb,0x794b,0x814b,0x58b, +0x5cb,0x60b,0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x1b,0x34cb,0x344b,0x3ccb,0x19,0x58b,0x5cb,0x788b, +0x78cb,0,0,0,0,0,0,0,0,0,0,0,0x16cb,0x194b,0x1bcb,0x1e4b, +0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0x984b,0xa04b,0xa84b,0xb04b, +0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x78cb,0x80cb,0x984b,0xa04b,0xa84b,0xb04b, +0xb84b,0x788b,0x808b,0x888b,0x908b,0x988b,0xa08b,0xa88b,0xb08b,0xb88b,0x1b,0x5cb,0x60b,0x64b,0x68b,0x6cb, +0x70b,0x74b,0x78b,0x7cb,0x900b,0xa00b,0x804b,0x788b,0x344b,0x354b,0,0,0,0x58b,0x5cb,0x60b, +0x64b,0x68b,0x6cb,0x70b,0x74b,0x78b,0x7cb,0xa4b,0xccb,0xf4b,0x11cb,0x144b,0x16cb,0x194b,0x1bcb,0x1e4b, +0x800b,0x880b,0x900b,0x980b,0xa00b,0xa80b,0xb00b,0xb80b,0x784b,0x804b,0x884b,0x904b,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x18,0x18,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,0, +5,0,0,5,0,5,5,5,5,5,5,5,5,5,5,0, +5,5,5,5,0,5,0,5,0,0,0,0,0,0,5,0, +0,0,0,5,0,5,0,5,0,5,5,5,0,5,5,0, +5,0,0,5,0,5,0,5,0,5,0,5,0,5,5,0, +5,0,0,5,5,5,5,0,5,5,5,5,5,5,5,0, +5,5,5,5,0,5,5,5,5,0,5,0,5,5,5,5, +5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,0,0,0,0,5,5,5, +0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,0,0,0,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x2cb,0x2cb,0x30b,0x34b, +0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x54b,0x54b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0, +0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x2cb,0x2cb,0x30b,0x34b,0x38b,0x3cb,0x40b,0x44b,0x48b,0x4cb,0x50b,0x54b,0x54b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0x1b,0x1b,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b,0,0,0, +0x1b,0x1b,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0,0,0,0,0x1b,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0, -0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0, -0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0, -0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0, -0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x1b,0x1b,0x1b,5,0x705,5,5,5,5,5,5,5,5,5,5, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0, +0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, +5,0x705,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x645,5,5,5,5,5,5,5,5,5,5,5, +0x645,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x645,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,0x645,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0x685,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x685,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0xcc5, +5,5,5,5,5,5,5,5,0xf45,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0xf45,5,5,5,5,5,5,5, +5,5,5,5,5,5,0x6c5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,0x605,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,0xcc5,5,5,5,5,5,5,5,5,0xf45,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,0xf45,5,5,5, -5,5,5,5,5,5,5,5,5,5,0x6c5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,5,5,5,5,0x605,5,5, +5,5,5,5,5,0x605,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,5,5,5,0x605,5,5,5,5,5,5, +0x605,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x605, +5,5,5,5,5,5,5,5,5,5,5,5,5,0x645,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x605,5,5,5,5,5,5,5,5,5,5,5, +5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,0x605,5,5,5,5,5,5,5,5,5,5,5,5, -5,0x645,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x785,5,5,5,5,5,5,5,5,5,5,5, -5,5,5,5,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +0x785,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, -0x10,0x10,0x10,0x10,0,0x10,0,0,0,0,0,0,0,0,0,0, +0,0x10,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, -0x11,0x11,0,0,0,0,0,0 +0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0,0, +0,0,0,0 }; static const UTrie2 propsTrie={ @@ -1458,155 +1467,155 @@ static const UTrie2 propsTrie={ propsTrie_index+4692, nullptr, 4692, - 18324, + 18464, 0xa40, 0x12d4, 0x0, 0x0, 0x110000, - 0x59e4, + 0x5a70, nullptr, 0, false, false, 0, nullptr }; -static const uint16_t propsVectorsTrie_index[32692]={ -0x539,0x541,0x549,0x551,0x569,0x571,0x579,0x581,0x589,0x591,0x599,0x5a1,0x5a9,0x5b1,0x5b9,0x5c1, -0x5c8,0x5d0,0x5d8,0x5e0,0x5e3,0x5eb,0x5f3,0x5fb,0x603,0x60b,0x613,0x61b,0x623,0x62b,0x633,0x63b, -0x643,0x64b,0x652,0x65a,0x662,0x66a,0x672,0x67a,0x682,0x68a,0x68f,0x697,0x69e,0x6a6,0x6ae,0x6b6, -0x6be,0x6c6,0x6ce,0x6d6,0x6dd,0x6e5,0x6ed,0x6f5,0x6fd,0x705,0x70d,0x715,0x71d,0x725,0x72d,0x735, -0x1b39,0xd8a,0xe56,0x118d,0x12cc,0x1d01,0x1ea0,0x1cf9,0x13e6,0x13f6,0x13de,0x13ee,0x80a,0x810,0x818,0x820, -0x828,0x82e,0x836,0x83e,0x846,0x84c,0x854,0x85c,0x864,0x86a,0x872,0x87a,0x882,0x88a,0x892,0x899, -0x8a1,0x8a7,0x8af,0x8b7,0x8bf,0x8c5,0x8cd,0x8d5,0x8dd,0x13fe,0x8e5,0x8ed,0x8f5,0x8fc,0x904,0x90c, -0x914,0x918,0x920,0x927,0x92f,0x937,0x93f,0x947,0x1719,0x1721,0x94f,0x957,0x95f,0x967,0x96f,0x976, -0x177f,0x176f,0x1777,0x1a74,0x1a7c,0x140e,0x97e,0x1406,0x1662,0x1662,0x1664,0x1422,0x1423,0x1416,0x1418,0x141a, -0x1787,0x1789,0x986,0x1789,0x98e,0x993,0x99b,0x178e,0x9a1,0x1789,0x9a7,0x9af,0xc6a,0x1796,0x1796,0x9b7, -0x17a6,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7,0x17a7, -0x17a7,0x17a7,0x17a7,0x179e,0x9bf,0x17af,0x17af,0x9c7,0xb92,0xb9a,0xba2,0xbaa,0x17bf,0x17b7,0x9cf,0x9d7, -0x9df,0x17c9,0x17d1,0x9e7,0x17c7,0x9ef,0x1b41,0xd92,0xbb2,0xbba,0xbc2,0xbc7,0x19da,0xc91,0xc98,0x1936, -0xc42,0x1b49,0xd9a,0xda2,0xdaa,0xdb2,0xf60,0xf64,0x1a3a,0x1a3f,0xcd0,0xcd8,0x1ab0,0x1ab8,0x1c19,0xe5e, -0x1ac0,0xd1e,0xd26,0x1ac8,0x1105,0x11b5,0xf38,0xdba,0x1956,0x193e,0x194e,0x1946,0x19f2,0x19ea,0x19a6,0x1a32, -0x142b,0x142b,0x142b,0x142b,0x142e,0x142b,0x142b,0x1436,0x9f7,0x143e,0x9fb,0xa03,0x143e,0xa0b,0xa13,0xa1b, -0x144e,0x1446,0x1456,0xa23,0xa2b,0x145e,0xa33,0xa3b,0x1466,0x146e,0x1476,0x147e,0xa43,0x1486,0x148d,0x1495, -0x149d,0x14a5,0x14ad,0x14b5,0x14bd,0x14c4,0x14cc,0x14d4,0x14dc,0x14e4,0x14e7,0x14e9,0x17d9,0x18cc,0x18d2,0x1a22, -0x14f1,0xa4b,0xa53,0x1617,0x161c,0x161f,0x1625,0x14f9,0x162d,0x162d,0x1509,0x1501,0x1511,0x1519,0x1521,0x1529, -0x1531,0x1539,0x1541,0x1549,0x18da,0x192e,0x1a84,0x1be1,0x1559,0x155f,0x1567,0x156f,0x1551,0x1577,0x18e2,0x18e9, -0x17e1,0x17e1,0x17e1,0x17e1,0x17e1,0x17e1,0x17e1,0x17e1,0x18f1,0x18f1,0x18f1,0x18f1,0x18f9,0x1900,0x1902,0x1909, -0x1911,0x1915,0x1915,0x1918,0x1915,0x1915,0x191e,0x1915,0x195e,0x1a2a,0x1a8c,0xbcf,0xbd5,0x1d45,0x1d4d,0x1e2b, -0x19ca,0x19be,0x19c2,0x1a47,0x19ae,0x19ae,0x19ae,0xc52,0x19b6,0xc72,0x1a0a,0xcc0,0xc5a,0xc62,0xc62,0x1ad0, -0x19fa,0x1a94,0xca8,0xcb0,0xa5b,0x17e9,0x17e9,0xa63,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0xa6b,0x73d, -0x164a,0x166c,0xa73,0x1674,0xa7b,0x167c,0x1684,0x168c,0xa83,0xa88,0x1694,0x169b,0xa8d,0x17f9,0x1a1a,0xc4a, -0xa95,0x16f6,0x16fd,0x16a3,0x1705,0x1709,0x16ab,0x16af,0x16c8,0x16c8,0x16ca,0x16b7,0x16bf,0x16bf,0x16c0,0x1711, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801, -0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1801,0x1804,0x1966,0x1966, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2, -0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d2,0x16d9,0x1b31,0x1f0c, -0x180c,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, -0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812, -0x1812,0x1812,0x1812,0x1812,0xa9d,0x181a,0xaa5,0x1b51,0x1adc,0x1adc,0x1adc,0x1adc,0x1adc,0x1adc,0x1adc,0x1adc, -0x1ad8,0xd2e,0x1aec,0x1ae4,0x1aee,0x1b59,0x1b59,0xdc2,0x19d2,0x1a4f,0x1aa4,0x1aa8,0x1a9c,0x1c11,0xce0,0xce7, -0x1a02,0xcb8,0x1a57,0xcef,0x1af6,0x1af9,0xd36,0x1b61,0x1b09,0x1b01,0xd3e,0xdca,0x1b69,0x1b6d,0xdd2,0x100f, -0x1b11,0xd46,0xd4e,0x1b75,0x1b85,0x1b7d,0xdda,0xf08,0xe66,0xe6e,0x1d9b,0xfbf,0x1e48,0x1e48,0x1b8d,0xde2, -0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762, -0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764, -0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766, -0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761, -0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763, -0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765, -0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767, -0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762, -0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764, -0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766, -0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761, -0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763, -0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765, -0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767, -0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762, -0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764, -0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766, -0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761, -0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763, -0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765, -0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767, -0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0xaad,0xdea,0xded, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739, -0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739,0x1739, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, -0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x16e1,0x16e1,0x16e1,0x16e1,0x16e1,0x16e1,0x16e1,0x16e1, -0x16e6,0x16ee,0x1926,0x13a3,0x1a12,0x1a12,0x13a7,0x13ae,0xab5,0xabd,0xac5,0x1597,0x159e,0x15a6,0xacd,0x15ae, -0x15ec,0x15ec,0x157f,0x1587,0x15b6,0x15e3,0x15e4,0x15f4,0x15be,0x15c3,0x15cb,0x15d3,0xad5,0x15db,0xadd,0x158f, -0xcc8,0x15fc,0xae5,0xaed,0x1604,0x160a,0x160f,0xaf5,0xb05,0x1652,0x165a,0x163d,0x1642,0xb0d,0xb15,0xafd, -0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729, -0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1729,0x1731,0x1731,0x1731,0x1731, -0x1564,0x1564,0x15a4,0x15e4,0x1624,0x1664,0x16a4,0x16e4,0x1720,0x1760,0x178c,0x17cc,0x180c,0x184c,0x188c,0x18cc, -0x190c,0x1948,0x1988,0x19c8,0x1a08,0x1a3c,0x1a78,0x1ab8,0x1af8,0x1b38,0x1b74,0x1bb4,0x1bf4,0x1c34,0x1c74,0x1cb4, -0xe59,0xa80,0xac0,0xb00,0xb40,0xb6b,0xf99,0xa40,0xed9,0xa40,0xa40,0xa40,0xa40,0xbab,0x13e2,0x13e2, +static const uint16_t propsVectorsTrie_index[32764]={ +0x53e,0x546,0x54e,0x556,0x56e,0x576,0x57e,0x586,0x58e,0x596,0x59e,0x5a6,0x5ae,0x5b6,0x5be,0x5c6, +0x5cd,0x5d5,0x5dd,0x5e5,0x5e8,0x5f0,0x5f8,0x600,0x608,0x610,0x618,0x620,0x628,0x630,0x638,0x640, +0x648,0x650,0x657,0x65f,0x667,0x66f,0x677,0x67f,0x687,0x68f,0x694,0x69c,0x6a3,0x6ab,0x6b3,0x6bb, +0x6c3,0x6cb,0x6d3,0x6db,0x6e2,0x6ea,0x6f2,0x6fa,0x702,0x70a,0x712,0x71a,0x722,0x72a,0x732,0x73a, +0x1b43,0xd8f,0xe5b,0x1192,0x12d1,0x1d0b,0x1eaa,0x1d03,0x13f0,0x1400,0x13e8,0x13f8,0x80f,0x815,0x81d,0x825, +0x82d,0x833,0x83b,0x843,0x84b,0x851,0x859,0x861,0x869,0x86f,0x877,0x87f,0x887,0x88f,0x897,0x89e, +0x8a6,0x8ac,0x8b4,0x8bc,0x8c4,0x8ca,0x8d2,0x8da,0x8e2,0x1408,0x8ea,0x8f2,0x8fa,0x901,0x909,0x911, +0x919,0x91d,0x925,0x92c,0x934,0x93c,0x944,0x94c,0x1723,0x172b,0x954,0x95c,0x964,0x96c,0x974,0x97b, +0x1789,0x1779,0x1781,0x1a7e,0x1a86,0x1418,0x983,0x1410,0x166c,0x166c,0x166e,0x142c,0x142d,0x1420,0x1422,0x1424, +0x1791,0x1793,0x98b,0x1793,0x993,0x998,0x9a0,0x1798,0x9a6,0x1793,0x9ac,0x9b4,0xc6f,0x17a0,0x17a0,0x9bc, +0x17b0,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1,0x17b1, +0x17b1,0x17b1,0x17b1,0x17a8,0x9c4,0x17b9,0x17b9,0x9cc,0xb97,0xb9f,0xba7,0xbaf,0x17c9,0x17c1,0x9d4,0x9dc, +0x9e4,0x17d3,0x17db,0x9ec,0x17d1,0x9f4,0x1b4b,0xd97,0xbb7,0xbbf,0xbc7,0xbcc,0x19e4,0xc96,0xc9d,0x1940, +0xc47,0x1b53,0xd9f,0xda7,0xdaf,0xdb7,0xf65,0xf69,0x1a44,0x1a49,0xcd5,0xcdd,0x1aba,0x1ac2,0x1c23,0xe63, +0x1aca,0xd23,0xd2b,0x1ad2,0x110a,0x11ba,0xf3d,0xdbf,0x1960,0x1948,0x1958,0x1950,0x19fc,0x19f4,0x19b0,0x1a3c, +0x1435,0x1435,0x1435,0x1435,0x1438,0x1435,0x1435,0x1440,0x9fc,0x1448,0xa00,0xa08,0x1448,0xa10,0xa18,0xa20, +0x1458,0x1450,0x1460,0xa28,0xa30,0x1468,0xa38,0xa40,0x1470,0x1478,0x1480,0x1488,0xa48,0x1490,0x1497,0x149f, +0x14a7,0x14af,0x14b7,0x14bf,0x14c7,0x14ce,0x14d6,0x14de,0x14e6,0x14ee,0x14f1,0x14f3,0x17e3,0x18d6,0x18dc,0x1a2c, +0x14fb,0xa50,0xa58,0x1621,0x1626,0x1629,0x162f,0x1503,0x1637,0x1637,0x1513,0x150b,0x151b,0x1523,0x152b,0x1533, +0x153b,0x1543,0x154b,0x1553,0x18e4,0x1938,0x1a8e,0x1beb,0x1563,0x1569,0x1571,0x1579,0x155b,0x1581,0x18ec,0x18f3, +0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x18fb,0x18fb,0x18fb,0x18fb,0x1903,0x190a,0x190c,0x1913, +0x191b,0x191f,0x191f,0x1922,0x191f,0x191f,0x1928,0x191f,0x1968,0x1a34,0x1a96,0xbd4,0xbda,0x1d4f,0x1d57,0x1e35, +0x19d4,0x19c8,0x19cc,0x1a51,0x19b8,0x19b8,0x19b8,0xc57,0x19c0,0xc77,0x1a14,0xcc5,0xc5f,0xc67,0xc67,0x1ada, +0x1a04,0x1a9e,0xcad,0xcb5,0xa60,0x17f3,0x17f3,0xa68,0x17fb,0x17fb,0x17fb,0x17fb,0x17fb,0x17fb,0xa70,0x742, +0x1654,0x1676,0xa78,0x167e,0xa80,0x1686,0x168e,0x1696,0xa88,0xa8d,0x169e,0x16a5,0xa92,0x1803,0x1a24,0xc4f, +0xa9a,0x1700,0x1707,0x16ad,0x170f,0x1713,0x16b5,0x16b9,0x16d2,0x16d2,0x16d4,0x16c1,0x16c9,0x16c9,0x16ca,0x171b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b, +0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180b,0x180e,0x1970,0x1970, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc, +0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16dc,0x16e3,0x1b3b,0x1f16, +0x1816,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c, +0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c,0x181c, +0x181c,0x181c,0x181c,0x181c,0xaa2,0x1824,0xaaa,0x1b5b,0x1ae6,0x1ae6,0x1ae6,0x1ae6,0x1ae6,0x1ae6,0x1ae6,0x1ae6, +0x1ae2,0xd33,0x1af6,0x1aee,0x1af8,0x1b63,0x1b63,0xdc7,0x19dc,0x1a59,0x1aae,0x1ab2,0x1aa6,0x1c1b,0xce5,0xcec, +0x1a0c,0xcbd,0x1a61,0xcf4,0x1b00,0x1b03,0xd3b,0x1b6b,0x1b13,0x1b0b,0xd43,0xdcf,0x1b73,0x1b77,0xdd7,0x1014, +0x1b1b,0xd4b,0xd53,0x1b7f,0x1b8f,0x1b87,0xddf,0xf0d,0xe6b,0xe73,0x1da5,0xfc4,0x1e52,0x1e52,0x1b97,0xde7, +0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c, +0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e, +0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770, +0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b, +0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d, +0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f, +0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771, +0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c, +0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e, +0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770, +0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b, +0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d, +0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f, +0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771, +0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c, +0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e, +0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770, +0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b, +0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d, +0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f, +0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771, +0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0x1771,0x176b,0x176c,0x176d,0x176e,0x176f,0x1770,0xab2,0xdef,0xdf2, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743, +0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743,0x1743, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f, +0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x163f,0x16eb,0x16eb,0x16eb,0x16eb,0x16eb,0x16eb,0x16eb,0x16eb, +0x16f0,0x16f8,0x1930,0x139d,0x1a1c,0x1a1c,0x13a1,0x13a8,0xaba,0xac2,0xaca,0x15a1,0x15a8,0x15b0,0xad2,0x15b8, +0x15f6,0x15f6,0x1589,0x1591,0x15c0,0x15ed,0x15ee,0x15fe,0x15c8,0x15cd,0x15d5,0x15dd,0xada,0x15e5,0xae2,0x1599, +0xccd,0x1606,0xaea,0xaf2,0x160e,0x1614,0x1619,0xafa,0xb0a,0x165c,0x1664,0x1647,0x164c,0xb12,0xb1a,0xb02, +0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733, +0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x1733,0x173b,0x173b,0x173b,0x173b, +0x1578,0x1578,0x15b8,0x15f8,0x1638,0x1678,0x16b8,0x16f8,0x1734,0x1774,0x17a0,0x17e0,0x1820,0x1860,0x18a0,0x18e0, +0x1920,0x195c,0x199c,0x19dc,0x1a1c,0x1a50,0x1a8c,0x1acc,0x1b0c,0x1b4c,0x1b88,0x1bc8,0x1c08,0x1c48,0x1c88,0x1cc8, +0xe59,0xa80,0xac0,0xb00,0xb40,0xb6b,0xf99,0xa40,0xed9,0xa40,0xa40,0xa40,0xa40,0xbab,0x13f5,0x13f5, 0xf19,0xfd9,0xa40,0xa40,0xa40,0xbeb,0xf59,0xc2b,0xa40,0xc51,0xc91,0xcd1,0xd11,0xd51,0xe99,0xdc9, -0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322,0x1322, -0x1322,0x1322,0x1322,0x1322,0x1019,0x1362,0x1157,0x1197,0x13a2,0x11a2,0x1422,0x1422,0x1422,0x1059,0x1079,0x10b9, -0x1462,0x1462,0x11e2,0x14a2,0x10f9,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079, -0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1079,0x1117, +0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335,0x1335, +0x1335,0x1335,0x1335,0x1335,0x1019,0x1375,0x116a,0x11aa,0x13b5,0x11b5,0x1435,0x1435,0x1435,0x1059,0x108c,0x10cc, +0x1475,0x1475,0x11f5,0x14b5,0x110c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c, +0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x108c,0x112a, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, @@ -1629,1954 +1638,1958 @@ static const uint16_t propsVectorsTrie_index[32692]={ 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, 0xe09,0xe19,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40, 0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xa40,0xd89, -0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2, -0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x1222, -0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2, -0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x12e2,0x1262, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0xc27,0xc2a,0xdf5,0x1deb,0x1017,0x745,0x559,0x10b1,0xcf7,0xd76,0x559,0x559,0x1d11,0xf10,0xf18,0x1e33, -0xc7a,0xc81,0xc89,0x1b95,0x1dcb,0x559,0x1dab,0xfe7,0x1b9d,0xdfd,0xe05,0xe0d,0x103f,0x74d,0x559,0x559, -0x1ba5,0x1ba5,0x755,0x559,0x1e60,0x10c9,0x1e58,0x10d1,0x1f4c,0x11cb,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0xe15,0x1fa4,0x12c4,0x1346,0x1347,0x1f6c,0x11f3,0x11fa,0x1201,0x1303,0x1307,0x127b,0x1211, -0x1c21,0x1c23,0xe76,0xe7d,0x1bad,0x1bb5,0xe1d,0xf30,0x1d09,0xef8,0xf00,0xfdf,0x1d29,0x1d2d,0x1d35,0x105f, -0xfaf,0x1d8b,0x75d,0x559,0x10b9,0x10c1,0x1d93,0xfb7,0xf91,0xf97,0xf9f,0xfa7,0x559,0x559,0x559,0x559, -0x1ed0,0x1ec8,0x113b,0x1143,0x1e13,0x1e0b,0x1087,0x559,0x559,0x559,0x559,0x559,0x1dfb,0x1047,0x104f,0x1057, -0x1dc3,0x1dbb,0xff7,0x1133,0x1d3d,0xf40,0x765,0x559,0x1097,0x109f,0x76d,0x559,0x559,0x559,0x559,0x559, -0x1f44,0x11ad,0x775,0x559,0x559,0x1e23,0x1e1b,0x108f,0x1283,0x1289,0x1291,0x559,0x559,0x1219,0x121d,0x1225, -0x1f04,0x1efc,0x1195,0x1ef4,0x1eec,0x1185,0x1df3,0x1037,0x1357,0x135a,0x135a,0x559,0x559,0x559,0x559,0x559, -0x10e9,0x10ee,0x10f6,0x10fd,0x1125,0x112b,0x559,0x559,0x1169,0x116d,0x1175,0x11bd,0x11c3,0x77d,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x11db,0x136a,0x136f,0x1377,0x559,0x559,0x781,0x1f8c,0x126b, -0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f, -0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a5f,0x1a64,0xcff,0xd06,0xd06,0xd06, -0x1a6c,0x1a6c,0x1a6c,0xd0e,0x1e50,0x1e50,0x1e50,0x1e50,0x1e50,0x1e50,0x789,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x78d,0x1fbc,0x1fbc,0x12d4,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b, -0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0x1c2b,0xe85,0xfff,0x1007,0x1fc4, -0x130f,0x1317,0xf48,0x1de3,0x1ddb,0x1027,0x102f,0x795,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x1f64,0x1f5c,0x11eb, -0x559,0x559,0x559,0x1d21,0x1d21,0xf20,0x1d19,0xf28,0x559,0x559,0x111d,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x799,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x1d73,0x1d73,0x1d73,0xf6c,0xf71, -0x7a1,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x1fd4,0x1337,0x133e,0x1fcc,0x1fcc,0x1fcc,0x7a9, -0x559,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0xb2b,0x184f,0xb33,0x1850,0x1847,0x1858,0x185e,0x1866, -0xb3b,0x198e,0x198e,0x7b1,0x559,0x559,0x559,0x1362,0x11e3,0x197e,0x197e,0xc32,0xd16,0x559,0x559,0x559, -0x559,0x1897,0x189e,0xb43,0x18a1,0xb4b,0xb53,0xb5b,0x189b,0xb63,0xb6b,0xb73,0x18a0,0x18a8,0x1897,0x189e, -0x189a,0x18a1,0x18a9,0x1898,0x189f,0x189b,0xb7a,0x186e,0x1876,0x187d,0x1884,0x1871,0x1879,0x1880,0x1887,0xb82, -0x188f,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78,0x1e78, -0x1e78,0x1e68,0x1e6b,0x1e68,0x1e72,0x10d9,0x7b9,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x12f0,0x12f8,0x12fb,0x12fb,0x12fb,0x12fb,0x12fb, -0x12fb,0x110d,0x1115,0x1fdc,0x134f,0x7c1,0x559,0x559,0x559,0x1f84,0x122d,0x7c9,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x7cd,0x131f,0x1f94,0x1273,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x7d5,0x137f,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x12dc,0x1db3,0x1db3,0x1db3,0x1db3,0x1db3,0x1db3,0xfef,0x559,0x1ec0,0x1eb8,0x10e1,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x7dd,0x1f54,0x11d3,0x559,0x559,0x1235,0x1236,0x7e5,0x559,0x559,0x559,0x559, -0x559,0xebd,0xec5,0xecd,0xed5,0xedd,0xee5,0xeec,0xef0,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x7e9,0x1067,0x1e03,0x106d,0x1e03,0x1075,0x107a,0x107f, -0x107f,0x1e88,0x1ea8,0x1eb0,0x1f1c,0x1e90,0x1f74,0x1e98,0x1f24,0x1f7c,0x1f7c,0x119d,0x11a5,0x124d,0x1253,0x125b, -0x1263,0x1f9c,0x1f9c,0x1f9c,0x1f9c,0x12a7,0x1f9c,0x12ad,0x12b1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1, -0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1, -0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f1,0x7f2,0xb8a,0x18b1,0x18b1,0x18b1,0x7fa,0x7fa,0x7fa, -0x7fa,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x802,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa, -0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa, -0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa, -0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa, -0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0x7fa,0xbdd,0xbe4,0xbec,0xbf4,0x196e,0x196e,0x196e, -0xbfc,0xc04,0xc07,0x199e,0x1996,0xc3a,0xd56,0xd5a,0xd5e,0x559,0x559,0x559,0x559,0xd66,0x1b19,0xd6e, -0xf58,0x1822,0xb1d,0xb23,0x101f,0xc0f,0x19e2,0xca0,0x559,0x1837,0x182a,0x182f,0x1976,0xc17,0xc1f,0x114b, -0x1151,0x1d7b,0xf79,0x1d6b,0xf50,0x1327,0x132f,0x559,0x559,0x1da3,0x1da3,0x1da3,0x1da3,0x1da3,0x1da3,0x1da3, -0x1da3,0x1da3,0xfc7,0xfcf,0xfd7,0x12e4,0x12e8,0x559,0x559,0x1b21,0xd7e,0x1b29,0x1b29,0xd82,0xe8d,0xe95, -0xe9d,0x1bf1,0x1bd9,0x1bf9,0x1c01,0x1be9,0xe25,0xe29,0xe30,0xe38,0xe3c,0xe44,0xe4c,0xe4e,0xe4e,0xe4e, -0xe4e,0x1c62,0x1c6a,0x1c62,0x1c70,0x1c78,0x1c43,0x1c80,0x1c88,0x1c62,0x1c90,0x1c98,0x1c9f,0x1ca7,0x1c4b,0x1c62, -0x1cac,0x1c53,0x1c5a,0x1cb4,0x1cba,0x1d5c,0x1d63,0x1d55,0x1cc1,0x1cc9,0x1cd1,0x1cd9,0x1dd3,0x1ce1,0x1ce9,0xea5, -0xead,0x1c33,0x1c33,0x1c33,0xeb5,0x1d83,0x1d83,0xf81,0xf89,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x1e3b,0x1e3b,0x1e3b,0x1e3b,0x1e3b,0x1e3b,0x1e3b, -0x1e3b,0x1e3b,0x1e3b,0x1e3b,0x1e3b,0x1e3b,0x1e3b,0x1e40,0x1e3b,0x1e3b,0x1e3b,0x10a7,0x10a9,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8, -0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8, -0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8, -0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8, -0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1159,0x1c3b,0x1f14,0x1f14,0x1f14,0x1f14,0x1f14,0x1f14, -0x1f14,0x1f34,0x1161,0x123e,0x1245,0x1f3c,0x1f3c,0x1f3c,0x1f3c,0x1f3c,0x1f3c,0x1f3c,0x1f3c,0x1f3c,0x1f3c,0x1f3c, -0x117d,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd, -0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbf,0x1bbd,0x1bc7,0x1bbd,0x1bbd, -0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bca,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1bd1,0x1209,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0, -0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0,0x1ee0, -0x1ee4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1fb4,0x1299, -0x129f,0x12b9,0x12bc,0x12bc,0x12bc,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559, -0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x559,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9, -0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9, -0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9, -0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18bc, -0x1387,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c, -0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c, -0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x138f,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x18c4,0x18c4,0x18c4,0x18c4,0x18c4,0x18c4,0x18c4, -0x18c4,0x18c4,0x18c4,0x18c4,0x18c4,0x18c4,0x18c4,0x18c4,0x18c4,0x13b6,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1393,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x139b,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1387, -0x1387,0x1387,0x1387,0x1387,0x1387,0x1387,0x1393,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09, -0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09, -0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09, -0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09, -0x13be,0x1cf1,0x1cf1,0x1cf1,0x1cf1,0x1cf1,0x1cf1,0x13c6,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80, -0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80, -0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80, -0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80, -0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x13ce,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c, -0x1f2c,0x1f2c,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac, -0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x13d6,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751, -0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751, -0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751, -0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751, -0x1751,0x1741,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759, -0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759, -0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759, -0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759, -0x1759,0x1749,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751, -0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751, -0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751, -0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751,0x1751, -0x1751,0x1751,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759, -0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759, -0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759, -0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759,0x1759, -0x1759,0x1759,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9, -0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9, -0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9, -0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9,0x18b9, -0x18b9,0x18b9,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09, -0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09, -0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09, -0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09,0x1c09, -0x1c09,0x1c09,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80, -0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80, -0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80, -0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80,0x1e80, -0x1e80,0x1e80,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8, -0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8, -0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8, -0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8,0x1ed8, -0x1ed8,0x1ed8,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c, -0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c, -0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c, -0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c,0x1f2c, -0x1f2c,0x1f2c,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac, -0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac, -0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac, -0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac,0x1fac, -0x1fac,0x1fac,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4,0x1fe4, -0x1fe4,0x1fe4,0x538,0x538,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e5,0x2ee,0x2e8, -0x2e8,0x2eb,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2, -0x2e2,0x2e2,0x2e2,0x2e2,0x7da,0x7d4,0x7b9,0x79e,0x7aa,0x7a7,0x79e,0x7b6,0x7a4,0x7b0,0x79e,0x7cb, -0x7c2,0x7b3,0x7d7,0x7ad,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x7bf,0x7bc, -0x7c5,0x7c5,0x7c5,0x7d4,0x79e,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0, -0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7a4, -0x7aa,0x7b0,0x7d1,0x798,0x7ce,0x7e3,0x7e3,0x7e3,0x7e3,0x7e3,0x7e3,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd, -0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7a4, -0x7c8,0x7a1,0x7c5,0x2e2,0,0,0,0,0,0,0,0,0,0,0,0, +0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5, +0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x12b5,0x1235, +0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5, +0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x12f5,0x1275, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0xc2c,0xc2f,0xdfa,0x1df5,0x101c,0x74a,0x55e,0x10b6,0xcfc,0xd7b,0x55e,0x55e,0x1d1b,0xf15,0xf1d,0x1e3d, +0xc7f,0xc86,0xc8e,0x1b9f,0x1dd5,0x55e,0x1db5,0xfec,0x1ba7,0xe02,0xe0a,0xe12,0x1044,0x752,0x55e,0x55e, +0x1baf,0x1baf,0x75a,0x55e,0x1e6a,0x10ce,0x1e62,0x10d6,0x1f56,0x11d0,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0xe1a,0x1fae,0x12c9,0x134b,0x134c,0x1f76,0x11f8,0x11ff,0x1206,0x1308,0x130c,0x1280,0x1216, +0x1c2b,0x1c2d,0xe7b,0xe82,0x1bb7,0x1bbf,0xe22,0xf35,0x1d13,0xefd,0xf05,0xfe4,0x1d33,0x1d37,0x1d3f,0x1064, +0xfb4,0x1d95,0x762,0x55e,0x10be,0x10c6,0x1d9d,0xfbc,0xf96,0xf9c,0xfa4,0xfac,0x55e,0x55e,0x55e,0x55e, +0x1eda,0x1ed2,0x1140,0x1148,0x1e1d,0x1e15,0x108c,0x55e,0x55e,0x55e,0x55e,0x55e,0x1e05,0x104c,0x1054,0x105c, +0x1dcd,0x1dc5,0xffc,0x1138,0x1d47,0xf45,0x76a,0x55e,0x109c,0x10a4,0x772,0x55e,0x55e,0x55e,0x55e,0x55e, +0x1f4e,0x11b2,0x77a,0x55e,0x55e,0x1e2d,0x1e25,0x1094,0x1288,0x128e,0x1296,0x55e,0x55e,0x121e,0x1222,0x122a, +0x1f0e,0x1f06,0x119a,0x1efe,0x1ef6,0x118a,0x1dfd,0x103c,0x135c,0x135f,0x135f,0x55e,0x55e,0x55e,0x55e,0x55e, +0x10ee,0x10f3,0x10fb,0x1102,0x112a,0x1130,0x55e,0x55e,0x116e,0x1172,0x117a,0x11c2,0x11c8,0x782,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x11e0,0x136f,0x1374,0x137c,0x55e,0x55e,0x786,0x1f96,0x1270, +0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69, +0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a69,0x1a6e,0xd04,0xd0b,0xd0b,0xd0b, +0x1a76,0x1a76,0x1a76,0xd13,0x1e5a,0x1e5a,0x1e5a,0x1e5a,0x1e5a,0x1e5a,0x78e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x792,0x1fc6,0x1fc6,0x12d9,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35, +0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0xe8a,0x1004,0x100c,0x1fce, +0x1314,0x131c,0xf4d,0x1ded,0x1de5,0x102c,0x1034,0x79a,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1f6e,0x1f66,0x11f0, +0x55e,0x55e,0x55e,0x1d2b,0x1d2b,0xf25,0x1d23,0xf2d,0x55e,0x55e,0x1122,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x79e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1d7d,0x1d7d,0x1d7d,0xf71,0xf76, +0x7a6,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1fde,0x133c,0x1343,0x1fd6,0x1fd6,0x1fd6,0x7ae, +0x55e,0x1849,0x1849,0x1849,0x1849,0x1849,0x1849,0x1849,0xb30,0x1859,0xb38,0x185a,0x1851,0x1862,0x1868,0x1870, +0xb40,0x1998,0x1998,0x7b6,0x55e,0x55e,0x55e,0x1367,0x11e8,0x1988,0x1988,0xc37,0xd1b,0x55e,0x55e,0x55e, +0x55e,0x18a1,0x18a8,0xb48,0x18ab,0xb50,0xb58,0xb60,0x18a5,0xb68,0xb70,0xb78,0x18aa,0x18b2,0x18a1,0x18a8, +0x18a4,0x18ab,0x18b3,0x18a2,0x18a9,0x18a5,0xb7f,0x1878,0x1880,0x1887,0x188e,0x187b,0x1883,0x188a,0x1891,0xb87, +0x1899,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82,0x1e82, +0x1e82,0x1e72,0x1e75,0x1e72,0x1e7c,0x10de,0x7be,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x12f5,0x12fd,0x1300,0x1300,0x1300,0x1300,0x1300, +0x1300,0x1112,0x111a,0x1fe6,0x1354,0x7c6,0x55e,0x55e,0x55e,0x1f8e,0x1232,0x7ce,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x7d2,0x1324,0x1f9e,0x1278,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x7da,0x1384,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x12e1,0x1dbd,0x1dbd,0x1dbd,0x1dbd,0x1dbd,0x1dbd,0xff4,0x55e,0x1eca,0x1ec2,0x10e6,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x7e2,0x1f5e,0x11d8,0x55e,0x55e,0x123a,0x123b,0x7ea,0x55e,0x55e,0x55e,0x55e, +0x55e,0xec2,0xeca,0xed2,0xeda,0xee2,0xeea,0xef1,0xef5,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x7ee,0x106c,0x1e0d,0x1072,0x1e0d,0x107a,0x107f,0x1084, +0x1084,0x1e92,0x1eb2,0x1eba,0x1f26,0x1e9a,0x1f7e,0x1ea2,0x1f2e,0x1f86,0x1f86,0x11a2,0x11aa,0x1252,0x1258,0x1260, +0x1268,0x1fa6,0x1fa6,0x1fa6,0x1fa6,0x12ac,0x1fa6,0x12b2,0x12b6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6, +0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6, +0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f6,0x7f7,0xb8f,0x18bb,0x18bb,0x18bb,0x7ff,0x7ff,0x7ff, +0x7ff,0x1990,0x1990,0x1990,0x1990,0x1990,0x1990,0x1990,0x807,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff, +0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff, +0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff, +0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff, +0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0x7ff,0xbe2,0xbe9,0xbf1,0xbf9,0x1978,0x1978,0x1978, +0xc01,0xc09,0xc0c,0x19a8,0x19a0,0xc3f,0xd5b,0xd5f,0xd63,0x55e,0x55e,0x55e,0x55e,0xd6b,0x1b23,0xd73, +0xf5d,0x182c,0xb22,0xb28,0x1024,0xc14,0x19ec,0xca5,0x55e,0x1841,0x1834,0x1839,0x1980,0xc1c,0xc24,0x1150, +0x1156,0x1d85,0xf7e,0x1d75,0xf55,0x132c,0x1334,0x55e,0x55e,0x1dad,0x1dad,0x1dad,0x1dad,0x1dad,0x1dad,0x1dad, +0x1dad,0x1dad,0xfcc,0xfd4,0xfdc,0x12e9,0x12ed,0x55e,0x55e,0x1b2b,0xd83,0x1b33,0x1b33,0xd87,0xe92,0xe9a, +0xea2,0x1bfb,0x1be3,0x1c03,0x1c0b,0x1bf3,0xe2a,0xe2e,0xe35,0xe3d,0xe41,0xe49,0xe51,0xe53,0xe53,0xe53, +0xe53,0x1c6c,0x1c74,0x1c6c,0x1c7a,0x1c82,0x1c4d,0x1c8a,0x1c92,0x1c6c,0x1c9a,0x1ca2,0x1ca9,0x1cb1,0x1c55,0x1c6c, +0x1cb6,0x1c5d,0x1c64,0x1cbe,0x1cc4,0x1d66,0x1d6d,0x1d5f,0x1ccb,0x1cd3,0x1cdb,0x1ce3,0x1ddd,0x1ceb,0x1cf3,0xeaa, +0xeb2,0x1c3d,0x1c3d,0x1c3d,0xeba,0x1d8d,0x1d8d,0xf86,0xf8e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1e45,0x1e45,0x1e45,0x1e45,0x1e45,0x1e45,0x1e45, +0x1e45,0x1e45,0x1e45,0x1e45,0x1e45,0x1e45,0x1e45,0x1e4a,0x1e45,0x1e45,0x1e45,0x10ac,0x10ae,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2, +0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2, +0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2, +0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2, +0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x115e,0x1c45,0x1f1e,0x1f1e,0x1f1e,0x1f1e,0x1f1e,0x1f1e, +0x1f1e,0x1f3e,0x1166,0x1243,0x124a,0x1f46,0x1f46,0x1f46,0x1f46,0x1f46,0x1f46,0x1f46,0x1f46,0x1f46,0x1f46,0x1f46, +0x1182,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7, +0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc9,0x1bc7,0x1bd1,0x1bc7,0x1bc7, +0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bd4,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bc7,0x1bdb,0x120e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea, +0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea,0x1eea, +0x1eee,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x1fbe,0x129e, +0x12a4,0x12be,0x12c1,0x12c1,0x12c1,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e, +0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x55e,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3, +0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3, +0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3, +0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c6, +0x138c,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36, +0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36, +0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x13d0,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6, +0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x1ff6,0x13e0,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x18ce,0x18ce,0x18ce,0x18ce, +0x18ce,0x18ce,0x18ce,0x18ce,0x18ce,0x18ce,0x18ce,0x18ce,0x18ce,0x18ce,0x18ce,0x18ce,0x13b0,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138d,0x1fee,0x1fee,0x1fee,0x1fee, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1395,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138d,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13, +0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13, +0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13, +0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13, +0x1c13,0x1c13,0x1c13,0x13b8,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x1cfb,0x13c0,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a, +0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a, +0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a, +0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a, +0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x13c8,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36, +0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6, +0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x13d8, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x174b,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763, +0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763, +0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763, +0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763, +0x1763,0x1763,0x1763,0x1763,0x1753,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, +0x175b,0x175b,0x175b,0x175b,0x175b,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763, +0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763, +0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763, +0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763,0x1763, +0x1763,0x1763,0x1763,0x1763,0x1763,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3, +0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3, +0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3, +0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x18c3, +0x18c3,0x18c3,0x18c3,0x18c3,0x18c3,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13, +0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13, +0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13, +0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1c13, +0x1c13,0x1c13,0x1c13,0x1c13,0x1c13,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a, +0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a, +0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a, +0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a, +0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1e8a,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2, +0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2, +0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2, +0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2, +0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1ee2,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36, +0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36, +0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36, +0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1f36, +0x1f36,0x1f36,0x1f36,0x1f36,0x1f36,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6, +0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6, +0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6, +0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6, +0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fb6,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x1fee, +0x1fee,0x1fee,0x1fee,0x1fee,0x1fee,0x53d,0x53d,0x53d,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2, +0x2e2,0x2e5,0x2ee,0x2e8,0x2e8,0x2eb,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2, +0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x2e2,0x7da,0x7d4,0x7b9,0x79e,0x7aa,0x7a7,0x79e,0x7b6, +0x7a4,0x7b0,0x79e,0x7cb,0x7c2,0x7b3,0x7d7,0x7ad,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b,0x79b, +0x79b,0x79b,0x7bf,0x7bc,0x7c5,0x7c5,0x7c5,0x7d4,0x79e,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e6,0x7e0, +0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0,0x7e0, +0x7e0,0x7e0,0x7e0,0x7a4,0x7aa,0x7b0,0x7d1,0x798,0x7ce,0x7e3,0x7e3,0x7e3,0x7e3,0x7e3,0x7e3,0x7dd, +0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd,0x7dd, +0x7dd,0x7dd,0x7dd,0x7a4,0x7c8,0x7a1,0x7c5,0x2e2,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x300,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1, +0,0,0,0,0,0,0,0,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x300,0x2f1,0x2f1, 0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1, -0x2f1,0x2f1,0x2f1,0x2f1,0x2f4,0x64b,0x7ef,0x7f2,0x651,0x7f2,0x7ec,0x645,0x63c,0x2fa,0x65a,0x2fd, -0x7f5,0x633,0x648,0x7e9,0x64e,0x657,0x639,0x639,0x63f,0x2f7,0x645,0x642,0x63c,0x639,0x65a,0x2fd, -0x636,0x636,0x636,0x64b,0x306,0x306,0x306,0x306,0x306,0x306,0x663,0x306,0x306,0x306,0x306,0x306, -0x306,0x306,0x306,0x306,0x663,0x306,0x306,0x306,0x306,0x306,0x306,0x654,0x663,0x306,0x306,0x306, -0x306,0x306,0x663,0x65d,0x660,0x660,0x303,0x303,0x303,0x303,0x65d,0x303,0x660,0x660,0x660,0x303, -0x660,0x660,0x303,0x303,0x65d,0x303,0x660,0x660,0x303,0x303,0x303,0x654,0x65d,0x660,0x660,0x303, -0x660,0x303,0x65d,0x303,0x312,0x669,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309, -0x312,0x309,0x312,0x309,0x30f,0x666,0x312,0x669,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x669, -0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x66f,0x666,0x312,0x309,0x312,0x669, -0x312,0x309,0x312,0x309,0x312,0x666,0x672,0x66c,0x312,0x309,0x312,0x309,0x666,0x312,0x309,0x312, -0x309,0x312,0x309,0x672,0x66c,0x66f,0x666,0x312,0x669,0x312,0x309,0x312,0x669,0x675,0x66f,0x666, -0x312,0x669,0x312,0x309,0x312,0x309,0x66f,0x666,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309, -0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x66f,0x666,0x312,0x309,0x312,0x669, -0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x312,0x309,0x312, -0x309,0x312,0x309,0x30c,0x315,0x321,0x321,0x315,0x321,0x315,0x321,0x321,0x315,0x321,0x321,0x321, -0x315,0x315,0x321,0x321,0x321,0x321,0x315,0x321,0x321,0x315,0x321,0x321,0x321,0x315,0x315,0x315, -0x321,0x321,0x315,0x321,0x324,0x318,0x321,0x315,0x321,0x315,0x321,0x321,0x315,0x321,0x315,0x315, -0x321,0x315,0x321,0x324,0x318,0x321,0x321,0x321,0x315,0x321,0x315,0x321,0x321,0x315,0x315,0x31e, -0x321,0x315,0x315,0x315,0x31e,0x31e,0x31e,0x31e,0x327,0x327,0x31b,0x327,0x327,0x31b,0x327,0x327, -0x31b,0x324,0x678,0x324,0x678,0x324,0x678,0x324,0x678,0x324,0x678,0x324,0x678,0x324,0x678,0x324, -0x678,0x315,0x324,0x318,0x324,0x318,0x324,0x318,0x321,0x315,0x324,0x318,0x324,0x318,0x324,0x318, -0x324,0x318,0x324,0x318,0x318,0x327,0x327,0x31b,0x324,0x318,0x9cf,0x9cf,0x9d2,0x9cc,0x324,0x318, -0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318, -0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x9d2,0x9cc,0x9d2,0x9cc,0x9cf,0x9c9,0x9d2,0x9cc, -0xb8b,0xc84,0x9cf,0x9c9,0x9cf,0x9c9,0x9d2,0x9cc,0x9d2,0x9cc,0x9d2,0x9cc,0x9d2,0x9cc,0x9d2,0x9cc, -0x9d2,0x9cc,0x9d2,0x9cc,0xc84,0xc84,0xc84,0xd7d,0xd7d,0xd7d,0xd80,0xd80,0xd7d,0xd80,0xd80,0xd7d, -0xd7d,0xd80,0xebe,0xec1,0xec1,0xec1,0xec1,0xebe,0xec1,0xebe,0xec1,0xebe,0xec1,0xebe,0xec1,0xebe, -0x32a,0x67b,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a, -0x32a,0x67b,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a, +0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f1,0x2f4,0x64b,0x7ef,0x7f2,0x651,0x7f2,0x7ec,0x645, +0x63c,0x2fa,0x65a,0x2fd,0x7f5,0x633,0x648,0x7e9,0x64e,0x657,0x639,0x639,0x63f,0x2f7,0x645,0x642, +0x63c,0x639,0x65a,0x2fd,0x636,0x636,0x636,0x64b,0x306,0x306,0x306,0x306,0x306,0x306,0x663,0x306, +0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x306,0x663,0x306,0x306,0x306,0x306,0x306,0x306,0x654, +0x663,0x306,0x306,0x306,0x306,0x306,0x663,0x65d,0x660,0x660,0x303,0x303,0x303,0x303,0x65d,0x303, +0x660,0x660,0x660,0x303,0x660,0x660,0x303,0x303,0x65d,0x303,0x660,0x660,0x303,0x303,0x303,0x654, +0x65d,0x660,0x660,0x303,0x660,0x303,0x65d,0x303,0x312,0x669,0x312,0x309,0x312,0x309,0x312,0x309, +0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x30f,0x666,0x312,0x669,0x312,0x309,0x312,0x309, +0x312,0x309,0x312,0x669,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x66f,0x666, +0x312,0x309,0x312,0x669,0x312,0x309,0x312,0x309,0x312,0x666,0x672,0x66c,0x312,0x309,0x312,0x309, +0x666,0x312,0x309,0x312,0x309,0x312,0x309,0x672,0x66c,0x66f,0x666,0x312,0x669,0x312,0x309,0x312, +0x669,0x675,0x66f,0x666,0x312,0x669,0x312,0x309,0x312,0x309,0x66f,0x666,0x312,0x309,0x312,0x309, +0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x66f,0x666, +0x312,0x309,0x312,0x669,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309,0x312,0x309, +0x312,0x312,0x309,0x312,0x309,0x312,0x309,0x30c,0x315,0x321,0x321,0x315,0x321,0x315,0x321,0x321, +0x315,0x321,0x321,0x321,0x315,0x315,0x321,0x321,0x321,0x321,0x315,0x321,0x321,0x315,0x321,0x321, +0x321,0x315,0x315,0x315,0x321,0x321,0x315,0x321,0x324,0x318,0x321,0x315,0x321,0x315,0x321,0x321, +0x315,0x321,0x315,0x315,0x321,0x315,0x321,0x324,0x318,0x321,0x321,0x321,0x315,0x321,0x315,0x321, +0x321,0x315,0x315,0x31e,0x321,0x315,0x315,0x315,0x31e,0x31e,0x31e,0x31e,0x327,0x327,0x31b,0x327, +0x327,0x31b,0x327,0x327,0x31b,0x324,0x678,0x324,0x678,0x324,0x678,0x324,0x678,0x324,0x678,0x324, +0x678,0x324,0x678,0x324,0x678,0x315,0x324,0x318,0x324,0x318,0x324,0x318,0x321,0x315,0x324,0x318, +0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x318,0x327,0x327,0x31b,0x324,0x318,0x9cf,0x9cf, +0x9d2,0x9cc,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318, +0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x324,0x318,0x9d2,0x9cc,0x9d2,0x9cc, +0x9cf,0x9c9,0x9d2,0x9cc,0xb8e,0xc87,0x9cf,0x9c9,0x9cf,0x9c9,0x9d2,0x9cc,0x9d2,0x9cc,0x9d2,0x9cc, +0x9d2,0x9cc,0x9d2,0x9cc,0x9d2,0x9cc,0x9d2,0x9cc,0xc87,0xc87,0xc87,0xd80,0xd80,0xd80,0xd83,0xd83, +0xd80,0xd83,0xd83,0xd80,0xd80,0xd83,0xec1,0xec4,0xec4,0xec4,0xec4,0xec1,0xec4,0xec1,0xec4,0xec1, +0xec4,0xec1,0xec4,0xec1,0x32a,0x67b,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a, +0x32a,0x32a,0x32a,0x32a,0x32a,0x67b,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a, 0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a, -0x32d,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a, -0x32a,0x32a,0x32a,0x32a,0x32a,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0xc87,0xc87,0x342,0x342,0x342,0x342, -0x342,0x342,0x342,0x342,0x342,0x339,0x339,0x339,0x339,0x339,0x339,0x339,0x336,0x336,0x333,0x333, -0x681,0x333,0x339,0x684,0x33c,0x684,0x684,0x684,0x33c,0x684,0x339,0x339,0x687,0x33f,0x333,0x333, -0x333,0x333,0x333,0x333,0x67e,0x67e,0x67e,0x67e,0x330,0x67e,0x333,0xb01,0x342,0x342,0x342,0x342, -0x342,0x333,0x333,0x333,0x333,0x333,0x9de,0x9de,0x9db,0x9d8,0x9db,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a, -0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0xc8a,0x68a,0x68a,0x68a,0x68a, +0x32a,0x32a,0x32a,0x32a,0x32d,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a, +0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x32a,0x9d5,0x9d5,0x9d5,0x9d5,0x9d5,0xc8a,0xc8a, +0x342,0x342,0x342,0x342,0x342,0x342,0x342,0x342,0x342,0x339,0x339,0x339,0x339,0x339,0x339,0x339, +0x336,0x336,0x333,0x333,0x681,0x333,0x339,0x684,0x33c,0x684,0x684,0x684,0x33c,0x684,0x339,0x339, +0x687,0x33f,0x333,0x333,0x333,0x333,0x333,0x333,0x67e,0x67e,0x67e,0x67e,0x330,0x67e,0x333,0xb04, +0x342,0x342,0x342,0x342,0x342,0x333,0x333,0x333,0x333,0x333,0x9de,0x9de,0x9db,0x9d8,0x9db,0xc8d, +0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d,0xc8d, +0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a, 0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a, 0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a, 0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a, -0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68a,0x68d,0x68d,0x92d,0x68d, -0x68d,0x930,0xb04,0xb04,0xb04,0xb04,0xb04,0xb04,0xb04,0xb04,0xb04,0xc3c,0xd47,0xd47,0xd47,0xd47, -0xd47,0xd47,0xd47,0xd47,0xe82,0xe82,0xe82,0xe82,0xe85,0xd4a,0xd4a,0xd4a,0x690,0x690,0xb07,0xc81, -0xc81,0xc81,0xc81,0xc81,0xc81,0xc81,0xc81,0xc81,0xc81,0xc81,0xc81,0xc81,0xf6c,0xf69,0xf6c,0xf69, -0x34e,0x357,0xf6c,0xf69,9,9,0x35d,0xec4,0xec4,0xec4,0x345,0x14af,9,9,9,9, -0x35a,0x348,0x36c,0x34b,0x36c,0x36c,0x36c,9,0x36c,9,0x36c,0x36c,0x363,0x696,0x696,0x696, -0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,9,0x696, -0x696,0x696,0x696,0x696,0x696,0x696,0x36c,0x36c,0x363,0x363,0x363,0x363,0x363,0x693,0x693,0x693, -0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x360,0x693, -0x693,0x693,0x693,0x693,0x693,0x693,0x363,0x363,0x363,0x363,0x363,0xf6c,0x36f,0x36f,0x372,0x36c, -0x36c,0x36f,0x366,0x9e1,0xb94,0xb91,0x369,0x9e1,0x369,0x9e1,0x369,0x9e1,0x369,0x9e1,0x354,0x351, -0x354,0x351,0x354,0x351,0x354,0x351,0x354,0x351,0x354,0x351,0x354,0x351,0x36f,0x36f,0x366,0x360, -0xb43,0xb40,0xb8e,0xc90,0xc8d,0xc93,0xc90,0xc8d,0xd83,0xd86,0xd86,0xd86,0x9f0,0x6a2,0x37e,0x381, -0x37e,0x37e,0x37e,0x381,0x37e,0x37e,0x37e,0x37e,0x381,0x9f0,0x381,0x37e,0x69f,0x69f,0x69f,0x69f, -0x69f,0x69f,0x69f,0x69f,0x69f,0x6a2,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f, -0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x699,0x699,0x699,0x699, -0x699,0x699,0x699,0x699,0x699,0x69c,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699, -0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x9ea,0x69c,0x378,0x37b,0x378,0x378,0x378,0x37b, -0x378,0x378,0x378,0x378,0x37b,0x9ea,0x37b,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378, -0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x381,0x37b, -0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x375,0x939,0x93c,0x91e,0x91e,0x1116, -0x9e4,0x9e4,0xb9a,0xb97,0x9ed,0x9e7,0x9ed,0x9e7,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378, +0x68d,0x68d,0x92d,0x68d,0x68d,0x930,0xb07,0xb07,0xb07,0xb07,0xb07,0xb07,0xb07,0xb07,0xb07,0xc3f, +0xd4a,0xd4a,0xd4a,0xd4a,0xd4a,0xd4a,0xd4a,0xd4a,0xe85,0xe85,0xe85,0xe85,0xe88,0xd4d,0xd4d,0xd4d, +0x690,0x690,0xb0a,0xc84,0xc84,0xc84,0xc84,0xc84,0xc84,0xc84,0xc84,0xc84,0xc84,0xc84,0xc84,0xc84, +0xf6f,0xf6c,0xf6f,0xf6c,0x34e,0x357,0xf6f,0xf6c,9,9,0x35d,0xec7,0xec7,0xec7,0x345,0x14b8, +9,9,9,9,0x35a,0x348,0x36c,0x34b,0x36c,0x36c,0x36c,9,0x36c,9,0x36c,0x36c, +0x363,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x696, +0x696,0x696,9,0x696,0x696,0x696,0x696,0x696,0x696,0x696,0x36c,0x36c,0x363,0x363,0x363,0x363, +0x363,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x693, +0x693,0x693,0x360,0x693,0x693,0x693,0x693,0x693,0x693,0x693,0x363,0x363,0x363,0x363,0x363,0xf6f, +0x36f,0x36f,0x372,0x36c,0x36c,0x36f,0x366,0x9e1,0xb97,0xb94,0x369,0x9e1,0x369,0x9e1,0x369,0x9e1, +0x369,0x9e1,0x354,0x351,0x354,0x351,0x354,0x351,0x354,0x351,0x354,0x351,0x354,0x351,0x354,0x351, +0x36f,0x36f,0x366,0x360,0xb46,0xb43,0xb91,0xc93,0xc90,0xc96,0xc93,0xc90,0xd86,0xd89,0xd89,0xd89, +0x9f0,0x6a2,0x37e,0x381,0x37e,0x37e,0x37e,0x381,0x37e,0x37e,0x37e,0x37e,0x381,0x9f0,0x381,0x37e, +0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x6a2,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f, +0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f,0x69f, +0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x69c,0x699,0x699,0x699,0x699,0x699,0x699, +0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x699,0x9ea,0x69c,0x378,0x37b, +0x378,0x378,0x378,0x37b,0x378,0x378,0x378,0x378,0x37b,0x9ea,0x37b,0x378,0x37e,0x378,0x37e,0x378, 0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378, +0x37e,0x378,0x381,0x37b,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x375,0x939, +0x93c,0x91e,0x91e,0x111c,0x9e4,0x9e4,0xb9d,0xb9a,0x9ed,0x9e7,0x9ed,0x9e7,0x37e,0x378,0x37e,0x378, 0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378, -0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x381,0x37b,0x37e,0x378,0xb9a,0xb97,0x37e, -0x378,0xb9a,0xb97,0x37e,0x378,0xb9a,0xb97,0xec7,0x381,0x37b,0x381,0x37b,0x37e,0x378,0x381,0x37b, -0x37e,0x378,0x381,0x37b,0x381,0x37b,0x381,0x37b,0x37e,0x378,0x381,0x37b,0x381,0x37b,0x381,0x37b, -0x37e,0x378,0x381,0x37b,0x9f0,0x9ea,0x381,0x37b,0x381,0x37b,0x381,0x37b,0x381,0x37b,0xd8c,0xd89, -0x381,0x37b,0xeca,0xec7,0xeca,0xec7,0xeca,0xec7,0xc00,0xbfd,0xc00,0xbfd,0xc00,0xbfd,0xc00,0xbfd, -0xc00,0xbfd,0xc00,0xbfd,0xc00,0xbfd,0xc00,0xbfd,0xef7,0xef4,0xef7,0xef4,0xfe7,0xfe4,0xfe7,0xfe4, -0xfe7,0xfe4,0xfe7,0xfe4,0xfe7,0xfe4,0xfe7,0xfe4,0xfe7,0xfe4,0xfe7,0xfe4,0x114f,0x114c,0x1329,0x1326, -0x14e5,0x14e2,0x14e5,0x14e2,0x14e5,0x14e2,0x14e5,0x14e2,0xc,0x393,0x393,0x393,0x393,0x393,0x393,0x393, +0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378, +0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x378,0x37e,0x381,0x37b,0x37e, +0x378,0xb9d,0xb9a,0x37e,0x378,0xb9d,0xb9a,0x37e,0x378,0xb9d,0xb9a,0xeca,0x381,0x37b,0x381,0x37b, +0x37e,0x378,0x381,0x37b,0x37e,0x378,0x381,0x37b,0x381,0x37b,0x381,0x37b,0x37e,0x378,0x381,0x37b, +0x381,0x37b,0x381,0x37b,0x37e,0x378,0x381,0x37b,0x9f0,0x9ea,0x381,0x37b,0x381,0x37b,0x381,0x37b, +0x381,0x37b,0xd8f,0xd8c,0x381,0x37b,0xecd,0xeca,0xecd,0xeca,0xecd,0xeca,0xc03,0xc00,0xc03,0xc00, +0xc03,0xc00,0xc03,0xc00,0xc03,0xc00,0xc03,0xc00,0xc03,0xc00,0xc03,0xc00,0xefa,0xef7,0xefa,0xef7, +0xfea,0xfe7,0xfea,0xfe7,0xfea,0xfe7,0xfea,0xfe7,0xfea,0xfe7,0xfea,0xfe7,0xfea,0xfe7,0xfea,0xfe7, +0x1155,0x1152,0x132f,0x132c,0x14ee,0x14eb,0x14ee,0x14eb,0x14ee,0x14eb,0x14ee,0x14eb,0xc,0x393,0x393,0x393, 0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393,0x393, -0x393,0x393,0x393,0xc,0xc,0x396,0x384,0x384,0x384,0x38a,0x384,0x387,0x18ea,0x38d,0x38d,0x38d, +0x393,0x393,0x393,0x393,0x393,0x393,0x393,0xc,0xc,0x396,0x384,0x384,0x384,0x38a,0x384,0x387, +0x18f9,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d, 0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d, -0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x38d,0x390, -0x18ea,0x399,0x9f3,0xc,0xc,0x14b2,0x14b2,0x13ce,0xf,0x960,0x960,0x960,0x960,0x960,0x960,0x960, -0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0xd8f,0x960,0x960,0x960,0x960,0x960, -0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0x39c, -0x39c,0x39c,0xecd,0x39c,0x39c,0x39c,0x3a8,0x39c,0x39f,0x39c,0x39c,0x3ab,0x963,0xd92,0xd95,0xd92, -0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae, +0x38d,0x38d,0x38d,0x390,0x18f9,0x399,0x9f3,0xc,0xc,0x14bb,0x14bb,0x13d7,0xf,0x960,0x960,0x960, +0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0xd92,0x960, +0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x960,0x39c,0x39c,0x39c,0x39c, +0x39c,0x39c,0x39c,0x39c,0x39c,0x39c,0xed0,0x39c,0x39c,0x39c,0x3a8,0x39c,0x39f,0x39c,0x39c,0x3ab, +0x963,0xd95,0xd98,0xd95,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x3ae,0x3ae,0x3ae,0x3ae, 0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae, -0x3ae,0x3ae,0x3ae,0xf,0xf,0xf,0xf,0x18ed,0x3ae,0x3ae,0x3ae,0x3a5,0x3a2,0xf,0xf,0xf, -0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xca8,0xca8,0xca8,0xca8,0x13d1,0x14b5,0xf75,0xf75, -0xf75,0xf72,0xf72,0xd9b,0x8a6,0xca2,0xc9f,0xc9f,0xc96,0xc96,0xc96,0xc96,0xc96,0xc96,0xf6f,0xf6f, -0xf6f,0xf6f,0xf6f,0x8a3,0x14ac,0x1afd,0xd9e,0x8a9,0x12f0,0x3c9,0x3cc,0x3cc,0x3cc,0x3cc,0x3cc,0x3c9, +0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0x3ae,0xf,0xf,0xf,0xf,0x18fc,0x3ae,0x3ae,0x3ae,0x3a5, +0x3a2,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xcab,0xcab,0xcab,0xcab, +0x13da,0x14be,0xf78,0xf78,0xf78,0xf75,0xf75,0xd9e,0x8a6,0xca5,0xca2,0xca2,0xc99,0xc99,0xc99,0xc99, +0xc99,0xc99,0xf72,0xf72,0xf72,0xf72,0xf72,0x8a3,0x14b5,0x1b0f,0xda1,0x8a9,0x12f6,0x3c9,0x3cc,0x3cc, +0x3cc,0x3cc,0x3cc,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, +0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0xf7b,0xf7b,0xf7b,0xf7b,0xf7b,0x8ac,0x3c9,0x3c9,0x3c9, +0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x924,0x924,0x924,0x924,0x924,0x924,0x924,0x924,0xb3d, +0xb3d,0xb3d,0xc99,0xc9f,0xc9c,0xd9b,0xd9b,0xd9b,0xd9b,0xd9b,0xd9b,0x12f3,0x93f,0x93f,0x93f,0x93f, +0x93f,0x93f,0x93f,0x93f,0x93f,0x93f,0x3c3,0x3c0,0x3bd,0x3ba,0xba0,0xba0,0x921,0x3c9,0x3c9,0x3d5, +0x3c9,0x3cf,0x3cf,0x3cf,0x3cf,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, 0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, -0x3c9,0x3c9,0x3c9,0xf78,0xf78,0xf78,0xf78,0xf78,0x8ac,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, -0x3c9,0x3c9,0x3c9,0x924,0x924,0x924,0x924,0x924,0x924,0x924,0x924,0xb3a,0xb3a,0xb3a,0xc96,0xc9c, -0xc99,0xd98,0xd98,0xd98,0xd98,0xd98,0xd98,0x12ed,0x93f,0x93f,0x93f,0x93f,0x93f,0x93f,0x93f,0x93f, -0x93f,0x93f,0x3c3,0x3c0,0x3bd,0x3ba,0xb9d,0xb9d,0x921,0x3c9,0x3c9,0x3d5,0x3c9,0x3cf,0x3cf,0x3cf, -0x3cf,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, 0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, 0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, -0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x9f9,0x9f9,0x3c9,0x3c9, -0x3c9,0x3c9,0x3c9,0x9f9,0x3cc,0x3c9,0x3cc,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, -0x3c9,0x3c9,0x3c9,0x9f9,0x3c9,0x3c9,0x3c9,0x3cc,0x942,0x3c9,0x3b4,0x3b4,0x3b4,0x3b4,0x3b4,0x3b4, -0x3b4,0x3b1,0x3ba,0x3b7,0x3b7,0x3b4,0x3b4,0x3b4,0x3b4,0x3d2,0x3d2,0x3b4,0x3b4,0x3ba,0x3b7,0x3b7, -0x3b7,0x3b4,0xca5,0xca5,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x9f9,0x9f9, -0x9f9,0x9f6,0x9f6,0xca5,0xa0e,0xa0e,0xa0e,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa08,0xa05, -0xa08,0xa05,0x12,0xa11,0xa0b,0x9fc,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b, +0x9f9,0x9f9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x9f9,0x3cc,0x3c9,0x3cc,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9, +0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x3c9,0x9f9,0x3c9,0x3c9,0x3c9,0x3cc,0x942,0x3c9,0x3b4,0x3b4, +0x3b4,0x3b4,0x3b4,0x3b4,0x3b4,0x3b1,0x3ba,0x3b7,0x3b7,0x3b4,0x3b4,0x3b4,0x3b4,0x3d2,0x3d2,0x3b4, +0x3b4,0x3ba,0x3b7,0x3b7,0x3b7,0x3b4,0xca8,0xca8,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6,0x3c6, +0x3c6,0x3c6,0x9f9,0x9f9,0x9f9,0x9f6,0x9f6,0xca8,0xa0e,0xa0e,0xa0e,0xa08,0xa08,0xa08,0xa08,0xa08, +0xa08,0xa08,0xa08,0xa05,0xa08,0xa05,0x12,0xa11,0xa0b,0x9fc,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b, 0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xa0b, -0xa0b,0xcab,0xcab,0xcab,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02, -0xa02,0xa02,0xa02,0xa02,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x12, -0x12,0xcab,0xcab,0xcab,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb, -0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb, -0xdfb,0xdfb,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9, -0xff9,0xff9,0xff9,0xff9,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17, +0xa0b,0xa0b,0xa0b,0xa0b,0xa0b,0xcae,0xcae,0xcae,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02, +0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0xa02,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff,0x9ff, +0x9ff,0x9ff,0x9ff,0x12,0x12,0xcae,0xcae,0xcae,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe, +0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe, +0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xdfe,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc, +0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17, 0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17, -0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14, -0xa14,0xa14,0xa14,0xa14,0xa14,0xba0,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, -0x15,0x15,0x15,0x15,0xf0f,0xf0f,0xf0f,0xf0f,0xf0f,0xf0f,0xf0f,0xf0f,0xf0f,0xf0f,0xf12,0xf12, -0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12, -0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf06, -0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf06,0xf15,0xf15,0xf09,0xf09,0xf0c,0xf1b,0xf18,0x102, -0x102,0x1911,0x1914,0x1914,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb13,0xb13,0xb16,0xb16,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13, -0x6f,0x6f,0x6f,0x6f,0x1e0,0x1e0,0x1e0,0x1e0,0x1e0,0x1e0,0x1e0,0x1617,0x1617,0x1617,0x1617,0x1617, -0x1617,0x1617,0x1617,0x1617,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1650,0x1650,0x1650, -0x1650,0x1650,0x1650,0x1650,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x16b,0x16b,0x16b, -0x16b,0x16b,0x16b,0x16b,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1bdb,0x1bd8,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2, -0x1c2,0x1c2,0x1c2,0x1c2,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1a7,0x1a7, -0x1a7,0x1a7,0x1a7,0x1a7,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x201,0x201,0x201,0x201,0x201, -0x201,0x201,0x201,0x201,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x249,0x249,0x249,0x249,0x249,0x249,0x249,0x249,0x249,0x249,0x249,0x249, -0x249,0x249,0x249,0x249,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x195f,0x195f,0x195f,0x195f,0x195f,0x195f,0x195f,0x195f,0x195f,0x195f,0x24f,0x24f, -0x24f,0x24f,0x24f,0x24f,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1ac1,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b, -0x28b,0x28b,0x28b,0x28b,0x1752,0x1752,0x1752,0x1752,0x207,0x207,0x207,0x207,0x207,0x207,0x207,0x207, -0x207,0x207,0x207,0x207,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c, -0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e, -0x163e,0x163e,0x163e,0x163e,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x2a0,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3,0x1bc3, -0x2a0,0x1bc3,0x1bc3,0x2a0,0x16b6,0x16b6,0x16b6,0x16b6,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef, -0x1ef,0x1ef,0x1ef,0x1ef,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5, -0x2b5,0x2b5,0x2b5,0x2b5,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xdf2,0xdf2,0xdef,0xdef,0xdef,0xdf2,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5, -0xd5,0xd5,0xd5,0xd5,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x213,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a, -0x176a,0x176a,0x176a,0x176a,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb, -0x2bb,0x2bb,0x2bb,0x1bf6,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1a13,0x1a13,0x1a13,0x1a13,0x1a13,0x1a13,0x1a13,0x1a13,0x1a13,0x1a13,0x270,0x270, -0x270,0x270,0x1a16,0x1a10,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93, -0x1b93,0x1b93,0x1b93,0x1b93,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26, -0x1c26,0x1c26,0x1c26,0x1c26,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0x255,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974, -0x1974,0x1974,0x1974,0x1974,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273, -0x273,0x273,0x273,0x273,0,0,0,0,0,0,0,0,0,0,0,0, +0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa17,0xa14,0xa14, +0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xa14,0xba3,0x15,0x15,0x15,0x15,0x15,0x15, +0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12,0xf12, +0xf12,0xf12,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15, +0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15,0xf15, +0xf15,0xf15,0xf15,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf09,0xf18,0xf18,0xf0c,0xf0c, +0xf0f,0xf1e,0xf1b,0xff,0xff,0x1920,0x1923,0x1923,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb16,0xb16,0xb19,0xb19,0xb16,0xb16,0xb16,0xb16, +0xb16,0xb16,0xb16,0xb16,0x1c53,0x1c53,0x1c50,0x1c50,0x1dd,0x1dd,0x1dd,0x1dd,0x1dd,0x1dd,0x1dd,0x1626, +0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9, +0x1e9,0x165f,0x165f,0x165f,0x165f,0x165f,0x165f,0x165f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248, +0x1248,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1bed,0x1bea,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf, +0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491, +0x1491,0x1491,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1fe, +0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x246,0x246,0x246,0x246,0x246,0x246,0x246,0x246, +0x246,0x246,0x246,0x246,0x246,0x246,0x246,0x246,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e, +0x196e,0x196e,0x24c,0x24c,0x24c,0x24c,0x24c,0x24c,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1ad3,0x288,0x288,0x288,0x288,0x288,0x288,0x288, +0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x1761,0x1761,0x1761,0x1761,0x204,0x204,0x204,0x204, +0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e, +0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d, +0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1bd5,0x1bd5,0x1bd5,0x1bd5,0x29d,0x1bd5,0x1bd5,0x1bd5, +0x1bd5,0x1bd5,0x1bd5,0x1bd5,0x29d,0x1bd5,0x1bd5,0x29d,0x16c5,0x16c5,0x16c5,0x16c5,0x1ec,0x1ec,0x1ec,0x1ec, +0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x2b2,0x2b2,0x2b2,0x2b2, +0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xdf5,0xdf5,0xdf2,0xdf2,0xdf2,0xdf5,0xd2,0xd2, +0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x210,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779, +0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8, +0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x1c08,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1a25,0x1a25,0x1a25,0x1a25,0x1a25,0x1a25,0x1a25,0x1a25, +0x1a25,0x1a25,0x26d,0x26d,0x26d,0x26d,0x1a28,0x1a22,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5, +0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38, +0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x252,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983, +0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0x270, +0x270,0x270,0x270,0x270,0x270,0x270,0x270,0x270,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0x95d,0x95d,3,3,3,3,3,3,3,3,3,3,3,3, +0,0,0,0,0,0,0x95d,0x95d,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, -3,3,3,3,3,3,0x95d,0x95d,6,6,6,6,6,6,6,6, +3,3,3,3,3,3,3,3,3,3,0x95d,0x95d,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50, -0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,6,6,6,6,6,6,6,6, -6,6,6,6,6,6,6,6,0x14bb,0x3f0,0x3ff,0x3ff,0x18,0x405,0x405,0x405, -0x405,0x405,0x405,0x405,0x405,0x18,0x18,0x405,0x405,0x18,0x18,0x405,0x405,0x405,0x405,0x405, -0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x18,0x405,0x405,0x405,0x405,0x405,0x405, -0x405,0x18,0x405,0x18,0x18,0x18,0x405,0x405,0x405,0x405,0x18,0x18,0x3f3,0xcb1,0x3f0,0x3ff, -0x3ff,0x3f0,0x3f0,0x3f0,0x3f0,0x18,0x18,0x3ff,0x3ff,0x18,0x18,0x402,0x402,0x3f6,0xda4,0x18, -0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3f0,0x18,0x18,0x18,0x18,0x408,0x408,0x18,0x408, -0x405,0x405,0x3f0,0x3f0,0x18,0x18,0x948,0x948,0x948,0x948,0x948,0x948,0x948,0x948,0x948,0x948, -0x405,0x405,0x3fc,0x3fc,0x3f9,0x3f9,0x3f9,0x3f9,0x3f9,0x3fc,0x3f9,0x1125,0x184b,0x1848,0x18f0,0x18, -0x1b,0xcb4,0x40b,0xcb7,0x1b,0x417,0x417,0x417,0x417,0x417,0x417,0x1b,0x1b,0x1b,0x1b,0x417, -0x417,0x1b,0x1b,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x417, -0x417,0x1b,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x1b,0x417,0x41a,0x1b,0x417,0x41a,0x1b, -0x417,0x417,0x1b,0x1b,0x40e,0x1b,0x414,0x414,0x414,0x40b,0x40b,0x1b,0x1b,0x1b,0x1b,0x40b, -0x40b,0x1b,0x1b,0x40b,0x40b,0x411,0x1b,0x1b,0x1b,0xf81,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, -0x1b,0x41a,0x41a,0x41a,0x417,0x1b,0x41a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x94b,0x94b, -0x94b,0x94b,0x94b,0x94b,0x94b,0x94b,0x94b,0x94b,0x40b,0x40b,0x417,0x417,0x417,0xf81,0x18f3,0x1b, -0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1e,0x41d,0x41d,0x426,0x1e,0x429,0x429,0x429, -0x429,0x429,0x429,0x429,0xcc0,0x429,0x1e,0x429,0x429,0x429,0x1e,0x429,0x429,0x429,0x429,0x429, -0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x1e,0x429,0x429,0x429,0x429,0x429,0x429, -0x429,0x1e,0x429,0x429,0x1e,0x429,0x429,0x429,0x429,0x429,0x1e,0x1e,0x420,0x429,0x426,0x426, -0x426,0x41d,0x41d,0x41d,0x41d,0x41d,0x1e,0x41d,0x41d,0x426,0x1e,0x426,0x426,0x423,0x1e,0x1e, -0x429,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, -0x429,0xcc0,0xcba,0xcba,0x1e,0x1e,0x94e,0x94e,0x94e,0x94e,0x94e,0x94e,0x94e,0x94e,0x94e,0x94e, -0x13d4,0xcbd,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x16cb,0x184e,0x184e,0x184e,0x1851,0x1851,0x1851, -0x21,0x42c,0x43b,0x43b,0x21,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x21,0x21,0x441, -0x441,0x21,0x21,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441, -0x441,0x21,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x21,0x441,0x441,0x21,0xcc3,0x441,0x441, -0x441,0x441,0x21,0x21,0x42f,0x441,0x42c,0x42c,0x43b,0x42c,0x42c,0x42c,0xf84,0x21,0x21,0x43b, -0x43e,0x21,0x21,0x43e,0x43e,0x432,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x1a5b,0x42c,0x42c, -0x21,0x21,0x21,0x21,0x444,0x444,0x21,0x441,0x441,0x441,0xf84,0xf84,0x21,0x21,0x438,0x438, -0x438,0x438,0x438,0x438,0x438,0x438,0x438,0x438,0x435,0xcc3,0x12fc,0x12fc,0x12fc,0x12fc,0x12fc,0x12fc, -0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x24,0x24,0x447,0x453,0x24,0x453,0x453,0x453, -0x453,0x453,0x453,0x24,0x24,0x24,0x453,0x453,0x453,0x24,0x453,0x453,0x456,0x453,0x24,0x24, -0x24,0x453,0x453,0x24,0x453,0x24,0x453,0x453,0x24,0x24,0x24,0x453,0x453,0x24,0x24,0x24, -0x453,0x453,0x453,0x24,0x24,0x24,0x453,0x453,0x453,0x453,0x453,0x453,0x453,0x453,0xda7,0x453, -0x453,0x453,0x24,0x24,0x24,0x24,0x447,0x44d,0x447,0x44d,0x44d,0x24,0x24,0x24,0x44d,0x44d, -0x44d,0x24,0x450,0x450,0x450,0x44a,0x24,0x24,0xf87,0x24,0x24,0x24,0x24,0x24,0x24,0x447, -0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0xebb,0x954,0x954,0x954,0x954,0x954, -0x954,0x954,0x954,0x954,0x951,0x951,0x951,0xd77,0xcc6,0xcc6,0xcc6,0xcc6,0xcc6,0xcc9,0xcc6,0x24, -0x24,0x24,0x24,0x24,0x14be,0x465,0x465,0x465,0x18f6,0x468,0x468,0x468,0x468,0x468,0x468,0x468, -0x468,0x27,0x468,0x468,0x468,0x27,0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x468, -0x468,0x468,0x468,0x468,0x468,0x27,0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x468, -0x14c1,0x468,0x468,0x468,0x468,0x468,0x27,0x27,0x1b00,0xf90,0x459,0x459,0x459,0x465,0x465,0x465, -0x465,0x27,0x459,0x459,0x45c,0x27,0x459,0x459,0x459,0x45f,0x27,0x27,0x27,0x27,0x27,0x27, -0x27,0x459,0x459,0x27,0xf90,0xf90,0x16ce,0x27,0x27,0x1b03,0x27,0x27,0x468,0x468,0xf8a,0xf8a, -0x27,0x27,0x462,0x462,0x462,0x462,0x462,0x462,0x462,0x462,0x462,0x462,0x27,0x27,0x27,0x27, -0x27,0x27,0x27,0x19bf,0xf8d,0xf8d,0xf8d,0xf8d,0xf8d,0xf8d,0xf8d,0xf8d,0x178e,0x14c4,0x471,0x471, -0x18f9,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x2a,0x477,0x477,0x477,0x2a,0x477,0x477, -0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x2a,0x477,0x477, -0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x2a,0x477,0x477,0x477,0x477,0x477,0x2a,0x2a, -0xccc,0xccf,0x471,0x46b,0x474,0x471,0x46b,0x471,0x471,0x2a,0x46b,0x474,0x474,0x2a,0x474,0x474, -0x46b,0x46e,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x46b,0x46b,0x2a,0x2a,0x2a,0x2a,0x2a, -0x2a,0x1b06,0x477,0x2a,0x477,0x477,0xed3,0xed3,0x2a,0x2a,0x957,0x957,0x957,0x957,0x957,0x957, -0x957,0x957,0x957,0x957,0x2a,0xed6,0xed6,0x1bc9,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, -0x2a,0x2a,0x2a,0x2a,0x1854,0x14c7,0x483,0x483,0x1a5e,0x489,0x489,0x489,0x489,0x489,0x489,0x489, -0x489,0x2d,0x489,0x489,0x489,0x2d,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489, -0x489,0x489,0x489,0x489,0x483,0x47a,0x47a,0x47a,0xf93,0x2d,0x483,0x483,0x483,0x2d,0x486,0x486, -0x486,0x47d,0x1302,0x1791,0x2d,0x2d,0x2d,0x2d,0x1794,0x1794,0x1794,0x47a,0x1791,0x1791,0x1791,0x1791, -0x1791,0x1791,0x1791,0x16d1,0x489,0x489,0xf93,0xf93,0x2d,0x2d,0x480,0x480,0x480,0x480,0x480,0x480, -0x480,0x480,0x480,0x480,0xf96,0xf96,0xf96,0xf96,0xf96,0xf96,0x1791,0x1791,0x1791,0xf99,0xf9c,0xf9c, -0xf9c,0xf9c,0xf9c,0xf9c,0x30,0x1a61,0xa23,0xa23,0x30,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29, -0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0x30,0x30,0x30,0xa29,0xa29, -0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29, -0xa29,0xa29,0x30,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0x30,0xa29,0x30,0x30, -0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0x30,0x30,0x30,0xa1d,0x30,0x30,0x30,0x30,0xa1a, -0xa23,0xa23,0xa1a,0xa1a,0xa1a,0x30,0xa1a,0x30,0xa23,0xa23,0xa26,0xa23,0xa26,0xa26,0xa26,0xa1a, -0x30,0x30,0x30,0x30,0x30,0x30,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca,0x14ca, -0x30,0x30,0xa23,0xa23,0xa20,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, -0x33,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4, +6,6,6,6,6,6,6,6,6,6,6,6,0xd53,0xd53,0xd53,0xd53, +0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,6,6,6,6, +6,6,6,6,6,6,6,6,6,6,6,6,0x14c4,0x3f0,0x3ff,0x3ff, +0x18,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x18,0x18,0x405,0x405,0x18,0x18,0x405, +0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x405,0x18,0x405,0x405, +0x405,0x405,0x405,0x405,0x405,0x18,0x405,0x18,0x18,0x18,0x405,0x405,0x405,0x405,0x18,0x18, +0x3f3,0xcb4,0x3f0,0x3ff,0x3ff,0x3f0,0x3f0,0x3f0,0x3f0,0x18,0x18,0x3ff,0x3ff,0x18,0x18,0x402, +0x402,0x3f6,0xda7,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3f0,0x18,0x18,0x18,0x18, +0x408,0x408,0x18,0x408,0x405,0x405,0x3f0,0x3f0,0x18,0x18,0x948,0x948,0x948,0x948,0x948,0x948, +0x948,0x948,0x948,0x948,0x405,0x405,0x3fc,0x3fc,0x3f9,0x3f9,0x3f9,0x3f9,0x3f9,0x3fc,0x3f9,0x112b, +0x185a,0x1857,0x18ff,0x18,0x1b,0xcb7,0x40b,0xcba,0x1b,0x417,0x417,0x417,0x417,0x417,0x417,0x1b, +0x1b,0x1b,0x1b,0x417,0x417,0x1b,0x1b,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x417, +0x417,0x417,0x417,0x417,0x417,0x1b,0x417,0x417,0x417,0x417,0x417,0x417,0x417,0x1b,0x417,0x41a, +0x1b,0x417,0x41a,0x1b,0x417,0x417,0x1b,0x1b,0x40e,0x1b,0x414,0x414,0x414,0x40b,0x40b,0x1b, +0x1b,0x1b,0x1b,0x40b,0x40b,0x1b,0x1b,0x40b,0x40b,0x411,0x1b,0x1b,0x1b,0xf84,0x1b,0x1b, +0x1b,0x1b,0x1b,0x1b,0x1b,0x41a,0x41a,0x41a,0x417,0x1b,0x41a,0x1b,0x1b,0x1b,0x1b,0x1b, +0x1b,0x1b,0x94b,0x94b,0x94b,0x94b,0x94b,0x94b,0x94b,0x94b,0x94b,0x94b,0x40b,0x40b,0x417,0x417, +0x417,0xf84,0x1902,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1e,0x41d,0x41d,0x426, +0x1e,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0xcc3,0x429,0x1e,0x429,0x429,0x429,0x1e,0x429, +0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x429,0x1e,0x429,0x429, +0x429,0x429,0x429,0x429,0x429,0x1e,0x429,0x429,0x1e,0x429,0x429,0x429,0x429,0x429,0x1e,0x1e, +0x420,0x429,0x426,0x426,0x426,0x41d,0x41d,0x41d,0x41d,0x41d,0x1e,0x41d,0x41d,0x426,0x1e,0x426, +0x426,0x423,0x1e,0x1e,0x429,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, +0x1e,0x1e,0x1e,0x1e,0x429,0xcc3,0xcbd,0xcbd,0x1e,0x1e,0x94e,0x94e,0x94e,0x94e,0x94e,0x94e, +0x94e,0x94e,0x94e,0x94e,0x13dd,0xcc0,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x16da,0x185d,0x185d, +0x185d,0x1860,0x1860,0x1860,0x21,0x42c,0x43b,0x43b,0x21,0x441,0x441,0x441,0x441,0x441,0x441,0x441, +0x441,0x21,0x21,0x441,0x441,0x21,0x21,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x441, +0x441,0x441,0x441,0x441,0x441,0x21,0x441,0x441,0x441,0x441,0x441,0x441,0x441,0x21,0x441,0x441, +0x21,0xcc6,0x441,0x441,0x441,0x441,0x21,0x21,0x42f,0x441,0x42c,0x42c,0x43b,0x42c,0x42c,0x42c, +0xf87,0x21,0x21,0x43b,0x43e,0x21,0x21,0x43e,0x43e,0x432,0x21,0x21,0x21,0x21,0x21,0x21, +0x21,0x1a6d,0x42c,0x42c,0x21,0x21,0x21,0x21,0x444,0x444,0x21,0x441,0x441,0x441,0xf87,0xf87, +0x21,0x21,0x438,0x438,0x438,0x438,0x438,0x438,0x438,0x438,0x438,0x438,0x435,0xcc6,0x1302,0x1302, +0x1302,0x1302,0x1302,0x1302,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x24,0x24,0x447,0x453, +0x24,0x453,0x453,0x453,0x453,0x453,0x453,0x24,0x24,0x24,0x453,0x453,0x453,0x24,0x453,0x453, +0x456,0x453,0x24,0x24,0x24,0x453,0x453,0x24,0x453,0x24,0x453,0x453,0x24,0x24,0x24,0x453, +0x453,0x24,0x24,0x24,0x453,0x453,0x453,0x24,0x24,0x24,0x453,0x453,0x453,0x453,0x453,0x453, +0x453,0x453,0xdaa,0x453,0x453,0x453,0x24,0x24,0x24,0x24,0x447,0x44d,0x447,0x44d,0x44d,0x24, +0x24,0x24,0x44d,0x44d,0x44d,0x24,0x450,0x450,0x450,0x44a,0x24,0x24,0xf8a,0x24,0x24,0x24, +0x24,0x24,0x24,0x447,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0xebe,0x954, +0x954,0x954,0x954,0x954,0x954,0x954,0x954,0x954,0x951,0x951,0x951,0xd7a,0xcc9,0xcc9,0xcc9,0xcc9, +0xcc9,0xccc,0xcc9,0x24,0x24,0x24,0x24,0x24,0x14c7,0x465,0x465,0x465,0x1905,0x468,0x468,0x468, +0x468,0x468,0x468,0x468,0x468,0x27,0x468,0x468,0x468,0x27,0x468,0x468,0x468,0x468,0x468,0x468, +0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x468,0x27,0x468,0x468,0x468,0x468,0x468,0x468, +0x468,0x468,0x468,0x468,0x14ca,0x468,0x468,0x468,0x468,0x468,0x27,0x27,0x1b12,0xf93,0x459,0x459, +0x459,0x465,0x465,0x465,0x465,0x27,0x459,0x459,0x45c,0x27,0x459,0x459,0x459,0x45f,0x27,0x27, +0x27,0x27,0x27,0x27,0x27,0x459,0x459,0x27,0xf93,0xf93,0x16dd,0x27,0x27,0x1b15,0x27,0x27, +0x468,0x468,0xf8d,0xf8d,0x27,0x27,0x462,0x462,0x462,0x462,0x462,0x462,0x462,0x462,0x462,0x462, +0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x19d1,0xf90,0xf90,0xf90,0xf90,0xf90,0xf90,0xf90,0xf90, +0x179d,0x14cd,0x471,0x471,0x1908,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x2a,0x477,0x477, +0x477,0x2a,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477, +0x477,0x2a,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x477,0x2a,0x477,0x477,0x477, +0x477,0x477,0x2a,0x2a,0xccf,0xcd2,0x471,0x46b,0x474,0x471,0x46b,0x471,0x471,0x2a,0x46b,0x474, +0x474,0x2a,0x474,0x474,0x46b,0x46e,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x46b,0x46b,0x2a, +0x2a,0x2a,0x2a,0x2a,0x2a,0x1b18,0x477,0x2a,0x477,0x477,0xed6,0xed6,0x2a,0x2a,0x957,0x957, +0x957,0x957,0x957,0x957,0x957,0x957,0x957,0x957,0x2a,0xed9,0xed9,0x1bdb,0x2a,0x2a,0x2a,0x2a, +0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x1863,0x14d0,0x483,0x483,0x1a70,0x489,0x489,0x489, +0x489,0x489,0x489,0x489,0x489,0x2d,0x489,0x489,0x489,0x2d,0x489,0x489,0x489,0x489,0x489,0x489, +0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x483,0x47a,0x47a,0x47a,0xf96,0x2d,0x483,0x483, +0x483,0x2d,0x486,0x486,0x486,0x47d,0x1308,0x17a0,0x2d,0x2d,0x2d,0x2d,0x17a3,0x17a3,0x17a3,0x47a, +0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x17a0,0x16e0,0x489,0x489,0xf96,0xf96,0x2d,0x2d,0x480,0x480, +0x480,0x480,0x480,0x480,0x480,0x480,0x480,0x480,0xf99,0xf99,0xf99,0xf99,0xf99,0xf99,0x17a0,0x17a0, +0x17a0,0xf9c,0xf9f,0xf9f,0xf9f,0xf9f,0xf9f,0xf9f,0x30,0x1a73,0xa23,0xa23,0x30,0xa29,0xa29,0xa29, +0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0x30, +0x30,0x30,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29, +0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0x30,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29, +0x30,0xa29,0x30,0x30,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0xa29,0x30,0x30,0x30,0xa1d,0x30, +0x30,0x30,0x30,0xa1a,0xa23,0xa23,0xa1a,0xa1a,0xa1a,0x30,0xa1a,0x30,0xa23,0xa23,0xa26,0xa23, +0xa26,0xa26,0xa26,0xa1a,0x30,0x30,0x30,0x30,0x30,0x30,0x14d3,0x14d3,0x14d3,0x14d3,0x14d3,0x14d3, +0x14d3,0x14d3,0x14d3,0x14d3,0x30,0x30,0xa23,0xa23,0xa20,0x30,0x30,0x30,0x30,0x30,0x30,0x30, +0x30,0x30,0x30,0x30,0x33,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4, 0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x4a4, -0x4a4,0x48f,0x4a4,0x4a1,0x48f,0x48f,0x48f,0x48f,0x48f,0x48f,0x495,0x33,0x33,0x33,0x33,0x48c, -0x4aa,0x4aa,0x4aa,0x4aa,0x4aa,0x4a4,0x4a7,0x492,0x492,0x492,0x492,0x492,0x492,0x48f,0x492,0x498, -0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49b,0x49b,0x33,0x33,0x33,0x33, +0x4a4,0x4a4,0x4a4,0x4a4,0x4a4,0x48f,0x4a4,0x4a1,0x48f,0x48f,0x48f,0x48f,0x48f,0x48f,0x495,0x33, +0x33,0x33,0x33,0x48c,0x4aa,0x4aa,0x4aa,0x4aa,0x4aa,0x4a4,0x4a7,0x492,0x492,0x492,0x492,0x492, +0x492,0x48f,0x492,0x498,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49b,0x49b, 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, -0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x4b9,0x4b9,0x36, -0x4b9,0x36,0x19c5,0x4b9,0x4b9,0x19c5,0x4b9,0x36,0x19c5,0x4b9,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5, -0x4b9,0x4b9,0x4b9,0x4b9,0x19c5,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x19c5,0x4b9,0x4b9,0x4b9, -0x36,0x4b9,0x36,0x4b9,0x19c5,0x19c5,0x4b9,0x4b9,0x19c5,0x4b9,0x4b9,0x4b9,0x4b9,0x4ad,0x4b9,0x4b6, -0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x19c2,0x4ad,0x4ad,0x4b9,0x36,0x36,0x4c2,0x4c2,0x4c2,0x4c2, -0x4c2,0x36,0x4bf,0x36,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4ad,0x1bcc,0x36,0x4b3,0x4b3,0x4b3,0x4b3, -0x4b3,0x4b3,0x4b3,0x4b3,0x4b3,0x4b3,0x36,0x36,0x4bc,0x4bc,0x13d7,0x13d7,0x36,0x36,0x36,0x36, +0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, +0x36,0x4b9,0x4b9,0x36,0x4b9,0x36,0x19d7,0x4b9,0x4b9,0x19d7,0x4b9,0x36,0x19d7,0x4b9,0x19d7,0x19d7, +0x19d7,0x19d7,0x19d7,0x19d7,0x4b9,0x4b9,0x4b9,0x4b9,0x19d7,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9,0x4b9, +0x19d7,0x4b9,0x4b9,0x4b9,0x36,0x4b9,0x36,0x4b9,0x19d7,0x19d7,0x4b9,0x4b9,0x19d7,0x4b9,0x4b9,0x4b9, +0x4b9,0x4ad,0x4b9,0x4b6,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x4ad,0x19d4,0x4ad,0x4ad,0x4b9,0x36,0x36, +0x4c2,0x4c2,0x4c2,0x4c2,0x4c2,0x36,0x4bf,0x36,0x4b0,0x4b0,0x4b0,0x4b0,0x4b0,0x4ad,0x1bde,0x36, +0x4b3,0x4b3,0x4b3,0x4b3,0x4b3,0x4b3,0x4b3,0x4b3,0x4b3,0x4b3,0x36,0x36,0x4bc,0x4bc,0x13e0,0x13e0, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, -0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x99c,0x99c,0x99c,0x99f, -0x99c,0x99c,0x99c,0x99c,0x39,0x99c,0x99c,0x99c,0x99c,0x99f,0x99c,0x99c,0x99c,0x99c,0x99f,0x99c, -0x99c,0x99c,0x99c,0x99f,0x99c,0x99c,0x99c,0x99c,0x99f,0x99c,0x99c,0x99c,0x99c,0x99c,0x99c,0x99c, -0x99c,0x99c,0x99c,0x99c,0x99c,0x99f,0xa38,0xfa8,0xfa8,0x39,0x39,0x39,0x39,0x966,0x966,0x969, -0x966,0x969,0x969,0x975,0x969,0x975,0x966,0x966,0x966,0x966,0x966,0x996,0x966,0x969,0x96f,0x96f, -0x972,0x97b,0x96c,0x96c,0x99c,0x99c,0x99c,0x99c,0x130b,0x1305,0x1305,0x1305,0x966,0x966,0x966,0x969, -0x966,0x966,0xa2c,0x966,0x39,0x966,0x966,0x966,0x966,0x969,0x966,0x966,0x966,0x966,0x969,0x966, -0x966,0x966,0x966,0x969,0x966,0x966,0x966,0x966,0x969,0x966,0xa2c,0xa2c,0xa2c,0x966,0x966,0x966, -0x966,0x966,0x966,0x966,0xa2c,0x969,0xa2c,0xa2c,0xa2c,0x39,0xa35,0xa35,0xa32,0xa32,0xa32,0xa32, -0xa32,0xa32,0xa2f,0xa32,0xa32,0xa32,0xa32,0xa32,0xa32,0x39,0xf9f,0xa32,0xdaa,0xdaa,0xfa2,0xfa5, -0xf9f,0x1128,0x1128,0x1128,0x1128,0x1308,0x1308,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, +0x99c,0x99c,0x99c,0x99f,0x99c,0x99c,0x99c,0x99c,0x39,0x99c,0x99c,0x99c,0x99c,0x99f,0x99c,0x99c, +0x99c,0x99c,0x99f,0x99c,0x99c,0x99c,0x99c,0x99f,0x99c,0x99c,0x99c,0x99c,0x99f,0x99c,0x99c,0x99c, +0x99c,0x99c,0x99c,0x99c,0x99c,0x99c,0x99c,0x99c,0x99c,0x99f,0xa38,0xfab,0xfab,0x39,0x39,0x39, +0x39,0x966,0x966,0x969,0x966,0x969,0x969,0x975,0x969,0x975,0x966,0x966,0x966,0x966,0x966,0x996, +0x966,0x969,0x96f,0x96f,0x972,0x97b,0x96c,0x96c,0x99c,0x99c,0x99c,0x99c,0x1311,0x130b,0x130b,0x130b, +0x966,0x966,0x966,0x969,0x966,0x966,0xa2c,0x966,0x39,0x966,0x966,0x966,0x966,0x969,0x966,0x966, +0x966,0x966,0x969,0x966,0x966,0x966,0x966,0x969,0x966,0x966,0x966,0x966,0x969,0x966,0xa2c,0xa2c, +0xa2c,0x966,0x966,0x966,0x966,0x966,0x966,0x966,0xa2c,0x969,0xa2c,0xa2c,0xa2c,0x39,0xa35,0xa35, +0xa32,0xa32,0xa32,0xa32,0xa32,0xa32,0xa2f,0xa32,0xa32,0xa32,0xa32,0xa32,0xa32,0x39,0xfa2,0xa32, +0xdad,0xdad,0xfa5,0xfa8,0xfa2,0x112e,0x112e,0x112e,0x112e,0x130e,0x130e,0x39,0x39,0x39,0x39,0x39, 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, -0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x3c,0x13dd, -0x3c,0x3c,0x3c,0x3c,0x3c,0x13dd,0x3c,0x3c,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5, -0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdb9, +0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x4c8,0x4c8,0x4c8,0x4c8, +0x4c8,0x4c8,0x3c,0x13e6,0x3c,0x3c,0x3c,0x3c,0x3c,0x13e6,0x3c,0x3c,0x4c5,0x4c5,0x4c5,0x4c5, +0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0xa62,0xa62,0xa62,0xa62, +0xa62,0xa62,0xa62,0xdbc,0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62, +0xa62,0xa62,0xa62,0x3f,0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62, +0xa62,0xa62,0xa62,0xdbc,0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62, +0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdbc, 0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0x3f, -0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdb9, -0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, -0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdb9,0xa62,0x3f,0xa62,0xa62, -0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0x3f,0xa62,0x3f,0xa62,0xa62, -0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdb9,0xa62,0xa62,0xa62,0xa62, -0xa62,0xa62,0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, -0xa62,0xa62,0xa62,0xdb9,0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62, -0xa62,0xa62,0xa62,0xdb9,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, -0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0x130e,0x130e,0xdb3,0xdb6,0xa5c,0xa65,0xa59, -0xa59,0xa59,0xa59,0xa65,0xa65,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f,0xa56,0xa56, -0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0x3f,0x3f,0x3f,0xa68,0xa68,0xa68,0xa68, +0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdbc, +0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, +0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdbc,0xa62,0x3f,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f, +0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdbc,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, +0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0x3f,0x3f,0x1314,0x1314,0xdb6, +0xdb9,0xa5c,0xa65,0xa59,0xa59,0xa59,0xa59,0xa65,0xa65,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f,0xa5f, +0xa5f,0xa5f,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0xa56,0x3f,0x3f,0x3f, 0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68, -0xa68,0x16d7,0x42,0x42,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x16d4,0x42,0x42,0xa7a,0xa7d,0xa7d,0xa7d, -0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d, -0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa77,0xa74,0x45,0x45,0x45,0xa83,0xa83,0xa83,0xa83, -0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa80,0xa80,0xa80,0xa83,0xa83,0xa83,0x14cd,0x14cd,0x14cd, -0x14cd,0x14cd,0x14cd,0x14cd,0x14cd,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0xaa4,0xaa4,0xaa4,0xaa4, -0xaa4,0xaa4,0xa86,0xaa4,0xaa4,0xa89,0xa89,0xa89,0xa89,0xa89,0xa89,0xa89,0xa89,0xa89,0xa8c,0xa89, -0xa9b,0xa9b,0xa9e,0xaa7,0xa95,0xa92,0xa9b,0xa98,0xaa7,0xcd2,0x4b,0x4b,0xaa1,0xaa1,0xaa1,0xaa1, -0xaa1,0xaa1,0xaa1,0xaa1,0xaa1,0xaa1,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0xcd5,0xcd5,0xcd5,0xcd5, -0xcd5,0xcd5,0xcd5,0xcd5,0xcd5,0xcd5,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0xab6,0xab6,0xb2e,0xb31, -0xabc,0xb2b,0xab9,0xab6,0xabf,0xace,0xac2,0xad1,0xad1,0xad1,0xaad,0x1b09,0xac5,0xac5,0xac5,0xac5, -0xac5,0xac5,0xac5,0xac5,0xac5,0xac5,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0xac8,0xac8,0xac8,0xac8, -0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8, -0xac8,0xac8,0xac8,0xac8,0x18fc,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0xac8,0xac8,0xac8,0xac8, -0xac8,0xac8,0xac8,0xac8,0xac8,0xab0,0xfc6,0x4e,0x4e,0x4e,0x4e,0x4e,0x117f,0x117f,0x117f,0x117f, -0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e6,0x4e6,0x51,0x51,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x51,0x51,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e6,0x4e6,0x4e6,0x4e6,0x51,0x4e9,0x51,0x4e9,0x51,0x4e9,0x51,0x4e9,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x51,0x51,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e6,0x51,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e0,0x4e6,0x4e0,0x4e0,0x4dd,0x4e6,0x4e6, -0x4e6,0x51,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4dd,0x4dd,0x4dd,0x4e6,0x4e6,0x4e6,0x4e6, -0x51,0x51,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x51,0x4dd,0x4dd,0x4dd,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4dd,0x4dd,0x4dd,0x51,0x51,0x4e6,0x4e6, -0x4e6,0x51,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e3,0x4e0,0x51,0xba6,0xba9,0xba9,0xba9, -0xfcf,0x54,0x14a9,0x14a9,0x14a9,0x14a9,0x4f2,0x4f2,0x4f2,0x4f2,0x4f2,0x4f2,0x53d,0xbbb,0x57,0x57, -0x6d8,0x53d,0x53d,0x53d,0x53d,0x53d,0x543,0x555,0x543,0x54f,0x549,0x6db,0x53a,0x6d5,0x6d5,0x6d5, -0x6d5,0x53a,0x53a,0x53a,0x53a,0x53a,0x540,0x552,0x540,0x54c,0x546,0x57,0xdc2,0xdc2,0xdc2,0xdc2, -0xdc2,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x1311,0x57,0x57,0x57,0x1b0c,0x5a,0x5a,0x5a, -0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x564,0x564,0x564,0x564, -0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x561,0x561,0x561,0x561,0x564,0xadd,0xadd, -0xbc1,0xbc7,0xbc7,0xbc4,0xbc4,0xbc4,0xbc4,0xdc8,0xed9,0xed9,0xed9,0xed9,0x1113,0x5d,0x5d,0x5d, -0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x594,0x594,0x594,0xae6, -0xee2,0xfd5,0xfd5,0xfd5,0xfd5,0x126f,0x16dd,0x16dd,0x60,0x60,0x60,0x60,0x702,0x702,0x702,0x702, -0x702,0x702,0x702,0x702,0x702,0x702,0x5a0,0x5a0,0x59d,0x59d,0x59d,0x59d,0x5c1,0x5c1,0x5c1,0x5c1, -0x5c1,0xaef,0xaef,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, -0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x5c4,0x5c4,0x5c4,0x5c4, -0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66, -0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0xb0a,0xb0a,0xb0a,0xb0a, -0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a, -0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0x69,0xb0a,0xb0a,0xb0a,0xb0a,0xb0d,0xb0a,0xb0a,0xb0a,0xb0a, -0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0d, -0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0xb10,0xb10,0xb10,0xb10, -0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10, -0xb10,0xb10,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x72,0x822,0x81c,0x822, -0x81c,0x822,0x81c,0x822,0x81c,0x822,0x81c,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c, -0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81c,0x81c,0x81c,0x822, -0x81c,0x822,0x81c,0x822,0x81c,0x81c,0x81c,0x81c,0x81c,0x81c,0x822,0x81c,0x81c,0x81c,0x81c,0x81c, -0x81f,0xc60,0xc60,0x72,0x72,0x936,0x936,0x8fd,0x8fd,0x825,0x828,0xc5d,0x75,0x75,0x75,0x75, -0x75,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a, -0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x1101,0x18c3,0x19aa, -0x78,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d, -0x83d,0x83d,0x83d,0x78,0x906,0x906,0x909,0x909,0x909,0x909,0x909,0x909,0x909,0x909,0x909,0x909, -0x909,0x909,0x909,0x909,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846, +0xa68,0xa68,0xa68,0xa68,0xa68,0x16e6,0x42,0x42,0x16e3,0x16e3,0x16e3,0x16e3,0x16e3,0x16e3,0x42,0x42, +0xa7a,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d, +0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa7d,0xa77,0xa74,0x45,0x45,0x45, +0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa80,0xa80,0xa80,0xa83,0xa83, +0xa83,0x14d6,0x14d6,0x14d6,0x14d6,0x14d6,0x14d6,0x14d6,0x14d6,0x48,0x48,0x48,0x48,0x48,0x48,0x48, +0xaa4,0xaa4,0xaa4,0xaa4,0xaa4,0xaa4,0xa86,0xaa4,0xaa4,0xa89,0xa89,0xa89,0xa89,0xa89,0xa89,0xa89, +0xa89,0xa89,0xa8c,0xa89,0xaad,0xaad,0xa9e,0xaa7,0xa95,0xa92,0xa9b,0xa98,0xaa7,0xcd5,0x4b,0x4b, +0xaa1,0xaa1,0xaa1,0xaa1,0xaa1,0xaa1,0xaa1,0xaa1,0xaa1,0xaa1,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b, +0xcd8,0xcd8,0xcd8,0xcd8,0xcd8,0xcd8,0xcd8,0xcd8,0xcd8,0xcd8,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b, +0xab9,0xab9,0xb31,0xb34,0xabf,0xb2e,0xabc,0xab9,0xac2,0xad1,0xac5,0xad4,0xad4,0xad4,0xab0,0x1b1b, +0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, +0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb, +0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0x190b,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, +0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xab3,0xfc9,0x4e,0x4e,0x4e,0x4e,0x4e, +0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x51,0x51,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x51,0x51, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x51,0x4e9,0x51,0x4e9,0x51,0x4e9,0x51,0x4e9, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x51,0x51, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x51,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e0,0x4e6,0x4e0, +0x4e0,0x4dd,0x4e6,0x4e6,0x4e6,0x51,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4dd,0x4dd,0x4dd, +0x4e6,0x4e6,0x4e6,0x4e6,0x51,0x51,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x51,0x4dd,0x4dd,0x4dd, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4dd,0x4dd,0x4dd, +0x51,0x51,0x4e6,0x4e6,0x4e6,0x51,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e3,0x4e0,0x51, +0xba9,0xbac,0xbac,0xbac,0xfd2,0x54,0x14b2,0x14b2,0x14b2,0x14b2,0x4f2,0x4f2,0x4f2,0x4f2,0x4f2,0x4f2, +0x53d,0xbbe,0x57,0x57,0x6d8,0x53d,0x53d,0x53d,0x53d,0x53d,0x543,0x555,0x543,0x54f,0x549,0x6db, +0x53a,0x6d5,0x6d5,0x6d5,0x6d5,0x53a,0x53a,0x53a,0x53a,0x53a,0x540,0x552,0x540,0x54c,0x546,0x57, +0xdc5,0xdc5,0xdc5,0xdc5,0xdc5,0x1317,0x1317,0x1317,0x1317,0x1317,0x1317,0x1317,0x1317,0x57,0x57,0x57, +0x1b1e,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, +0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x564,0x561,0x561,0x561, +0x561,0x564,0xae0,0xae0,0xbc4,0xbca,0xbca,0xbc7,0xbc7,0xbc7,0xbc7,0xdcb,0xedc,0xedc,0xedc,0xedc, +0x1119,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, +0x594,0x594,0x594,0xae9,0xee5,0xfd8,0xfd8,0xfd8,0xfd8,0x1275,0x16ec,0x16ec,0x60,0x60,0x60,0x60, +0x702,0x702,0x702,0x702,0x702,0x702,0x702,0x702,0x702,0x702,0x5a0,0x5a0,0x59d,0x59d,0x59d,0x59d, +0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0xaf2,0xaf2,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, +0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, +0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x5c4,0x66,0x66,0x66,0x66,0x66, +0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66, +0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d, +0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0x69,0xb0d,0xb0d,0xb0d,0xb0d,0xb10, +0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d, +0xb0d,0xb0d,0xb0d,0xb10,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69, +0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13, +0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c, +0x6f,0x822,0x81c,0x822,0x81c,0x822,0x81c,0x822,0x81c,0x822,0x81c,0x81c,0x81f,0x81c,0x81f,0x81c, +0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c, +0x81c,0x81c,0x81c,0x822,0x81c,0x822,0x81c,0x822,0x81c,0x81c,0x81c,0x81c,0x81c,0x81c,0x822,0x81c, +0x81c,0x81c,0x81c,0x81c,0x81f,0xc63,0xc63,0x6f,0x6f,0x936,0x936,0x8fd,0x8fd,0x825,0x828,0xc60, +0x72,0x72,0x72,0x72,0x72,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a, +0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a,0x83a, +0x83a,0x1107,0x18d2,0x19bc,0x75,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d, +0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x75,0x906,0x906,0x909,0x909,0x909,0x909,0x909,0x909, +0x909,0x909,0x909,0x909,0x909,0x909,0x909,0x909,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846, 0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846,0x846, -0x846,0xd5c,0xd5c,0x7b,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22, -0xb22,0x7e,0x7e,0x7e,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28, -0xb28,0xb28,0xb28,0xb28,0xb28,0xc69,0xb28,0xb28,0xb28,0xc69,0xb28,0x81,0x81,0x81,0x81,0x81, -0x81,0x81,0x81,0x81,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6, -0x11a6,0x11a6,0x11a6,0x11a6,0x9c0,0x9c0,0x9c0,0x9c0,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, -0x84,0x84,0x84,0x84,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b, -0x121b,0x121b,0x121b,0x121b,0x609,0x609,0x609,0x609,0x609,0x609,0x609,0x87,0x87,0x87,0x87,0x87, -0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x5f7,0x5f7,0x5f7,0x5f7,0x5f7,0x87,0x87,0x87,0x87, -0x87,0xafb,0x5fa,0x600,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x5fd,0x600,0x600, -0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x87,0x600,0x600,0x600,0x600, -0x600,0x87,0x600,0x87,0x600,0x600,0x87,0x600,0x600,0x87,0x600,0x600,0x600,0x600,0x600,0x600, -0x600,0x600,0x600,0x603,0x615,0x60f,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f, -0x612,0x618,0x615,0x60f,0x1323,0x1323,0x1b0f,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a, -0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x615,0x60f,0x612,0x618,0x615,0x60f,0x615,0x60f,0x615, -0x60f,0x615,0x615,0x60f,0x60f,0x60f,0x60f,0x612,0x60f,0x60f,0x612,0x60f,0x612,0x612,0x612,0x60f, -0x612,0x612,0x612,0x612,0x8a,0x8a,0x612,0x612,0x612,0x612,0x60f,0x60f,0x612,0x60f,0x60f,0x60f, -0x60f,0x612,0x60f,0x60f,0x60f,0x60f,0x60f,0x612,0x612,0x612,0x60f,0x60f,0x8a,0x8a,0x8a,0x8a, -0x8a,0x8a,0x8a,0x1b0f,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46, -0xb46,0xb46,0xb46,0xb46,0x85e,0x870,0x86d,0x870,0x86d,0xc7e,0xc7e,0xd68,0xd65,0x861,0x861,0x861, -0x861,0x873,0x873,0x873,0x88b,0x88e,0x89d,0x8d,0x891,0x894,0x8a0,0x8a0,0x888,0x87f,0x879,0x87f, -0x879,0x87f,0x879,0x87c,0x87c,0x897,0x897,0x89a,0x897,0x897,0x897,0x8d,0x897,0x885,0x882,0x87c, -0x8d,0x8d,0x8d,0x8d,0x621,0x62d,0x621,0xbfa,0x621,0x90,0x621,0x62d,0x621,0x62d,0x621,0x62d, -0x621,0x62d,0x621,0x62d,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627, -0x62d,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x62a, -0x624,0x90,0x90,0x61e,0x75f,0x762,0x777,0x77a,0x759,0x762,0x762,0x96,0x741,0x744,0x744,0x744, -0x744,0x741,0x741,0x96,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0xafe,0xafe,0xafe, -0x9c3,0x73b,0x630,0x630,0x96,0x789,0x768,0x759,0x762,0x75f,0x759,0x76b,0x75c,0x756,0x759,0x777, -0x76e,0x765,0x786,0x759,0x783,0x783,0x783,0x783,0x783,0x783,0x783,0x783,0x783,0x783,0x774,0x771, -0x777,0x777,0x777,0x789,0x74a,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747, +0x846,0x846,0x846,0x846,0x846,0xd5f,0xd5f,0x78,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25, +0xb25,0xb25,0xb25,0xb25,0xb25,0x7b,0x7b,0x7b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b, +0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xc6c,0xb2b,0xb2b,0xb2b,0xc6c,0xb2b,0x7e, +0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac, +0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x9c0,0x9c0,0x9c0,0x9c0,0x81,0x81,0x81,0x81, +0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221, +0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x1221,0x609,0x609,0x609,0x609,0x609,0x609,0x609,0x84, +0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x5f7,0x5f7,0x5f7,0x5f7,0x5f7, +0x84,0x84,0x84,0x84,0x84,0xafe,0x5fa,0x600,0x606,0x606,0x606,0x606,0x606,0x606,0x606,0x606, +0x606,0x5fd,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x84, +0x600,0x600,0x600,0x600,0x600,0x84,0x600,0x84,0x600,0x600,0x84,0x600,0x600,0x84,0x600,0x600, +0x600,0x600,0x600,0x600,0x600,0x600,0x600,0x603,0x615,0x60f,0x615,0x60f,0x612,0x618,0x615,0x60f, +0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x1329,0x1329,0x1b21,0x87,0x87,0x87,0x87,0x87, +0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x615,0x60f,0x612,0x618,0x615, +0x60f,0x615,0x60f,0x615,0x60f,0x615,0x615,0x60f,0x60f,0x60f,0x60f,0x612,0x60f,0x60f,0x612,0x60f, +0x612,0x612,0x612,0x60f,0x612,0x612,0x612,0x612,0x87,0x87,0x612,0x612,0x612,0x612,0x60f,0x60f, +0x612,0x60f,0x60f,0x60f,0x60f,0x612,0x60f,0x60f,0x60f,0x60f,0x60f,0x612,0x612,0x612,0x60f,0x60f, +0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x1b21,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49, +0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0x85e,0x870,0x86d,0x870,0x86d,0xc81,0xc81,0xd6b, +0xd68,0x861,0x861,0x861,0x861,0x873,0x873,0x873,0x88b,0x88e,0x89d,0x8a,0x891,0x894,0x8a0,0x8a0, +0x888,0x87f,0x879,0x87f,0x879,0x87f,0x879,0x87c,0x87c,0x897,0x897,0x89a,0x897,0x897,0x897,0x8a, +0x897,0x885,0x882,0x87c,0x8a,0x8a,0x8a,0x8a,0x621,0x62d,0x621,0xbfd,0x621,0x8d,0x621,0x62d, +0x621,0x62d,0x621,0x62d,0x621,0x62d,0x621,0x62d,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627, +0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x62a, +0x624,0x62a,0x624,0x62a,0x624,0x8d,0x8d,0x61e,0x75f,0x762,0x777,0x77a,0x759,0x762,0x762,0x93, +0x741,0x744,0x744,0x744,0x744,0x741,0x741,0x93,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, +0x90,0xb01,0xb01,0xb01,0x9c3,0x73b,0x630,0x630,0x93,0x789,0x768,0x759,0x762,0x75f,0x759,0x76b, +0x75c,0x756,0x759,0x777,0x76e,0x765,0x786,0x759,0x783,0x783,0x783,0x783,0x783,0x783,0x783,0x783, +0x783,0x783,0x774,0x771,0x777,0x777,0x777,0x789,0x74a,0x747,0x747,0x747,0x747,0x747,0x747,0x747, 0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x747, -0x747,0x747,0x747,0x96,0x96,0x96,0x747,0x747,0x747,0x747,0x747,0x747,0x96,0x96,0x747,0x747, -0x747,0x747,0x747,0x747,0x96,0x96,0x747,0x747,0x747,0x747,0x747,0x747,0x96,0x96,0x747,0x747, -0x747,0x96,0x96,0x96,0xb49,0xb49,0xb49,0xb49,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, -0x99,0x1860,0x1860,0x1860,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f, -0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0x9c,0x9c,0x9c,0x9c,0x9c,0x1626,0x1626,0x1626,0x1626, -0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0xb58,0xb58,0xb58,0xb58, -0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58, -0xb58,0xb58,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb64,0xa2,0xa2,0xfe1,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0x16e3,0x16e3,0x16e3,0x16e3, -0x16e3,0x16e3,0x16e3,0x16e3,0x16e3,0x1b12,0x1b12,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2, -0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xa5,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb7c,0xb7c,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb7c,0xa5,0xb7c,0xb7c,0xa5,0xa5,0xb7c,0xa5, -0xa5,0xb7c,0xb7c,0xa5,0xa5,0xb7c,0xb7c,0xb7c,0xb7c,0xa5,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb79,0xb79,0xb79,0xb79,0xa5,0xb79,0xa5,0xb79,0xb79,0xb79,0xb79,0xcf0,0xb79,0xb79, -0xa5,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb79,0xb79,0xb79,0xb79, -0xb7c,0xb7c,0xa5,0xb7c,0xb7c,0xb7c,0xb7c,0xa5,0xa5,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xa5,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xa5,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb7c,0xb7c,0xa5,0xb7c,0xb7c,0xb7c,0xb7c,0xa5,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xa5,0xb7c,0xa5,0xa5,0xa5,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xa5,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xdda,0xdda,0xa5,0xa5, +0x747,0x747,0x747,0x747,0x747,0x747,0x747,0x93,0x93,0x93,0x747,0x747,0x747,0x747,0x747,0x747, +0x93,0x93,0x747,0x747,0x747,0x747,0x747,0x747,0x93,0x93,0x747,0x747,0x747,0x747,0x747,0x747, +0x93,0x93,0x747,0x747,0x747,0x93,0x93,0x93,0xb4c,0xb4c,0xb4c,0xb4c,0x96,0x96,0x96,0x96, +0x96,0x96,0x96,0x96,0x96,0x186f,0x186f,0x186f,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52, +0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0x99,0x99,0x99,0x99,0x99, +0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, +0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b, +0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c, +0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0x9f,0x9f,0xfe4,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67, +0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67, +0x16f2,0x16f2,0x16f2,0x16f2,0x16f2,0x16f2,0x16f2,0x16f2,0x16f2,0x1b24,0x1b24,0x9f,0x9f,0x9f,0x9f,0x9f, +0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7c,0xb7c, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xa2,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, +0xb7f,0xb7f,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7f,0xa2,0xb7f,0xb7f, +0xa2,0xa2,0xb7f,0xa2,0xa2,0xb7f,0xb7f,0xa2,0xa2,0xb7f,0xb7f,0xb7f,0xb7f,0xa2,0xb7f,0xb7f, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7c,0xb7c,0xb7c,0xb7c,0xa2,0xb7c,0xa2,0xb7c,0xb7c,0xb7c, +0xb7c,0xcf3,0xb7c,0xb7c,0xa2,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7f,0xb7f,0xa2,0xb7f,0xb7f,0xb7f,0xb7f,0xa2,0xa2,0xb7f,0xb7f,0xb7f, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xa2,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xa2,0xb7c,0xb7c, 0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb79,0xb79,0xb79,0xb73,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xef1,0xeee,0xa5,0xa5,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76, -0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xa8,0xb82,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8, -0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8, -0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09,0xc09, -0xc09,0xc09,0xc09,0xc09,0xc09,0x1b18,0xc09,0xc09,0xc09,0xc09,0xc03,0xc03,0xc06,0x1b15,0xab,0xab, -0xab,0xab,0xab,0xab,0xab,0xab,0xab,0x1b18,0xc12,0xc12,0xc12,0xc12,0xc12,0xc12,0xc12,0xc12, -0xc12,0xc12,0xc12,0xc12,0xc12,0xc12,0xc12,0xc12,0xc12,0xc12,0xc0c,0xc0c,0xc0f,0xc72,0xc72,0xae, -0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18, -0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc18,0xc15,0xc15,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xc1e, -0xc1e,0xc1e,0xc1e,0xc1e,0xc1e,0xb4,0xc1e,0xc1e,0xc1e,0xb4,0xc1b,0xc1b,0xb4,0xb4,0xb4,0xb4, -0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02, -0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02,0xd02, -0xd02,0xd02,0xd02,0xd02,0xd02,0x14e8,0x14e8,0xb7,0xcf3,0xcf3,0xcf3,0xcff,0xcff,0xcff,0xcff,0xcf3, -0xcf3,0xcff,0xcff,0xcff,0xb7,0xb7,0xb7,0xb7,0xcff,0xcff,0xcf3,0xcff,0xcff,0xcff,0xcff,0xcff, -0xcff,0xcf6,0xcf6,0xcf6,0xb7,0xb7,0xb7,0xb7,0xcf9,0xb7,0xb7,0xb7,0xd05,0xd05,0xcfc,0xcfc, -0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xcfc,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08, -0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xd08,0xba,0xba,0xd08,0xd08,0xd08,0xd08, -0xd08,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0x14eb,0x14eb,0x14eb,0x14eb, -0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb, -0xbd,0xbd,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb, -0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0xbd,0x1a64,0x14eb,0x14eb,0x14eb,0x14eb, -0x14eb,0x14eb,0x14eb,0x14eb,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c, -0xc0,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c, -0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xc0,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c, -0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xc0,0xd2c,0xd2c,0xc0,0xd2c, -0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xc0,0xc0, -0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xc0,0xc0, -0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, -0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, -0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f, -0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xc3,0xc3,0xc3,0xc3,0xc3, -0xd6e,0xd6e,0xd74,0xc6,0xc6,0xc6,0xc6,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b, -0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b,0xd6b, -0xc6,0xc6,0xc6,0xd71,0xd71,0xd71,0xd71,0xd71,0xd71,0xd71,0xd71,0xd71,0xd35,0xd35,0xd35,0xd35, -0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35, -0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xd35,0xc9,0xd32,0xd3e,0xd3e,0xd3e,0xd3e, -0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e, -0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xcc,0xcc,0xd3b,0xd3b,0xd3b,0xd3b, -0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x1824,0x1824,0x1824,0x1824, -0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0xd41,0xd41,0xd41,0xd41, -0xd41,0xd41,0xcf,0xcf,0xd41,0xcf,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41, -0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xcf,0xd41, -0xd41,0xcf,0xcf,0xcf,0xd41,0xcf,0xcf,0xd41,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44, -0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd2, -0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5, -0xdf5,0xdf5,0xdf5,0x14ee,0x14ee,0x179a,0x179a,0xd8,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0, -0x10e0,0x10e0,0x10e0,0x10e0,0x1a73,0x129,0x129,0x129,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07, -0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xe07,0xdfe, -0xdfe,0xe04,0xe04,0xdfe,0xdb,0xdb,0xe01,0xe01,0x1110,0x1110,0x1110,0x1110,0xde,0xde,0xde,0xde, -0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f, -0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xe19,0xe16,0xe19,0xe16,0xe16,0xe0d,0xe0d,0xe0d, -0xe0d,0xe0d,0xe0d,0x115b,0x1158,0x115b,0x1158,0x1155,0x1155,0x1155,0x13e6,0x13e3,0xe1,0xe1,0xe1,0xe1, -0xe1,0xe13,0xe10,0xe10,0xe10,0xe0d,0xe13,0xe10,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c, -0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe4, -0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe4, -0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe4,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe4, -0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe1c,0xe4,0xe22,0xe22,0xe22,0xe22,0xe22,0xe22,0xe22,0xe22, -0xe22,0xe22,0xe22,0xe22,0xe22,0xe22,0xe22,0xe22,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f, -0xe1f,0xe1f,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xea,0x13e9, -0xea,0xea,0xea,0xea,0xea,0x13e9,0xea,0xea,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c, -0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe3d,0xe31,0xe31,0xe31,0xed,0xe31,0xe31,0xed, -0xed,0xed,0xed,0xed,0xe31,0xe31,0xe31,0xe31,0xe3d,0xe3d,0xe3d,0xe3d,0xed,0xe3d,0xe3d,0xe3d, -0xed,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d, -0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0x1905,0x1905,0xed,0xed,0xe2e,0xe2e,0xe2e,0xed, -0xed,0xed,0xed,0xe34,0xe37,0xe37,0xe37,0xe37,0xe37,0xe37,0xe37,0xe37,0x1902,0xed,0xed,0xed, -0xed,0xed,0xed,0xed,0xe3a,0xe3a,0xe3a,0xe3a,0xe3a,0xe3a,0xe40,0xe40,0xe37,0xed,0xed,0xed, -0xed,0xed,0xed,0xed,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0x1161,0x1161, -0xf0,0xf0,0xf0,0xf0,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4f,0xe4f,0xe4f,0xe4c,0xe4c,0xe4f,0xe4c, -0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, -0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0xe49,0x115e,0xf0,0xf0,0xf0,0xe46,0xe46, -0xe55,0xe55,0xe55,0xe55,0xf3,0xf3,0xf3,0xf3,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55, -0xe52,0xe55,0xe55,0xe55,0xe55,0xe55,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, -0x14fd,0x1503,0x1500,0x1845,0x17a0,0x1869,0x1869,0x1869,0x1869,0x1869,0x190b,0x1908,0x190e,0x1908,0x190e,0x19cb, -0x1a67,0x1a67,0x1a67,0x1b2a,0x1b2a,0x1b24,0x1b21,0x1b24,0x1b21,0x1b24,0x1b21,0x1b24,0x1b21,0x1b27,0xf6,0xf6, -0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6, -0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6, -0xe79,0xe79,0xe79,0xe76,0xe76,0xe6d,0xe6d,0xe76,0xe73,0xe73,0xe73,0xe73,0x1a6a,0xf9,0xf9,0xf9, -0x12cc,0x12cc,0x12cc,0x12cf,0x12cf,0x12cf,0x12c6,0x12c6,0x12c9,0x12c6,0x14d,0x14d,0x14d,0x14d,0x14d,0x14d, -0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0x13f5,0x13f5,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xe7f, -0x1335,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0x1332, -0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42, -0xeac,0xe9d,0xe97,0xea9,0xea6,0xea0,0xea0,0xeaf,0xe9a,0xea3,0xff,0xff,0xff,0xff,0xff,0xff, -0xf33,0xf33,0xf1e,0xf33,0xf36,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0x1b2d,0x105,0x105,0x105, -0xf2d,0xf2d,0xf2d,0xf2d,0xf2d,0xf2d,0xf2d,0xf2d,0xf2d,0xf2d,0xf3f,0xf3f,0xf24,0xf2a,0xf3f,0xf3f, -0xf27,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf21,0xf21,0xf21,0xf21,0xf21, -0xf21,0xf21,0xf21,0xf21,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0x1b30,0x1b30,0x105, -0x1b39,0x1b33,0x19d1,0x19ce,0x19d1,0x19d1,0x19d1,0x1a70,0x1a6d,0x1a70,0x1a6d,0x108,0x108,0x108,0x108,0x108, -0x1b39,0x1b33,0x108,0x1b33,0x108,0x1b33,0x1b39,0x1b33,0x1b39,0x1b33,0x108,0x108,0x108,0x108,0x108,0x108, -0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x1b36,0x1b36, -0x1b36,0x1a70,0x1a6d,0x150c,0x13fe,0x13fe,0x1338,0x103b,0x103b,0x103b,0x103b,0x103b,0xf4e,0xf4e,0xf4e,0xf4e, -0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e, -0xf4b,0xf4b,0xf51,0xf51,0x10b,0x10b,0x10b,0x10b,0x10b,0x10b,0x10b,0x10b,0xf5a,0xf5a,0xf5a,0xf5a, -0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a,0xf5a, -0xf5a,0xf5a,0xf54,0xf54,0xf54,0xf54,0x116a,0x116a,0x10e,0x10e,0x10e,0xf57,0x1512,0x1512,0x1512,0x1512, -0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512, -0x1512,0x1512,0x1512,0x1512,0x1512,0x16f2,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111, -0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111, -0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0xf63,0xf63,0xf63,0x1518,0x1518,0x1518,0x1518,0x1518, -0x1518,0x1518,0x1518,0x1518,0x1518,0x1518,0x1518,0x114,0xf60,0xf60,0xf60,0xf60,0x1515,0x114,0x114,0x114, -0x114,0x114,0x114,0x114,0x114,0x114,0x114,0x114,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66, -0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0x191d,0x191d,0x191d,0x191d,0x191d,0x191d, -0x191d,0x117,0x117,0x117,0x117,0x117,0x117,0x117,0x1062,0x1062,0x1062,0x1062,0x105f,0x105f,0x105f,0x105f, -0x105f,0x105f,0x105f,0x105f,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x105f,0x105f,0x1056,0x1053, -0x11a,0x11a,0x11a,0x1065,0x1065,0x1059,0x1059,0x1059,0x105c,0x105c,0x105c,0x105c,0x105c,0x105c,0x105c,0x105c, -0x105c,0x105c,0x11a,0x11a,0x11a,0x1062,0x1062,0x1062,0x1068,0x1068,0x1068,0x1068,0x1068,0x1068,0x1068,0x1068, -0x1068,0x1068,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x107d,0x107d,0x107d,0x107d,0x107d,0x107d,0x107d,0x107d, -0x107d,0x107d,0x1080,0x1080,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d, -0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x10a7,0x10a7,0x10a7,0x10a7,0x10a1,0x17a6,0x120,0x120, -0x120,0x120,0x120,0x120,0x120,0x120,0x10ad,0x10ad,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4,0x10a4, -0x10a4,0x10a4,0x120,0x120,0x120,0x120,0x120,0x120,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10bf, -0x10bf,0x10bf,0x10bf,0x10bf,0x10bf,0x10bf,0x10bf,0x10bf,0x10bf,0x10bf,0x10c5,0x10c8,0x123,0x123,0x123,0x123, -0x123,0x123,0x123,0x123,0x123,0x123,0x123,0x10c2,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da, -0x10da,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10d7,0x10d7,0x10ce,0x10ce,0x10d7,0x10d7,0x10ce,0x10ce,0x126, -0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x10da,0x10da,0x10da,0x10ce,0x10da,0x10da,0x10da,0x10da, -0x10da,0x10da,0x10da,0x10da,0x10ce,0x10d7,0x126,0x126,0x10d4,0x10d4,0x10d4,0x10d4,0x10d4,0x10d4,0x10d4,0x10d4, -0x10d4,0x10d4,0x126,0x126,0x10d1,0x10dd,0x10dd,0x10dd,0x1524,0x129,0x129,0x129,0x129,0x129,0x129,0x129, -0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129, -0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x129,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3, -0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e3, -0x10e3,0x10e3,0x10e3,0x10e3,0x10e3,0x10e6,0x12c,0x12c,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7f,0xb7f,0xa2,0xb7f,0xb7f,0xb7f,0xb7f,0xa2, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xa2,0xb7f,0xa2,0xa2,0xa2,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f, +0xb7f,0xa2,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, +0xddd,0xddd,0xa2,0xa2,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7c,0xb7c,0xb7c,0xb76, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xef4,0xef1,0xa2,0xa2,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, +0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xa5,0xb85,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xc0c,0xc0c,0xc0c,0xc0c, +0xc0c,0xc0c,0xc0c,0xc0c,0xc0c,0xc0c,0xc0c,0xc0c,0xc0c,0x1b2a,0xc0c,0xc0c,0xc0c,0xc0c,0xc06,0xc06, +0xc09,0x1b27,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x1b2a,0xc15,0xc15,0xc15,0xc15, +0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc15,0xc0f,0xc0f, +0xc12,0xc75,0xc75,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xc1b,0xc1b,0xc1b,0xc1b, +0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc1b,0xc18,0xc18, +0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xc21,0xc21,0xc21,0xc21, +0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xb1,0xc21,0xc21,0xc21,0xb1,0xc1e,0xc1e, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xd05,0xd05,0xd05,0xd05, +0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05, +0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0xd05,0x14f1,0x14f1,0xb4,0xcf6,0xcf6,0xcf6,0xd02, +0xd02,0xd02,0xd02,0xcf6,0xcf6,0xd02,0xd02,0xd02,0xb4,0xb4,0xb4,0xb4,0xd02,0xd02,0xcf6,0xd02, +0xd02,0xd02,0xd02,0xd02,0xd02,0xcf9,0xcf9,0xcf9,0xb4,0xb4,0xb4,0xb4,0xcfc,0xb4,0xb4,0xb4, +0xd08,0xd08,0xcff,0xcff,0xcff,0xcff,0xcff,0xcff,0xcff,0xcff,0xcff,0xcff,0xd0b,0xd0b,0xd0b,0xd0b, +0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xb7,0xb7, +0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7, +0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4, +0x14f4,0x14f4,0x14f4,0x14f4,0xba,0xba,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4, +0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0xba,0x1a76, +0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f, +0xd2f,0xd2f,0xd2f,0xd2f,0xbd,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f, +0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xbd,0xd2f,0xd2f,0xd2f,0xd2f, +0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xbd, +0xd2f,0xd2f,0xbd,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f, +0xd2f,0xd2f,0xbd,0xbd,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f, +0xd2f,0xd2f,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, +0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, +0xbd,0xbd,0xbd,0xbd,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32, +0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xc0, +0xc0,0xc0,0xc0,0xc0,0xd71,0xd71,0xd77,0xc3,0xc3,0xc3,0xc3,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e, +0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e,0xd6e, +0xd6e,0xd6e,0xd6e,0xd6e,0xc3,0xc3,0xc3,0xd74,0xd74,0xd74,0xd74,0xd74,0xd74,0xd74,0xd74,0xd74, +0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38, +0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xc6,0xd35, +0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41, +0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xd41,0xc9,0xc9, +0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xd3e,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9, +0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833, +0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xcc,0xcc,0xd44,0xcc,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44, +0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44, +0xd44,0xd44,0xcc,0xd44,0xd44,0xcc,0xcc,0xcc,0xd44,0xcc,0xcc,0xd44,0xd47,0xd47,0xd47,0xd47, +0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47, +0xd47,0xd47,0xd47,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xdf8,0xdf8,0xdf8,0xdf8, +0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0x14f7,0x14f7,0x17a9,0x17a9,0xd5,0x10e6,0x10e6,0x10e6,0x10e6, +0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x10e6,0x1a85,0x126,0x126,0x126,0xe0a,0xe0a,0xe0a,0xe0a, +0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a,0xe0a, +0xe0a,0xe0a,0xe0a,0xe01,0xe01,0xe07,0xe07,0xe01,0xd8,0xd8,0xe04,0xe04,0x1113,0x1113,0x1113,0x1113, +0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0x1c56,0xc72,0xc72,0xc72,0xc72, +0xc72,0xc72,0xc72,0xc72,0xc72,0xc72,0xc72,0xc72,0xc72,0xc72,0xc72,0xc72,0xe1c,0xe19,0xe1c,0xe19, +0xe19,0xe10,0xe10,0xe10,0xe10,0xe10,0xe10,0x1161,0x115e,0x1161,0x115e,0x115b,0x115b,0x115b,0x13ef,0x13ec, +0xde,0xde,0xde,0xde,0xde,0xe16,0xe13,0xe13,0xe13,0xe10,0xe16,0xe13,0xe1f,0xe1f,0xe1f,0xe1f, +0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f, +0xe1f,0xe1f,0xe1f,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1f,0xe1f,0xe1f,0xe1f, +0xe1f,0xe1f,0xe1f,0xe1,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1,0xe1f,0xe1f,0xe1f,0xe1f, +0xe1f,0xe1f,0xe1f,0xe1,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1f,0xe1,0xe25,0xe25,0xe25,0xe25, +0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe22,0xe22,0xe22,0xe22, +0xe22,0xe22,0xe22,0xe22,0xe22,0xe22,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe28,0xe28,0xe28,0xe28, +0xe28,0xe28,0xe7,0x13f2,0xe7,0xe7,0xe7,0xe7,0xe7,0x13f2,0xe7,0xe7,0xe7f,0xe7f,0xe7f,0xe7f, +0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe40,0xe34,0xe34,0xe34, +0xea,0xe34,0xe34,0xea,0xea,0xea,0xea,0xea,0xe34,0xe34,0xe34,0xe34,0xe40,0xe40,0xe40,0xe40, +0xea,0xe40,0xe40,0xe40,0xea,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40, +0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0xe40,0x1914,0x1914,0xea,0xea, +0xe31,0xe31,0xe31,0xea,0xea,0xea,0xea,0xe37,0xe3a,0xe3a,0xe3a,0xe3a,0xe3a,0xe3a,0xe3a,0xe3a, +0x1911,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe3d,0xe43,0xe43, +0xe3a,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0x1167,0x1167,0xed,0xed,0xed,0xed,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe52,0xe52,0xe52, +0xe4f,0xe4f,0xe52,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xed,0xed, +0xed,0xed,0xed,0xed,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0x1164,0xed, +0xed,0xed,0xe49,0xe49,0xe58,0xe58,0xe58,0xe58,0xf0,0xf0,0xf0,0xf0,0xe58,0xe58,0xe58,0xe58, +0xe58,0xe58,0xe58,0xe58,0xe55,0xe58,0xe58,0xe58,0xe58,0xe58,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, +0xf0,0xf0,0xf0,0xf0,0x1506,0x150c,0x1509,0x1854,0x17af,0x1878,0x1878,0x1878,0x1878,0x1878,0x191a,0x1917, +0x191d,0x1917,0x191d,0x19dd,0x1a79,0x1a79,0x1a79,0x1b3c,0x1b3c,0x1b36,0x1b33,0x1b36,0x1b33,0x1b36,0x1b33,0x1b36, +0x1b33,0x1b39,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, +0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, +0xf3,0xf3,0xf3,0xf3,0xe7c,0xe7c,0xe7c,0xe79,0xe79,0xe70,0xe70,0xe79,0xe76,0xe76,0xe76,0xe76, +0x1a7c,0xf6,0xf6,0xf6,0x12cc,0x12cc,0x12cc,0x12cf,0x12cf,0x12cf,0x12d2,0x12d2,0x12d5,0x12d2,0x14a,0x14a, +0x14a,0x14a,0x14a,0x14a,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0x13fe,0x13fe,0xf9,0xf9,0xf9,0xf9, +0xf9,0xf9,0xf9,0xe82,0x133b,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9, +0xf9,0xf9,0xf9,0x1338,0xc45,0xc45,0xc45,0xc45,0xc45,0xc45,0xc45,0xc45,0xc45,0xc45,0xc45,0xc45, +0xc45,0xc45,0xc45,0xc45,0xeaf,0xea0,0xe9a,0xeac,0xea9,0xea3,0xea3,0xeb2,0xe9d,0xea6,0xfc,0xfc, +0xfc,0xfc,0xfc,0xfc,0xf36,0xf36,0xf21,0xf36,0xf39,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c, +0x1b3f,0x102,0x102,0x102,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf30,0xf42,0xf42, +0xf2a,0xf2d,0xf42,0xf42,0xf27,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf24, +0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf24,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a,0xf2a, +0xf2a,0x1b42,0x1b42,0x102,0x1b4b,0x1b45,0x19e3,0x19e0,0x19e3,0x19e3,0x19e3,0x1a82,0x1a7f,0x1a82,0x1a7f,0x105, +0x105,0x105,0x105,0x105,0x1b4b,0x1b45,0x105,0x1b45,0x105,0x1b45,0x1b4b,0x1b45,0x1b4b,0x1b45,0x105,0x105, +0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105,0x105, +0x105,0x105,0x1b48,0x1b48,0x1b48,0x1a82,0x1a7f,0x1515,0x1407,0x1407,0x133e,0x103e,0x103e,0x103e,0x103e,0x103e, +0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51, +0xf51,0xf51,0xf51,0xf51,0xf4e,0xf4e,0xf54,0xf54,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108, +0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d, +0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf57,0xf57,0xf57,0xf57,0x1170,0x1170,0x10b,0x10b,0x10b,0xf5a, +0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b, +0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x1701,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e, +0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e, +0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0x10e,0xf66,0xf66,0xf66,0x1521, +0x1521,0x1521,0x1521,0x1521,0x1521,0x1521,0x1521,0x1521,0x1521,0x1521,0x1521,0x111,0xf63,0xf63,0xf63,0xf63, +0x151e,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0x111,0xf69,0xf69,0xf69,0xf69, +0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0xf69,0x192c,0x192c, +0x192c,0x192c,0x192c,0x192c,0x192c,0x114,0x114,0x114,0x114,0x114,0x114,0x114,0x1065,0x1065,0x1065,0x1065, +0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1053,0x1053,0x1053,0x1053,0x1053,0x1053,0x1053,0x1053, +0x1062,0x1062,0x1059,0x1056,0x117,0x117,0x117,0x1068,0x1068,0x105c,0x105c,0x105c,0x105f,0x105f,0x105f,0x105f, +0x105f,0x105f,0x105f,0x105f,0x105f,0x105f,0x117,0x117,0x117,0x1065,0x1065,0x1065,0x106b,0x106b,0x106b,0x106b, +0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x1080,0x1080,0x1080,0x1080, +0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1083,0x1083,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a, +0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x11a,0x10aa,0x10aa,0x10aa,0x10aa, +0x10a4,0x17b5,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x10b0,0x10b0,0x10a7,0x10a7,0x10a7,0x10a7, +0x10a7,0x10a7,0x10a7,0x10a7,0x10a7,0x10a7,0x11d,0x11d,0x11d,0x11d,0x11d,0x11d,0x10ce,0x10ce,0x10ce,0x10ce, +0x10ce,0x10ce,0x10ce,0x10c2,0x10c2,0x10c2,0x10c2,0x10c2,0x10c2,0x10c2,0x10c2,0x10c2,0x10c2,0x10c2,0x10c8,0x10cb, +0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x10c5,0x10e0,0x10e0,0x10e0,0x10e0, +0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10d1,0x10d1,0x10d1,0x10d1,0x10d1,0x10d1,0x10da,0x10da,0x10d1,0x10d1,0x10da, +0x10da,0x10d1,0x10d1,0x123,0x123,0x123,0x123,0x123,0x123,0x123,0x123,0x123,0x10dd,0x10dd,0x10dd,0x10d1, +0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10dd,0x10d1,0x10da,0x123,0x123,0x10d7,0x10d7,0x10d7,0x10d7, +0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x10d7,0x123,0x123,0x10d4,0x10e3,0x10e3,0x10e3,0x152d,0x126,0x126,0x126, +0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126, +0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x126,0x10e9,0x10e9,0x10e9,0x10e9, 0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9, -0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x12f,0x12f,0x12f,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec, -0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x132,0x132,0x132,0x132,0x132,0x132,0x132, -0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x132,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2, -0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2, -0x10f2,0x10f2,0x135,0x135,0x135,0x135,0x135,0x10ef,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5, -0x10f5,0x10f5,0x10f5,0x10f5,0x138,0x138,0x138,0x138,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8, -0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x13b,0x13b,0x13b,0x13b, -0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x1170,0x1170,0x1170,0x1170,0x1179,0x1170,0x1170,0x1170, -0x1179,0x1170,0x1170,0x1170,0x1170,0x116d,0x13e,0x13e,0x1176,0x1176,0x1176,0x1176,0x1176,0x1176,0x1176,0x117c, -0x1176,0x117c,0x1176,0x1176,0x1176,0x117c,0x117c,0x13e,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f, -0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x141,0x141, -0x141,0x141,0x141,0x141,0x141,0x141,0x141,0x141,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a, -0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x1197,0x1182,0x1197, -0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x1182,0x144,0x118b,0x1194,0x1182,0x1194,0x1194,0x1182,0x1182,0x1182, -0x1182,0x1182,0x1182,0x1182,0x1182,0x1197,0x1197,0x1197,0x1197,0x1197,0x1197,0x1182,0x1182,0x1188,0x1188,0x1188, -0x1188,0x1188,0x1188,0x1188,0x1188,0x144,0x144,0x1185,0x1191,0x1191,0x1191,0x1191,0x1191,0x1191,0x1191,0x1191, -0x1191,0x1191,0x144,0x144,0x144,0x144,0x144,0x144,0x1191,0x1191,0x1191,0x1191,0x1191,0x1191,0x1191,0x1191, -0x1191,0x1191,0x144,0x144,0x144,0x144,0x144,0x144,0x118e,0x118e,0x118e,0x118e,0x118e,0x118e,0x118e,0x119d, -0x11a0,0x11a0,0x11a0,0x11a0,0x118e,0x118e,0x144,0x144,0x1563,0x1563,0x1563,0x1563,0x1563,0x1563,0x1563,0x1563, -0x1563,0x1563,0x1563,0x1563,0x1563,0x1563,0x1560,0x1a85,0x12e1,0x12ba,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8,0x12d8, -0x12d8,0x12c0,0x12bd,0x12b4,0x12b4,0x12de,0x12b4,0x12b4,0x12b4,0x12b4,0x12c3,0x149d,0x14a3,0x14a0,0x14a0,0x18e4, -0x16b9,0x16b9,0x1a52,0x147,0x147,0x147,0x147,0x147,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5, -0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11ac,0x11ac,0x11af,0x11b8,0x11b2,0x11b2,0x11b2,0x11b8, -0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x14a,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5, -0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x12a5, -0x12a5,0x12a5,0x12a5,0x12a5,0x12a5,0x150,0x150,0x150,0x11d6,0x11ca,0x11ca,0x11ca,0x11ca,0x11ca,0x11ca,0x11cd, -0x11dc,0x11dc,0x11ca,0x11ca,0x11ca,0x11ca,0x153,0x12d5,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0,0x11d0, -0x11d0,0x11d0,0x153,0x153,0x153,0x153,0x11ca,0x11ca,0x11fa,0x11ee,0x11fa,0x156,0x156,0x156,0x156,0x156, -0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156,0x156, -0x156,0x156,0x156,0x11f7,0x11f7,0x11fd,0x11f1,0x11f4,0x1212,0x1212,0x1212,0x120c,0x120c,0x1203,0x120c,0x120c, -0x1203,0x120c,0x120c,0x1215,0x120f,0x1206,0x159,0x159,0x1209,0x1209,0x1209,0x1209,0x1209,0x1209,0x1209,0x1209, -0x1209,0x1209,0x159,0x159,0x159,0x159,0x159,0x159,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b,0x121b,0x15c, -0x15c,0x15c,0x15c,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218, -0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218, -0x15c,0x15c,0x15c,0x15c,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224, -0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x15f,0x1221,0x121e,0x121e,0x121e,0x121e, -0x121e,0x121e,0x121e,0x121e,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233, -0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x162,0x162,0x162,0x122d,0x1230,0x1230, -0x1230,0x1230,0x1230,0x1230,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239, -0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x165,0x165,0x1236,0x1236,0x1236,0x1236, -0x1236,0x1236,0x1236,0x1236,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f, -0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x168,0x168,0x168,0x168,0x168,0x123c,0x123c,0x123c,0x123c, -0x123c,0x123c,0x123c,0x123c,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245, -0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245, -0x1245,0x1245,0x1245,0x16e,0x125d,0x125d,0x1b3c,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171, -0x171,0x1926,0x171,0x171,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c, -0x147c,0x147c,0x147c,0x147c,0x1827,0x1827,0x1827,0x1827,0x1827,0x1827,0x1827,0x1827,0x1827,0x1827,0x1827,0x1827, -0x1827,0x1a76,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174, -0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174, -0x174,0x174,0x174,0x174,0x174,0x174,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344, -0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344,0x1344, -0x12ae,0x13a7,0x13a7,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177, +0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10e9,0x10ec,0x129,0x129,0x10ef,0x10ef,0x10ef,0x10ef, +0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef, +0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x10ef,0x12c,0x12c,0x12c,0x10f2,0x10f2,0x10f2,0x10f2, +0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x12f,0x12f,0x12f, +0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x12f,0x10f8,0x10f8,0x10f8,0x10f8, +0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8, +0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x132,0x132,0x132,0x132,0x132,0x10f5,0x10fb,0x10fb,0x10fb,0x10fb, +0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x135,0x135,0x135,0x135,0x10fe,0x10fe,0x10fe,0x10fe, +0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe, +0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x138,0x1176,0x1176,0x1176,0x1176, +0x117f,0x1176,0x1176,0x1176,0x117f,0x1176,0x1176,0x1176,0x1176,0x1173,0x13b,0x13b,0x117c,0x117c,0x117c,0x117c, +0x117c,0x117c,0x117c,0x1182,0x117c,0x1182,0x117c,0x117c,0x117c,0x1182,0x1182,0x13b,0x1185,0x1185,0x1185,0x1185, +0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185, +0x1185,0x1185,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x13e,0x11a0,0x11a0,0x11a0,0x11a0, +0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0, +0x11a0,0x119d,0x1188,0x119d,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188,0x141,0x1191,0x119a,0x1188,0x119a, +0x119a,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188,0x1188,0x119d,0x119d,0x119d,0x119d,0x119d,0x119d,0x1188, +0x1188,0x118e,0x118e,0x118e,0x118e,0x118e,0x118e,0x118e,0x118e,0x141,0x141,0x118b,0x1197,0x1197,0x1197,0x1197, +0x1197,0x1197,0x1197,0x1197,0x1197,0x1197,0x141,0x141,0x141,0x141,0x141,0x141,0x1197,0x1197,0x1197,0x1197, +0x1197,0x1197,0x1197,0x1197,0x1197,0x1197,0x141,0x141,0x141,0x141,0x141,0x141,0x1194,0x1194,0x1194,0x1194, +0x1194,0x1194,0x1194,0x11a3,0x11a6,0x11a6,0x11a6,0x11a6,0x1194,0x1194,0x141,0x141,0x156c,0x156c,0x156c,0x156c, +0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x156c,0x1569,0x1a97,0x12e7,0x12c0,0x12de,0x12de, +0x12de,0x12de,0x12de,0x12de,0x12de,0x12c6,0x12c3,0x12ba,0x12ba,0x12e4,0x12ba,0x12ba,0x12ba,0x12ba,0x12c9,0x14a6, +0x14ac,0x14a9,0x14a9,0x18f3,0x16c8,0x16c8,0x1a64,0x144,0x144,0x144,0x144,0x144,0x11bb,0x11bb,0x11bb,0x11bb, +0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11b2,0x11b2,0x11b5,0x11be, +0x11b8,0x11b8,0x11b8,0x11be,0x147,0x147,0x147,0x147,0x147,0x147,0x147,0x147,0x12ab,0x12ab,0x12ab,0x12ab, 0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab, -0x12ab,0x12ab,0x13a7,0x13a7,0x13a7,0x13a7,0x13a7,0x13a7,0x13a7,0x13a7,0x13a7,0x182a,0x177,0x177,0x177,0x177, -0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x12a8,0x177,0x177,0x177,0x177,0x177,0x177,0x177, -0x13cb,0x13cb,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177, -0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177, -0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177, -0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x177,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d, -0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d,0x134d, -0x134d,0x1347,0x1347,0x1347,0x17a,0x17a,0x134a,0x17a,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x1350,0x1359, -0x1353,0x1353,0x1359,0x1359,0x1359,0x1353,0x1359,0x1353,0x1353,0x1353,0x135c,0x135c,0x17d,0x17d,0x17d,0x17d, -0x17d,0x17d,0x17d,0x17d,0x1356,0x1356,0x1356,0x1356,0x180,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x180, -0x180,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x180,0x180,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x180, -0x180,0x180,0x180,0x180,0x180,0x180,0x180,0x180,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x180, -0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x1362,0x180,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0, -0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1368,0x137a, -0x137a,0x136e,0x136e,0x136e,0x136e,0x136e,0x183,0x183,0x183,0x183,0x136b,0x136b,0x136b,0x136b,0x136b,0x136b, -0x136b,0x136b,0x136b,0x136b,0x136b,0x136b,0x136b,0x136b,0x136b,0x136b,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371, -0x1371,0x1371,0x1371,0x1371,0x1b42,0x1b45,0x1b45,0x1b3f,0x1b3f,0x1b45,0x183,0x183,0x183,0x183,0x183,0x183, -0x183,0x183,0x183,0x1533,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d, -0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x186,0x186,0x186, -0x186,0x186,0x186,0x186,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380, -0x1380,0x1380,0x1380,0x189,0x189,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380, -0x1380,0x1380,0x1380,0x1536,0x189,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380, -0x1380,0x1380,0x1380,0x13b0,0x189,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380,0x1380, -0x1380,0x1380,0x1380,0x1380,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536, -0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x1536,0x189,0x189,0x189,0x189,0x189,0x189, -0x189,0x189,0x189,0x189,0x13c5,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542, -0x16b0,0x1542,0x1542,0x1542,0x1782,0x1833,0x1833,0x186c,0x186c,0x1a34,0x1adf,0x1adf,0x18c,0x18c,0x18c,0x18c, -0x1c2c,0x1bae,0x1bae,0x1bae,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x16ad, -0x16ad,0x18c,0x18c,0x18c,0x1542,0x1542,0x1542,0x1542,0x1833,0x1833,0x1833,0x18cf,0x18cf,0x19b0,0x1a34,0x1adf, -0x1adf,0x18c,0x18c,0x18c,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383, -0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1bd2,0x1bd2,0x1bd2,0x18f,0x18f,0x18f,0x18f,0x1bd2, -0x1bd2,0x1bd2,0x1bd2,0x1bd2,0x141f,0x141f,0x141f,0x141f,0x192,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f, -0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f, -0x141f,0x141f,0x141f,0x141f,0x192,0x141f,0x141f,0x192,0x141f,0x192,0x192,0x141f,0x192,0x141f,0x141f,0x141f, -0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x192,0x141f,0x141f,0x141f,0x141f,0x192,0x141f,0x192,0x141f, -0x192,0x192,0x192,0x192,0x192,0x192,0x141f,0x192,0x192,0x192,0x192,0x141f,0x192,0x141f,0x192,0x141f, -0x192,0x141f,0x141f,0x141f,0x192,0x141f,0x141f,0x192,0x141f,0x192,0x192,0x141f,0x192,0x141f,0x192,0x141f, -0x192,0x141f,0x192,0x141f,0x192,0x141f,0x141f,0x192,0x141f,0x192,0x192,0x141f,0x141f,0x141f,0x141f,0x192, -0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x192,0x141f,0x141f,0x141f,0x141f,0x192,0x141f,0x141f,0x141f, -0x141f,0x192,0x141f,0x192,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x192,0x141f, -0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f, -0x192,0x192,0x192,0x192,0x192,0x141f,0x141f,0x141f,0x192,0x141f,0x141f,0x141f,0x141f,0x141f,0x192,0x141f, -0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f, -0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192, -0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192, -0x141c,0x141c,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192,0x192, -0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1422,0x1422,0x1422,0x1422,0x1422,0x1431,0x1422,0x1425,0x1425, -0x1422,0x1422,0x1422,0x1428,0x1428,0x195,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e,0x142e, -0x142b,0x1437,0x1437,0x1437,0x1932,0x192f,0x192f,0x1a7c,0x195,0x195,0x195,0x195,0x195,0x195,0x195,0x195, -0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2, -0x1443,0x1443,0x1443,0x1443,0x1443,0x1443,0x1443,0x1443,0x1443,0x1443,0x1443,0x1440,0x143a,0x143a,0x1440,0x1440, -0x1449,0x1449,0x1443,0x1446,0x1446,0x1440,0x143d,0x198,0x198,0x198,0x198,0x198,0x198,0x198,0x198,0x198, -0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c, -0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x19b,0x19b,0x19b,0x19b,0x1707,0x1707,0x144c,0x144c, -0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707, -0x19b,0x19b,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707, -0x1458,0x1458,0x1458,0x1458,0x1458,0x19dd,0x19dd,0x19dd,0x19dd,0x19dd,0x19dd,0x19e,0x19e,0x19e,0x19e,0x19d7, -0x1458,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455, -0x19da,0x19da,0x19da,0x19da,0x19da,0x19da,0x19da,0x19da,0x19e,0x19e,0x19e,0x19e,0x19e,0x19e,0x19e,0x1452, -0x1452,0x1452,0x1452,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b,0x145b, -0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x147c,0x1a1,0x1a1,0x1a1,0x1a1,0x1a1,0x1a1,0x1a1, -0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1a1,0x1a1,0x1a1,0x1a1,0x1a1,0x1a1, -0x147f,0x147f,0x147f,0x147f,0x147f,0x147f,0x147f,0x147f,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4,0x1a4, -0x12db,0x12d8,0x12db,0x12b7,0x12d8,0x12de,0x12de,0x12e1,0x12de,0x12e1,0x12e4,0x12d8,0x12e1,0x12e1,0x12d8,0x12d8, -0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1482,0x148b,0x1482,0x148b,0x148b, -0x1482,0x1482,0x1482,0x1482,0x1482,0x1482,0x148e,0x1485,0x19e0,0x1b51,0x1a7,0x1a7,0x1a7,0x1a7,0x1a7,0x1a7, -0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1aa,0x1aa, -0x1551,0x1551,0x1551,0x1551,0x1551,0x1557,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa, -0x155d,0x155d,0x155d,0x155d,0x1ad,0x1ad,0x1ad,0x1ad,0x1ad,0x1ad,0x1ad,0x1ad,0x1ad,0x1ad,0x1ad,0x155a, -0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x2b2,0x1b9c,0x1b9c,0x1b9c,0x1b9c, -0x16bc,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3, -0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x16b3,0x1b0,0x1b0,0x1b0,0x1b0, -0x1a85,0x1b57,0x1b57,0x1b57,0x1b57,0x1b57,0x1b57,0x1b57,0x1b57,0x1b57,0x1b57,0x1b57,0x1b54,0x1b54,0x1b54,0x1b3, -0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3, -0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3, -0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6, -0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x1b6,0x1b6,0x1b6, -0x1b6,0x1b6,0x1b6,0x1b6,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x1b6,0x1b6, -0x156c,0x1566,0x1569,0x1572,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1b9,0x1b9,0x1b9,0x1b9, -0x1b9,0x1b9,0x1b9,0x1b9,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d, -0x155d,0x155d,0x155d,0x155d,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578, -0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1935,0x1935,0x1935,0x1935,0x1bd5,0x1bc,0x1bc, -0x1bc,0x1bc,0x1bc,0x1bc,0x1a37,0x1a37,0x1a37,0x1a37,0x1a37,0x1a37,0x1a37,0x1a37,0x1a37,0x1a37,0x1a37,0x1a37, -0x1bc,0x1bc,0x1bc,0x1bc,0x1bb1,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc, -0x1bc,0x1bc,0x1bc,0x1bc,0x171c,0x16bf,0x1581,0x16c5,0x1bf,0x158a,0x158a,0x158a,0x158a,0x158a,0x158a,0x158a, -0x158a,0x1bf,0x1bf,0x158a,0x158a,0x1bf,0x1bf,0x158a,0x158a,0x158a,0x158a,0x158a,0x158a,0x158a,0x158a,0x158a, -0x158a,0x158a,0x158a,0x158a,0x158a,0x1bf,0x158a,0x158a,0x158a,0x158a,0x158a,0x158a,0x158a,0x1bf,0x158a,0x158a, -0x1bf,0x158a,0x158a,0x158a,0x158a,0x158a,0x1bf,0x19bc,0x16c2,0x158a,0x157b,0x1581,0x157b,0x1581,0x1581,0x1581, -0x1581,0x1bf,0x1bf,0x1581,0x1581,0x1bf,0x1bf,0x1584,0x1584,0x1587,0x1bf,0x1bf,0x171f,0x1bf,0x1bf,0x1bf, -0x1bf,0x1bf,0x1bf,0x157b,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x158d,0x158a,0x158a,0x158a,0x158a,0x1581,0x1581, -0x1bf,0x1bf,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x1bf,0x1bf,0x1bf,0x157e,0x157e,0x157e,0x157e, -0x157e,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x1bf,0x15a2,0x15a2,0x15a2,0x15a2, -0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x1c2,0x15a2, -0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15b4,0x15b4,0x15b4,0x15a8, -0x15a8,0x15a8,0x15a8,0x15a8,0x15a8,0x15ab,0x15ae,0x1c5,0x1c5,0x1c5,0x1c5,0x1c5,0x15b1,0x15b1,0x15b1,0x15b1, -0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x1c5,0x1c5,0x1c5,0x1c5,0x1c5,0x1c5,0x1722,0x1722,0x1722,0x1722, -0x15c0,0x15bd,0x19e3,0x19e3,0x1a8b,0x1a8e,0x1a88,0x1a88,0x1c8,0x1c8,0x1c8,0x1c8,0x174f,0x174f,0x174f,0x174f, -0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x15c6,0x15c6,0x15c6,0x15c6, -0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6, -0x15c6,0x15c6,0x15c6,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x15c6,0x15c6,0x15c6,0x15c6, -0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6, -0x15c6,0x15c6,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x15c6,0x15c6,0x15c6,0x15c6, -0x15c6,0x15c6,0x15c6,0x15c6,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb, -0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x15d2,0x15d2,0x15d2,0x15d2, -0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15d2,0x15c9, -0x15cc,0x15cf,0x15d2,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x15e1,0x15e1,0x15e1,0x15e1, -0x15e1,0x15d5,0x15d5,0x1d1,0x1d1,0x1d1,0x1d1,0x15d8,0x15d8,0x15d8,0x15d8,0x15d8,0x15de,0x15de,0x16c8,0x15de, -0x15de,0x15de,0x15db,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x15ea,0x15ea,0x15ea,0x15ea, -0x15ea,0x1d4,0x1d4,0x15e7,0x15e7,0x15e7,0x15e7,0x15e7,0x15e7,0x15e7,0x15e7,0x15e7,0x15e4,0x15e4,0x15e4,0x15e4, -0x15e4,0x15e4,0x15e4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x15ed,0x15ff,0x15ff,0x15f3, -0x15fc,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x15f6,0x15f6,0x15f6,0x15f6, -0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x1d7,0x1605,0x1605,0x1605,0x1605, -0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605, -0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1da,0x1602,0x1602,0x1602,0x1602, -0x1602,0x1602,0x1602,0x1602,0x1602,0x1602,0x1da,0x1da,0x1da,0x1da,0x1608,0x1608,0x1b8d,0x1b8d,0x1b8d,0x1b8d, -0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1611,0x1611,0x1611,0x1611, -0x1611,0x160b,0x1614,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x160e,0x160e,0x160e,0x160e, -0x160e,0x160e,0x160e,0x160e,0x160e,0x160e,0x1611,0x1611,0x1611,0x1611,0x1611,0x1dd,0x161a,0x161a,0x161a,0x161a, -0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a, -0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x161a,0x1e0,0x1626,0x1626,0x1626,0x1626, -0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626,0x1626, -0x1626,0x1626,0x1623,0x1623,0x1623,0x1623,0x1623,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3,0x163e,0x163e,0x1641,0x1641, -0x1644,0x1635,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x163b,0x163b,0x163b,0x163b, -0x163b,0x163b,0x163b,0x163b,0x163b,0x163b,0x1e6,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1e6,0x163e, -0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e, -0x163e,0x163e,0x163e,0x163e,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x163e,0x163e,0x163e,0x164d,0x164d,0x164d,0x164d, -0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d, -0x164d,0x164d,0x164d,0x164d,0x164d,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1656,0x1656,0x1656,0x1656, -0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1656,0x1ec,0x1ec, -0x1ec,0x1ec,0x1ec,0x1ec,0x1ec,0x1653,0x1653,0x1653,0x1653,0x1ec,0x1ec,0x1ec,0x1671,0x1671,0x1671,0x1671, -0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1659,0x166b,0x166b,0x1659,0x1659, -0x1659,0x1659,0x1f2,0x1f2,0x166b,0x166b,0x166e,0x166e,0x1659,0x1659,0x166b,0x165f,0x165c,0x1662,0x1674,0x1674, -0x1665,0x1665,0x1668,0x1668,0x1668,0x1674,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b,0x172b, -0x172b,0x172b,0x172b,0x172b,0x1728,0x1728,0x1728,0x1728,0x1725,0x1725,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2, -0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2, -0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f5,0x1677,0x1677,0x1677, -0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677,0x1677, -0x1677,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x167a,0x167a,0x167a,0x167a, -0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x1f8,0x1f8,0x1f8,0x1f8,0x167a,0x167a,0x167a,0x167a, -0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x1f8,0x1f8,0x1f8,0x1f8, -0x1f8,0x1f8,0x1f8,0x1f8,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x1f8,0x1f8, -0x1f8,0x1f8,0x1f8,0x1f8,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x1f8,0x1f8,0x1f8,0x1f8, -0x1f8,0x1f8,0x1f8,0x1f8,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a, -0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x1f8,0x1f8,0x1a91,0x1a91,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8, -0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8, -0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x167d,0x168c,0x1683,0x1680, -0x1692,0x1692,0x1686,0x1692,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1689,0x1689,0x1689,0x1689, -0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1698,0x1698,0x1698,0x1698, -0x1698,0x1698,0x1698,0x1698,0x1698,0x1698,0x1695,0x1695,0x1695,0x1695,0x1695,0x1695,0x1695,0x1695,0x1695,0x1fe, -0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x1fe,0x169e,0x1740,0x1740,0x1740,0x1740, -0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1740, -0x1740,0x1740,0x1740,0x1740,0x1740,0x1740,0x1938,0x201,0x201,0x172e,0x172e,0x172e,0x173a,0x173a,0x172e,0x172e, -0x172e,0x172e,0x173d,0x172e,0x172e,0x172e,0x172e,0x1731,0x201,0x201,0x201,0x201,0x1737,0x1737,0x1737,0x1737, -0x1737,0x1737,0x1737,0x1737,0x1737,0x1737,0x1734,0x1734,0x1743,0x1743,0x1743,0x1734,0x1746,0x1746,0x1746,0x1746, -0x1746,0x1746,0x1746,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204, -0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204,0x204, -0x204,0x204,0x204,0x204,0x1758,0x1758,0x1758,0x1758,0x1758,0x1758,0x1758,0x1758,0x1758,0x1758,0x1758,0x1758, -0x1758,0x1758,0x1758,0x1758,0x1758,0x1758,0x1758,0x20a,0x1758,0x1758,0x20a,0x20a,0x20a,0x20a,0x20a,0x1755, -0x1755,0x1755,0x1755,0x1755,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x20d,0x175b,0x20d,0x175b,0x175b, -0x175b,0x175b,0x20d,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b, -0x175b,0x175b,0x20d,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175b,0x175e,0x20d,0x20d, -0x20d,0x20d,0x20d,0x20d,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7, -0x15b7,0x15b7,0x15b7,0x15b7,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x210, -0x210,0x210,0x210,0x210,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764, -0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x1761,0x1761, -0x1761,0x1761,0x1761,0x1761,0x176d,0x176d,0x176d,0x176d,0x176a,0x176d,0x176d,0x1770,0x1773,0x1770,0x1770,0x176d, -0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x213,0x176a, -0x176a,0x176a,0x176a,0x176a,0x17ca,0x17ca,0x17ca,0x17ca,0x17c1,0x17c1,0x17c1,0x17bb,0x17be,0x17be,0x17be,0x19e6, -0x216,0x216,0x216,0x216,0x17c7,0x17c7,0x17c7,0x17c7,0x17c7,0x17c7,0x17c7,0x17c7,0x17c7,0x17c7,0x216,0x216, -0x216,0x216,0x17c4,0x17c4,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x219,0x17e5,0x17e5, -0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5, -0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e2,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x219, -0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x17d0,0x17e2,0x17d3,0x17e5,0x17e8,0x17e8,0x17dc,0x17d9,0x17d9,0x219,0x219, -0x219,0x219,0x219,0x219,0x219,0x219,0x219,0x219,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df, -0x17df,0x17df,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6, -0x17d6,0x219,0x219,0x219,0x17f4,0x17f7,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd, -0x17fd,0x17fd,0x17fd,0x17fd,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x17eb,0x21c,0x21c,0x21c, -0x21c,0x21c,0x21c,0x21c,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956, -0x1956,0x1956,0x1956,0x1956,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x21f,0x17ee,0x17ee,0x17ee,0x17ee, -0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x21f,0x21f,0x17ee, -0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x21f,0x17ee,0x17ee,0x21f,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x21f, -0x21f,0x21f,0x21f,0x21f,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc, -0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x183c,0x18d8,0x1a40,0x1a43,0x1aeb,0x222,0x222,0x222,0x222,0x222,0x222,0x222, -0x222,0x222,0x222,0x222,0x1ae8,0x1ae8,0x222,0x222,0x222,0x222,0x222,0x222,0x222,0x222,0x222,0x222, -0x222,0x222,0x222,0x222,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd, -0x17fd,0x17fd,0x17fd,0x17fd,0x225,0x225,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1, -0x17f1,0x17f1,0x17f1,0x17f1,0x225,0x17fa,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17f1,0x17fa,0x17f1,0x17f1, -0x17fa,0x17f1,0x17f1,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x1800,0x1800,0x1800,0x1800, -0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x228,0x228,0x228,0x228,0x228,0x228,0x228, -0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x1818,0x1818,0x1809,0x1803, -0x1803,0x1818,0x1806,0x181b,0x181b,0x181b,0x181b,0x181e,0x181e,0x1812,0x180f,0x180c,0x1815,0x1815,0x1815,0x1815, -0x1815,0x1815,0x1815,0x1815,0x1815,0x1815,0x1a94,0x1812,0x22b,0x180c,0x193b,0x19e9,0x1a97,0x1a97,0x22b,0x22b, -0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b, -0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x22b,0x1824,0x1824,0x1824,0x1824, -0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824, -0x22e,0x22e,0x22e,0x22e,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821, -0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821,0x1821, -0x22e,0x22e,0x22e,0x22e,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, -0x183f,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x1a46,0x231,0x231,0x231,0x231, -0x231,0x231,0x231,0x231,0x1bba,0x1bba,0x1bba,0x234,0x234,0x234,0x234,0x234,0x234,0x234,0x234,0x234, -0x234,0x234,0x234,0x234,0x276,0x276,0x1c2f,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x276, -0x276,0x276,0x276,0x276,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x237,0x187e,0x187e,0x237,0x187e, -0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e, -0x187e,0x187e,0x187e,0x187e,0x187e,0x1872,0x1872,0x1872,0x1872,0x1872,0x1872,0x237,0x237,0x237,0x1872,0x237, -0x1872,0x1872,0x237,0x1872,0x1872,0x1872,0x1875,0x1872,0x1878,0x1878,0x1881,0x1872,0x237,0x237,0x237,0x237, -0x237,0x237,0x237,0x237,0x187b,0x187b,0x187b,0x187b,0x187b,0x187b,0x187b,0x187b,0x187b,0x187b,0x237,0x237, -0x237,0x237,0x237,0x237,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1, -0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1, -0x23a,0x23a,0x23a,0x23a,0x1890,0x1893,0x1893,0x23d,0x23d,0x23d,0x23d,0x23d,0x23d,0x23d,0x23d,0x23d, -0x23d,0x23d,0x23d,0x23d,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96, -0x1b96,0x1b96,0x1b96,0x1b96,0x18a2,0x18a2,0x18a2,0x18a2,0x18a2,0x18a2,0x18a2,0x18a2,0x18a2,0x18a2,0x18a2,0x240, -0x240,0x240,0x240,0x240,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63, -0x1b63,0x1b63,0x1b63,0x1b63,0x18ae,0x18b1,0x18c0,0x18c0,0x18b1,0x18b4,0x18ae,0x18ab,0x243,0x243,0x243,0x243, -0x243,0x243,0x243,0x243,0x1899,0x1884,0x1884,0x1884,0x1884,0x1884,0x1884,0x1896,0x1896,0x1884,0x1884,0x1884, -0x1899,0x1899,0x1899,0x1899,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef, -0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x246,0x246,0x246,0x246,0x246,0x246,0x246,0x246, -0x246,0x246,0x246,0x246,0x1941,0x1941,0x1941,0x1941,0x1941,0x1941,0x1941,0x1941,0x1941,0x1941,0x1941,0x1941, -0x1941,0x1941,0x246,0x246,0x1a4f,0x1a4f,0x1a4f,0x1a4f,0x1af1,0x1c35,0x1c35,0x1c35,0x1a4f,0x1a4f,0x1a4f,0x1bbd, -0x1bbd,0x279,0x279,0x279,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953, -0x1950,0x1950,0x1950,0x1944,0x1944,0x1944,0x1944,0x1944,0x1944,0x1944,0x1944,0x1944,0x1950,0x194a,0x1947,0x194d, -0x249,0x249,0x249,0x249,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956, -0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x1956,0x24c, -0x24c,0x1956,0x1956,0x1956,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x24f,0x1965,0x1965,0x24f,0x1965,0x1965, +0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x12ab,0x14d,0x14d,0x14d,0x11dc,0x11d0,0x11d0,0x11d0, +0x11d0,0x11d0,0x11d0,0x11d3,0x11e2,0x11e2,0x11d0,0x11d0,0x11d0,0x11d0,0x150,0x12db,0x11d6,0x11d6,0x11d6,0x11d6, +0x11d6,0x11d6,0x11d6,0x11d6,0x11d6,0x11d6,0x150,0x150,0x150,0x150,0x11d0,0x11d0,0x1200,0x11f4,0x1200,0x153, +0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x153, +0x153,0x153,0x153,0x153,0x153,0x153,0x153,0x11fd,0x11fd,0x1203,0x11f7,0x11fa,0x1218,0x1218,0x1218,0x1212, +0x1212,0x1209,0x1212,0x1212,0x1209,0x1212,0x1212,0x121b,0x1215,0x120c,0x156,0x156,0x120f,0x120f,0x120f,0x120f, +0x120f,0x120f,0x120f,0x120f,0x120f,0x120f,0x156,0x156,0x156,0x156,0x156,0x156,0x1221,0x1221,0x1221,0x1221, +0x1221,0x1221,0x1221,0x159,0x159,0x159,0x159,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e, +0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e,0x121e, +0x121e,0x121e,0x121e,0x121e,0x159,0x159,0x159,0x159,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a, +0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x15c,0x1227, +0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1224,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239, +0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x15f,0x15f, +0x15f,0x1233,0x1236,0x1236,0x1236,0x1236,0x1236,0x1236,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f, +0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x123f,0x162,0x162, +0x123c,0x123c,0x123c,0x123c,0x123c,0x123c,0x123c,0x123c,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245, +0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x1245,0x165,0x165,0x165,0x165,0x165, +0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b, +0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b, +0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x124b,0x16b,0x1263,0x1263,0x1b4e,0x16e,0x16e,0x16e,0x16e,0x16e, +0x16e,0x16e,0x16e,0x16e,0x16e,0x1935,0x16e,0x16e,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485, +0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836, +0x1836,0x1836,0x1836,0x1836,0x1836,0x1a88,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171, +0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171, +0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x171,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a, +0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a,0x134a, +0x134a,0x134a,0x134a,0x134a,0x12b4,0x13b0,0x13b0,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174, +0x174,0x174,0x174,0x174,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1, +0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x13b0,0x13b0,0x13b0,0x13b0,0x13b0,0x13b0,0x13b0,0x13b0,0x13b0,0x1839, +0x174,0x174,0x174,0x174,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x12ae,0x174,0x174,0x174, +0x174,0x174,0x174,0x174,0x13d4,0x13d4,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174, +0x174,0x174,0x174,0x174,0x18d8,0x18d8,0x18d8,0x18d8,0x18d8,0x18d8,0x174,0x174,0x174,0x174,0x174,0x174, +0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174, +0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x174,0x1353,0x1353,0x1353,0x1353, +0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353,0x1353, +0x1353,0x1353,0x1353,0x1353,0x1353,0x134d,0x134d,0x134d,0x177,0x177,0x1350,0x177,0x1365,0x1365,0x1365,0x1365, +0x1365,0x1365,0x1356,0x135f,0x1359,0x1359,0x135f,0x135f,0x135f,0x1359,0x135f,0x1359,0x1359,0x1359,0x1362,0x1362, +0x17a,0x17a,0x17a,0x17a,0x17a,0x17a,0x17a,0x17a,0x135c,0x135c,0x135c,0x135c,0x17d,0x1368,0x1368,0x1368, +0x1368,0x1368,0x1368,0x17d,0x17d,0x1368,0x1368,0x1368,0x1368,0x1368,0x1368,0x17d,0x17d,0x1368,0x1368,0x1368, +0x1368,0x1368,0x1368,0x17d,0x17d,0x17d,0x17d,0x17d,0x17d,0x17d,0x17d,0x17d,0x1368,0x1368,0x1368,0x1368, +0x1368,0x1368,0x1368,0x17d,0x1368,0x1368,0x1368,0x1368,0x1368,0x1368,0x1368,0x17d,0x15cf,0x15cf,0x15cf,0x15cf, +0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x136b,0x136b,0x136b,0x136b, +0x136b,0x136b,0x136e,0x1383,0x1383,0x1374,0x1374,0x1374,0x1374,0x1374,0x180,0x180,0x180,0x180,0x1371,0x1371, +0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1371,0x1377,0x1377, +0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1b54,0x1b57,0x1b57,0x1b51,0x1b51,0x1b57,0x180,0x180, +0x180,0x180,0x180,0x180,0x180,0x180,0x180,0x153c,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386, +0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386, +0x1386,0x183,0x183,0x183,0x183,0x183,0x183,0x183,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389, +0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x186,0x186,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389, +0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x153f,0x186,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389, +0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x13b9,0x186,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389, +0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x1389,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f, +0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x153f,0x186,0x186, +0x186,0x186,0x186,0x186,0x186,0x186,0x186,0x186,0x13ce,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x154b,0x154b, +0x154b,0x154b,0x154b,0x154b,0x16bf,0x154b,0x154b,0x154b,0x1791,0x1842,0x1842,0x187b,0x187b,0x1a46,0x1af1,0x1af1, +0x189,0x189,0x189,0x189,0x1c3e,0x1bc0,0x1bc0,0x1bc0,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b,0x154b, +0x154b,0x154b,0x154b,0x16bc,0x16bc,0x189,0x189,0x189,0x154b,0x154b,0x154b,0x154b,0x1842,0x1842,0x1842,0x18de, +0x18de,0x19c2,0x1a46,0x1af1,0x1af1,0x189,0x189,0x189,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x1be4,0x1be4,0x1be4,0x18c, +0x18c,0x18c,0x18c,0x1be4,0x1be4,0x1be4,0x1be4,0x1be4,0x1428,0x1428,0x1428,0x1428,0x18f,0x1428,0x1428,0x1428, +0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428, +0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x18f,0x1428,0x1428,0x18f,0x1428,0x18f,0x18f,0x1428, +0x18f,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x18f,0x1428,0x1428,0x1428,0x1428, +0x18f,0x1428,0x18f,0x1428,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x1428,0x18f,0x18f,0x18f,0x18f,0x1428, +0x18f,0x1428,0x18f,0x1428,0x18f,0x1428,0x1428,0x1428,0x18f,0x1428,0x1428,0x18f,0x1428,0x18f,0x18f,0x1428, +0x18f,0x1428,0x18f,0x1428,0x18f,0x1428,0x18f,0x1428,0x18f,0x1428,0x1428,0x18f,0x1428,0x18f,0x18f,0x1428, +0x1428,0x1428,0x1428,0x18f,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x18f,0x1428,0x1428,0x1428,0x1428, +0x18f,0x1428,0x1428,0x1428,0x1428,0x18f,0x1428,0x18f,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428, +0x1428,0x1428,0x18f,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428, +0x1428,0x1428,0x1428,0x1428,0x18f,0x18f,0x18f,0x18f,0x18f,0x1428,0x1428,0x1428,0x18f,0x1428,0x1428,0x1428, +0x1428,0x1428,0x18f,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428,0x1428, +0x1428,0x1428,0x1428,0x1428,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f, +0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f, +0x18f,0x18f,0x18f,0x18f,0x1425,0x1425,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f,0x18f, +0x18f,0x18f,0x18f,0x18f,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x142b,0x142b,0x142b,0x142b,0x142b, +0x143a,0x142b,0x142e,0x142e,0x142b,0x142b,0x142b,0x1431,0x1431,0x192,0x1437,0x1437,0x1437,0x1437,0x1437,0x1437, +0x1437,0x1437,0x1437,0x1437,0x1434,0x1440,0x1440,0x1440,0x1941,0x193e,0x193e,0x1a8e,0x192,0x192,0x192,0x192, +0x192,0x192,0x192,0x192,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1, +0x15e1,0x15e1,0x15e1,0x15e1,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x144c,0x1449, +0x1443,0x1443,0x1449,0x1449,0x1452,0x1452,0x144c,0x144f,0x144f,0x1449,0x1446,0x195,0x195,0x195,0x195,0x195, +0x195,0x195,0x195,0x195,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455, +0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x198,0x198,0x198,0x198, +0x1716,0x1716,0x1455,0x1455,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716, +0x1716,0x1716,0x1716,0x1716,0x198,0x198,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716, +0x1716,0x1716,0x1716,0x1716,0x1461,0x1461,0x1461,0x1461,0x1461,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19b, +0x19b,0x19b,0x19b,0x19e9,0x1461,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e, +0x145e,0x145e,0x145e,0x145e,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19ec,0x19b,0x19b,0x19b,0x19b, +0x19b,0x19b,0x19b,0x145b,0x145b,0x145b,0x145b,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464,0x1464, +0x1464,0x1464,0x1464,0x1464,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x1485,0x19e,0x19e,0x19e, +0x19e,0x19e,0x19e,0x19e,0x1482,0x1482,0x1482,0x1482,0x1482,0x1482,0x1482,0x1482,0x1482,0x1482,0x19e,0x19e, +0x19e,0x19e,0x19e,0x19e,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1488,0x1a1,0x1a1,0x1a1,0x1a1, +0x1a1,0x1a1,0x1a1,0x1a1,0x12e1,0x12de,0x12e1,0x12bd,0x12de,0x12e4,0x12e4,0x12e7,0x12e4,0x12e7,0x12ea,0x12de, +0x12e7,0x12e7,0x12de,0x12de,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x148b, +0x1494,0x148b,0x1494,0x1494,0x148b,0x148b,0x148b,0x148b,0x148b,0x148b,0x1497,0x148e,0x19f2,0x1b63,0x1a4,0x1a4, +0x1a4,0x1a4,0x1a4,0x1a4,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d, +0x155d,0x155d,0x1a7,0x1a7,0x155a,0x155a,0x155a,0x155a,0x155a,0x1560,0x1a7,0x1a7,0x1a7,0x1a7,0x1a7,0x1a7, +0x1a7,0x1a7,0x1a7,0x1a7,0x1566,0x1566,0x1566,0x1566,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa,0x1aa, +0x1aa,0x1aa,0x1aa,0x1563,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x2af, +0x1bae,0x1bae,0x1bae,0x1bae,0x16cb,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2, +0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2,0x16c2, +0x1ad,0x1ad,0x1ad,0x1ad,0x1a97,0x1b69,0x1b69,0x1b69,0x1b69,0x1b69,0x1b69,0x1b69,0x1b69,0x1b69,0x1b69,0x1b69, +0x1b66,0x1b66,0x1b66,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0, +0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0,0x1b0, +0x1b0,0x1b0,0x1b0,0x1b0,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1b3, +0x1b3,0x1b3,0x1b3,0x1b3,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578, +0x1578,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1b3,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578, +0x1578,0x1578,0x1b3,0x1b3,0x1575,0x156f,0x1572,0x157b,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e, +0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1b6,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566, +0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581, +0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1944,0x1944,0x1944, +0x1944,0x1be7,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1a49,0x1a49,0x1a49,0x1a49,0x1a49,0x1a49,0x1a49,0x1a49, +0x1a49,0x1a49,0x1a49,0x1a49,0x1b9,0x1b9,0x1b9,0x1b9,0x1bc3,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9, +0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x1b9,0x172b,0x16ce,0x158a,0x16d4,0x1bc,0x1596,0x1596,0x1596, +0x1596,0x1596,0x1596,0x1596,0x1596,0x1bc,0x1bc,0x1596,0x1596,0x1bc,0x1bc,0x1596,0x1596,0x1596,0x1596,0x1596, +0x1596,0x1596,0x1596,0x1596,0x1596,0x1596,0x1596,0x1596,0x1596,0x1bc,0x1596,0x1596,0x1596,0x1596,0x1596,0x1596, +0x1596,0x1bc,0x1596,0x1596,0x1bc,0x1596,0x1596,0x1596,0x1596,0x1596,0x1bc,0x19ce,0x16d1,0x1593,0x1584,0x158a, +0x1584,0x158a,0x158a,0x158a,0x158a,0x1bc,0x1bc,0x158a,0x158a,0x1bc,0x1bc,0x158d,0x158d,0x1590,0x1bc,0x1bc, +0x172e,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1584,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x159c,0x1599,0x1599, +0x1596,0x1596,0x158a,0x158a,0x1bc,0x1bc,0x1587,0x1587,0x1587,0x1587,0x1587,0x1587,0x1587,0x1bc,0x1bc,0x1bc, +0x1587,0x1587,0x1587,0x1587,0x1587,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc,0x1bc, +0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1, +0x15b1,0x15b1,0x1bf,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1, +0x15c3,0x15c3,0x15c3,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15ba,0x15bd,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2, +0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2,0x1c2, +0x1731,0x1731,0x1731,0x1731,0x15cf,0x15cc,0x19f5,0x19f5,0x1a9d,0x1aa0,0x1a9a,0x1a9a,0x1c5,0x1c5,0x1c5,0x1c5, +0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, +0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, +0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1, +0x15e1,0x15e1,0x15e1,0x15d8,0x15db,0x15de,0x15e1,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb,0x1cb, +0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15e4,0x15e4,0x1ce,0x1ce,0x1ce,0x1ce,0x15e7,0x15e7,0x15e7,0x15e7,0x15e7, +0x15ed,0x15ed,0x16d7,0x15ed,0x15ed,0x15ed,0x15ea,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce,0x1ce, +0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x1d1,0x1d1,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6,0x15f6, +0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x15f3,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1,0x1d1, +0x15fc,0x160e,0x160e,0x1602,0x160b,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4, +0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1605,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4,0x1d4, +0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614, +0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1614,0x1d7, +0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1611,0x1d7,0x1d7,0x1d7,0x1d7,0x1617,0x1617, +0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f, +0x1620,0x1620,0x1620,0x1620,0x1620,0x161a,0x1623,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620, +0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x161d,0x1620,0x1620,0x1620,0x1620,0x1620,0x1da, +0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629, +0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1dd, +0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635, +0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x1632,0x1632,0x1632,0x1632,0x1632,0x1e0,0x1e0,0x1e0,0x1e0,0x1e0, +0x164d,0x164d,0x1650,0x1650,0x1653,0x1644,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3, +0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x1e3,0x1644,0x1644,0x1644,0x1644,0x1644, +0x1644,0x1644,0x1e3,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d, +0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x1e3,0x1e3,0x1e3,0x1e3,0x1e3,0x164d,0x164d,0x164d, +0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c, +0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, +0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665,0x1665, +0x1665,0x1665,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1e9,0x1662,0x1662,0x1662,0x1662,0x1e9,0x1e9,0x1e9, +0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1668, +0x167a,0x167a,0x1668,0x1668,0x1668,0x1668,0x1ef,0x1ef,0x167a,0x167a,0x167d,0x167d,0x1668,0x1668,0x167a,0x166e, +0x166b,0x1671,0x1683,0x1683,0x1674,0x1674,0x1677,0x1677,0x1677,0x1683,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a, +0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x173a,0x1737,0x1737,0x1737,0x1737,0x1734,0x1734,0x1ef,0x1ef, +0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef, +0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef,0x1ef, +0x1f2,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686,0x1686, +0x1686,0x1686,0x1686,0x1686,0x1686,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2,0x1f2, +0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1f5,0x1f5,0x1f5,0x1f5, +0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689, +0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689, +0x1689,0x1689,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689, +0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689, +0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1f5,0x1f5,0x1aa3,0x1aa3,0x1f5,0x1f5, +0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5, +0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5,0x1f5, +0x168c,0x169b,0x1692,0x168f,0x16a1,0x16a1,0x1695,0x16a1,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8, +0x1698,0x1698,0x1698,0x1698,0x1698,0x1698,0x1698,0x1698,0x1698,0x1698,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8,0x1f8, +0x16a7,0x16a7,0x16a7,0x16a7,0x16a7,0x16a7,0x16a7,0x16a7,0x16a7,0x16a7,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4,0x16a4, +0x16a4,0x16a4,0x16a4,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x1fb,0x16ad, +0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f, +0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x1947,0x1fe,0x1fe,0x173d,0x173d,0x173d, +0x1749,0x1749,0x173d,0x173d,0x173d,0x173d,0x174c,0x173d,0x173d,0x173d,0x173d,0x1740,0x1fe,0x1fe,0x1fe,0x1fe, +0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1743,0x1743,0x1752,0x1752,0x1752,0x1743, +0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201, +0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201, +0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x201,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, +0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x207,0x1767,0x1767,0x207,0x207, +0x207,0x207,0x207,0x1764,0x1764,0x1764,0x1764,0x1764,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x20a, +0x176a,0x20a,0x176a,0x176a,0x176a,0x176a,0x20a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a, +0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x20a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a, +0x176a,0x176d,0x20a,0x20a,0x20a,0x20a,0x20a,0x20a,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6, +0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776, +0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x20d,0x20d,0x20d,0x20d,0x20d, +0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773, +0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x20d,0x20d,0x20d,0x20d,0x20d, +0x20d,0x20d,0x1770,0x1770,0x1770,0x1770,0x1770,0x1770,0x177c,0x177c,0x177c,0x177c,0x1779,0x177c,0x177c,0x177f, +0x1782,0x177f,0x177f,0x177c,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x210,0x210, +0x210,0x210,0x210,0x1779,0x1779,0x1779,0x1779,0x1779,0x17d9,0x17d9,0x17d9,0x17d9,0x17d0,0x17d0,0x17d0,0x17ca, +0x17cd,0x17cd,0x17cd,0x19f8,0x213,0x213,0x213,0x213,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6,0x17d6, +0x17d6,0x17d6,0x213,0x213,0x213,0x213,0x17d3,0x17d3,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4, +0x17f4,0x216,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4, +0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f4,0x17f1,0x17df,0x17df,0x17df,0x17df, +0x17df,0x17df,0x17df,0x216,0x17df,0x17df,0x17df,0x17df,0x17df,0x17df,0x17f1,0x17e2,0x17f4,0x17f7,0x17f7,0x17eb, +0x17e8,0x17e8,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x216,0x17ee,0x17ee,0x17ee,0x17ee, +0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17ee,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x17e5, +0x17e5,0x17e5,0x17e5,0x17e5,0x17e5,0x216,0x216,0x216,0x1803,0x1806,0x180c,0x180c,0x180c,0x180c,0x180c,0x180c, +0x180c,0x180c,0x180c,0x180c,0x180c,0x180c,0x180c,0x180c,0x17fa,0x17fa,0x17fa,0x17fa,0x17fa,0x17fa,0x17fa,0x17fa, +0x17fa,0x219,0x219,0x219,0x219,0x219,0x219,0x219,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965, +0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x21c, +0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd, +0x17fd,0x21c,0x21c,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x17fd,0x21c,0x17fd,0x17fd,0x21c,0x17fd,0x17fd, +0x17fd,0x17fd,0x17fd,0x21c,0x21c,0x21c,0x21c,0x21c,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e, +0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x184b,0x18e7,0x1a52,0x1a55,0x1afd,0x21f,0x21f,0x21f, +0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x1afa,0x1afa,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f, +0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x21f,0x180c,0x180c,0x180c,0x180c,0x180c,0x180c,0x180c,0x180c, +0x180c,0x180c,0x180c,0x180c,0x180c,0x180c,0x180c,0x180c,0x222,0x222,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800, +0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x222,0x1809,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800, +0x1800,0x1809,0x1800,0x1800,0x1809,0x1800,0x1800,0x222,0x222,0x222,0x222,0x222,0x222,0x222,0x222,0x222, +0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x180f,0x225,0x225,0x225, +0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225,0x225, +0x1827,0x1827,0x1818,0x1812,0x1812,0x1827,0x1815,0x182a,0x182a,0x182a,0x182a,0x182d,0x182d,0x1821,0x181e,0x181b, +0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1824,0x1aa6,0x1821,0x228,0x181b,0x194a,0x19fb, +0x1aa9,0x1aa9,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228, +0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228, +0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833,0x1833, +0x1833,0x1833,0x1833,0x1833,0x22b,0x22b,0x22b,0x22b,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830, +0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830,0x1830, +0x1830,0x1830,0x1830,0x1830,0x22b,0x22b,0x22b,0x22b,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e, +0x184e,0x184e,0x184e,0x184e,0x184e,0x19cb,0x19cb,0x19cb,0x19cb,0x19cb,0x1a58,0x1a58,0x1a58,0x1a58,0x1a58,0x1a58, +0x22e,0x22e,0x22e,0x22e,0x22e,0x22e,0x22e,0x22e,0x1bcc,0x1bcc,0x1bcc,0x231,0x231,0x231,0x231,0x231, +0x231,0x231,0x231,0x231,0x231,0x231,0x231,0x231,0x273,0x273,0x1c41,0x273,0x273,0x273,0x273,0x273, +0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x234, +0x188d,0x188d,0x234,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d, +0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x188d,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x234, +0x234,0x234,0x1881,0x234,0x1881,0x1881,0x234,0x1881,0x1881,0x1881,0x1884,0x1881,0x1887,0x1887,0x1890,0x1881, +0x234,0x234,0x234,0x234,0x234,0x234,0x234,0x234,0x188a,0x188a,0x188a,0x188a,0x188a,0x188a,0x188a,0x188a, +0x188a,0x188a,0x234,0x234,0x234,0x234,0x234,0x234,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0, +0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0, +0x18f0,0x18f0,0x18f0,0x18f0,0x237,0x237,0x237,0x237,0x189f,0x18a2,0x18a2,0x23a,0x23a,0x23a,0x23a,0x23a, +0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x23a,0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x1ba8, +0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x1ba8,0x18b1,0x18b1,0x18b1,0x18b1,0x18b1,0x18b1,0x18b1,0x18b1, +0x18b1,0x18b1,0x18b1,0x23d,0x23d,0x23d,0x23d,0x23d,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75, +0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x18bd,0x18c0,0x18cf,0x18cf,0x18c0,0x18c3,0x18bd,0x18ba, +0x240,0x240,0x240,0x240,0x240,0x240,0x240,0x240,0x18a8,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x18a5, +0x18a5,0x1893,0x1893,0x1893,0x18a8,0x18a8,0x18a8,0x18a8,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01, +0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x243,0x243,0x243,0x243, +0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x243,0x1950,0x1950,0x1950,0x1950,0x1950,0x1950,0x1950,0x1950, +0x1950,0x1950,0x1950,0x1950,0x1950,0x1950,0x243,0x243,0x1a61,0x1a61,0x1a61,0x1a61,0x1b03,0x1c47,0x1c47,0x1c47, +0x1a61,0x1a61,0x1a61,0x1bcf,0x1bcf,0x276,0x276,0x276,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962, +0x1962,0x1962,0x1962,0x1962,0x195f,0x195f,0x195f,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953, +0x195f,0x1959,0x1956,0x195c,0x246,0x246,0x246,0x246,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965, 0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1965, -0x1965,0x1965,0x1965,0x1965,0x1965,0x1965,0x1962,0x1962,0x1962,0x1962,0x1962,0x24f,0x1959,0x1959,0x24f,0x1962, -0x1962,0x1959,0x1962,0x195c,0x1965,0x24f,0x24f,0x24f,0x24f,0x24f,0x24f,0x24f,0x196e,0x196e,0x1971,0x1971, -0x1968,0x1968,0x1968,0x1968,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x196b,0x196b,0x196b,0x196b, -0x196b,0x196b,0x196b,0x196b,0x196b,0x196b,0x252,0x252,0x252,0x252,0x252,0x252,0x1974,0x1974,0x1974,0x1974, -0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1977,0x1974,0x1974,0x1974,0x1977,0x1974,0x1974,0x1974, -0x1974,0x255,0x255,0x255,0x255,0x255,0x255,0x255,0x255,0x255,0x255,0x255,0x1980,0x1980,0x1980,0x1980, -0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x1980,0x197a, -0x197a,0x197d,0x197d,0x1983,0x1983,0x258,0x258,0x258,0x258,0x258,0x258,0x258,0x1986,0x1986,0x1986,0x1986, -0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986,0x1986, -0x25b,0x25b,0x25b,0x25b,0x25b,0x25b,0x25b,0x25b,0x25b,0x25b,0x25b,0x25b,0x1989,0x1989,0x1989,0x1989, -0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989,0x1989, -0x1989,0x1989,0x1989,0x198c,0x1995,0x1989,0x1989,0x25e,0x25e,0x25e,0x25e,0x25e,0x1998,0x1998,0x1998,0x1998, -0x1998,0x1998,0x1998,0x199b,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x19a4,0x19a4,0x19a4,0x19a4, -0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x199e,0x199e, -0x199e,0x199e,0x199e,0x199e,0x199e,0x199e,0x199e,0x199e,0x199e,0x19a1,0x19a1,0x19a1,0x19a1,0x19a7,0x19a7,0x19a7, -0x19a7,0x19a7,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264, -0x264,0x264,0x264,0x264,0x1b84,0x1b84,0x1b84,0x1b84,0x1b84,0x1b84,0x1b84,0x1b84,0x1b84,0x1b84,0x1b84,0x1b84, -0x1b84,0x1b84,0x1b84,0x1b84,0x1be7,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bed,0x1bea,0x1bea,0x1bea,0x1bea,0x1bea, -0x1bea,0x1bea,0x1bea,0x1bea,0x1bea,0x1bea,0x1bea,0x1bea,0x1bea,0x1bea,0x267,0x267,0x267,0x267,0x267,0x267, -0x267,0x267,0x267,0x267,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb, -0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x19fb,0x26a,0x26a,0x26a,0x26a,0x26a, -0x26a,0x26a,0x26a,0x26a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x26d,0x26d,0x1a0a,0x1a0a, -0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a, -0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a0a,0x1a07,0x1a07,0x1a07,0x19fe,0x19fe,0x19fe,0x19fe,0x26d,0x26d,0x19fe,0x19fe, -0x1a07,0x1a07,0x1a07,0x1a07,0x1a01,0x1a0a,0x1a04,0x1a0a,0x1a07,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d, -0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d,0x26d, -0x26d,0x26d,0x26d,0x26d,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16, -0x1a16,0x270,0x270,0x270,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16, -0x1a19,0x1a19,0x270,0x270,0x273,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c, -0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c, -0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x273,0x273,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x276, -0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x1a49,0x1a49,0x1a49,0x276,0x276,0x1c32,0x276,0x276, -0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x1a4c,0x1a4c,0x1a4c,0x1a4c,0x276,0x276,0x276,0x276, -0x276,0x276,0x276,0x276,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1, -0x18e1,0x18e1,0x18e1,0x18e1,0x1a4f,0x1a4f,0x1a4f,0x1af1,0x1af1,0x1af1,0x1af1,0x1c35,0x1c35,0x279,0x279,0x279, -0x279,0x279,0x279,0x279,0x1a4f,0x1a4f,0x1a4f,0x1a4f,0x1a4f,0x1a4f,0x1af1,0x1af1,0x1af1,0x1af1,0x1af1,0x1af1, -0x1af1,0x1af1,0x1af1,0x1af1,0x1af1,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1c35,0x1c35,0x1c35,0x1af1,0x1af1,0x1af1,0x1af1, -0x1af1,0x1af1,0x1af1,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1c35,0x1c35,0x1c35,0x279,0x1c35,0x1af1,0x1af1,0x1af1,0x1bc0, -0x1bc0,0x1bc0,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x1c35,0x1c35,0x1af1,0x1af1,0x1af1,0x1af1, -0x1af1,0x1af1,0x1af1,0x1bbd,0x1bbd,0x1bbd,0x1c35,0x1c35,0x279,0x279,0x279,0x279,0x1bbd,0x1bbd,0x1bbd,0x1bbd, -0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1c35,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x1bc0,0x1bc0,0x1bc0,0x1bc0, -0x1bc0,0x1bc0,0x1bc0,0x1c38,0x1c38,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x1a25,0x1a1f,0x1a1f,0x1a1f, -0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x27c,0x27c, -0x27c,0x27c,0x27c,0x27c,0x27c,0x27c,0x27c,0x27c,0x27c,0x27c,0x27c,0x1a22,0x1a31,0x1a31,0x1a31,0x1a31, -0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a28,0x1a28,0x1a28,0x1a28,0x1a2e,0x1a2e,0x1a2e,0x1a2e, -0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x27f,0x27f,0x27f,0x27f,0x27f,0x1a2b,0x1a9d,0x1a9d,0x1a9d,0x1a9d, -0x1a9d,0x1a9a,0x1a9a,0x1a9a,0x1a9a,0x1a9a,0x1a9a,0x1a9a,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282, -0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x1ab8,0x1ab8,0x1ab8,0x1ab8, -0x1ab8,0x1ab8,0x1ab8,0x285,0x285,0x1ab8,0x285,0x285,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8, -0x285,0x1ab8,0x1ab8,0x285,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1ab8, -0x1ab8,0x1ab8,0x1ab8,0x1ab8,0x1aa0,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x285,0x1aaf,0x1ab2,0x285,0x285,0x1aa0, -0x1aa0,0x1ab5,0x1aa6,0x1abb,0x1aaf,0x1abb,0x1aaf,0x1aa3,0x1abe,0x1aa9,0x1abe,0x285,0x285,0x285,0x285,0x285, -0x285,0x285,0x285,0x285,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x285,0x285, -0x285,0x285,0x285,0x285,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7, -0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x288,0x288,0x288,0x288,0x288,0x288, -0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288, -0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x288,0x1ac4,0x1ac4,0x1ac4,0x1ac4, -0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x28e, -0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x28e, +0x1965,0x1965,0x1965,0x249,0x249,0x1965,0x1965,0x1965,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x24c,0x1974, +0x1974,0x24c,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974, +0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1971,0x1971,0x1971,0x1971,0x1971,0x24c, +0x1968,0x1968,0x24c,0x1971,0x1971,0x1968,0x1971,0x196b,0x1974,0x24c,0x24c,0x24c,0x24c,0x24c,0x24c,0x24c, +0x197d,0x197d,0x1980,0x1980,0x1977,0x1977,0x1977,0x1977,0x24f,0x24f,0x24f,0x24f,0x24f,0x24f,0x24f,0x24f, +0x197a,0x197a,0x197a,0x197a,0x197a,0x197a,0x197a,0x197a,0x197a,0x197a,0x24f,0x24f,0x24f,0x24f,0x24f,0x24f, +0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1986,0x1983,0x1983,0x1983, +0x1986,0x1983,0x1983,0x1983,0x1983,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x252,0x252, +0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992, +0x1992,0x1992,0x198f,0x1989,0x1989,0x198c,0x198c,0x1995,0x1995,0x255,0x255,0x255,0x255,0x255,0x255,0x255, +0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998,0x1998, +0x1998,0x1998,0x1998,0x1998,0x258,0x258,0x258,0x258,0x258,0x258,0x258,0x258,0x258,0x258,0x258,0x258, +0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b, +0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199e,0x19a7,0x199b,0x199b,0x25b,0x25b,0x25b,0x25b,0x25b, +0x19aa,0x19aa,0x19aa,0x19aa,0x19aa,0x19aa,0x19aa,0x19ad,0x25e,0x25e,0x25e,0x25e,0x25e,0x25e,0x25e,0x25e, +0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6,0x19b6, +0x19b6,0x19b6,0x19b0,0x19b0,0x19b0,0x19b0,0x19b0,0x19b0,0x19b0,0x19b0,0x19b0,0x19b0,0x19b0,0x19b3,0x19b3,0x19b3, +0x19b3,0x19b9,0x19b9,0x19b9,0x19b9,0x19b9,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261, +0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x261,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96, +0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1b96,0x1bf9,0x1bff,0x1bff,0x1bff,0x1bff,0x1bff,0x1bff,0x1bfc, +0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x264,0x264, +0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x264,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d, +0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x1a0d,0x267, +0x267,0x267,0x267,0x267,0x267,0x267,0x267,0x267,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c, +0x26a,0x26a,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c, +0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a1c,0x1a19,0x1a19,0x1a19,0x1a10,0x1a10,0x1a10,0x1a10, +0x26a,0x26a,0x1a10,0x1a10,0x1a19,0x1a19,0x1a19,0x1a19,0x1a13,0x1a1c,0x1a16,0x1a1c,0x1a19,0x26a,0x26a,0x26a, +0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a, +0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x26a,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28, +0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x26d,0x26d,0x26d,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a28, +0x1a28,0x1a28,0x1a28,0x1a28,0x1a2b,0x1a2b,0x26d,0x26d,0x270,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e, +0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e, +0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x1a2e,0x270,0x270,0x273,0x273,0x273,0x273, +0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x1a5b,0x1a5b,0x1a5b,0x273, +0x273,0x1c44,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x1a5e,0x1a5e,0x1a5e,0x1a5e, +0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x273,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0, +0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x1a61,0x1a61,0x1a61,0x1b03,0x1b03,0x1b03,0x1b03,0x1c47, +0x1c47,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x1a61,0x1a61,0x1a61,0x1a61,0x1a61,0x1a61,0x1b03,0x1b03, +0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1c47,0x1c47,0x1c47, +0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1c47,0x1c47,0x1c47,0x276,0x1c47, +0x1b03,0x1b03,0x1b03,0x1bd2,0x1bd2,0x1bd2,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x276,0x1c47,0x1c47, +0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1b03,0x1bcf,0x1bcf,0x1bcf,0x1c47,0x1c47,0x276,0x276,0x276,0x276, +0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1bcf,0x1c47,0x276,0x276,0x276,0x276,0x276,0x276,0x276, +0x1bd2,0x1bd2,0x1bd2,0x1bd2,0x1bd2,0x1bd2,0x1bd2,0x1c4a,0x1c4a,0x276,0x276,0x276,0x276,0x276,0x276,0x276, +0x1a37,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31, +0x1a31,0x1a31,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x279,0x1a34, +0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a3a,0x1a3a,0x1a3a,0x1a3a, +0x1a40,0x1a40,0x1a40,0x1a40,0x1a40,0x1a40,0x1a40,0x1a40,0x1a40,0x1a40,0x27c,0x27c,0x27c,0x27c,0x27c,0x1a3d, +0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x1aac,0x27f,0x27f,0x27f,0x27f, +0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f,0x27f, +0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x282,0x282,0x1aca,0x282,0x282,0x1aca,0x1aca,0x1aca,0x1aca, +0x1aca,0x1aca,0x1aca,0x1aca,0x282,0x1aca,0x1aca,0x282,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca, +0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1aca,0x1ab2,0x1ac1,0x1ac1,0x1ac1,0x1ac1,0x1ac1,0x282,0x1ac1, +0x1ac4,0x282,0x282,0x1ab2,0x1ab2,0x1ac7,0x1ab8,0x1acd,0x1ac1,0x1acd,0x1ac1,0x1ab5,0x1ad0,0x1abb,0x1ad0,0x282, +0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x282,0x1abe,0x1abe,0x1abe,0x1abe,0x1abe,0x1abe,0x1abe,0x1abe, +0x1abe,0x1abe,0x282,0x282,0x282,0x282,0x282,0x282,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09, +0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x285,0x285, +0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285, +0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285,0x285, +0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6, +0x1ad6,0x1ad6,0x1ad6,0x28b,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6, +0x1ad6,0x1ad6,0x1ad6,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b, +0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9, +0x1ad9,0x1ad9,0x28b,0x28b,0x28b,0x28b,0x28b,0x28b,0x1b0c,0x1b0c,0x1b0c,0x1b0c,0x1b0c,0x1b0c,0x1b0c,0x1b0c, +0x1b0c,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e, 0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e,0x28e, -0x28e,0x28e,0x28e,0x28e,0x1ac7,0x1ac7,0x1ac7,0x1ac7,0x1ac7,0x1ac7,0x1ac7,0x1ac7,0x1ac7,0x1ac7,0x28e,0x28e, -0x28e,0x28e,0x28e,0x28e,0x1afa,0x1afa,0x1afa,0x1afa,0x1afa,0x1afa,0x1afa,0x1afa,0x1afa,0x291,0x291,0x291, -0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291, -0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291, -0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x294,0x1aca,0x1aca,0x1acd,0x294,0x294, -0x1ad0,0x1ad0,0x294,0x294,0x294,0x294,0x294,0x294,0x294,0x294,0x294,0x294,0x294,0x294,0x294,0x294, -0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b60,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x1b63,0x297, -0x1b66,0x1b66,0x297,0x297,0x297,0x297,0x297,0x297,0x1b5d,0x1b5d,0x1b5d,0x1b5d,0x1b5d,0x1b5d,0x1b5d,0x1b5d, -0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c, -0x1b6c,0x1b69,0x1b69,0x29a,0x29a,0x29a,0x29a,0x29a,0x29a,0x29a,0x29a,0x29a,0x29a,0x29a,0x29a,0x29a, -0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x29d,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x29d,0x1b6f,0x1b6f,0x29d, -0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x29d, -0x1b72,0x1b78,0x1b78,0x1b75,0x1b75,0x1b75,0x2a3,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75, -0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75, -0x1b75,0x2a3,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3, -0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7e,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b, -0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x1b7b,0x2a6, -0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x1bf0,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6, -0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6, -0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x1b84,0x1b84,0x1b81,0x1b81, -0x1b81,0x1b81,0x1b87,0x1b87,0x1b87,0x1b87,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9, -0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x1a9d,0x1a9d,0x1a9d,0x1a9d, -0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1a9d,0x1b8d,0x1b8d,0x1b8d,0x1b8d, +0x28e,0x28e,0x28e,0x28e,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x291,0x1adc, +0x1adc,0x1adf,0x291,0x291,0x1ae2,0x1ae2,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291,0x291, +0x291,0x291,0x291,0x291,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b75,0x1b72,0x1b75,0x1b75,0x1b75, +0x1b75,0x1b75,0x1b75,0x294,0x1b78,0x1b78,0x294,0x294,0x294,0x294,0x294,0x294,0x1b6f,0x1b6f,0x1b6f,0x1b6f, +0x1b6f,0x1b6f,0x1b6f,0x1b6f,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e, +0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7b,0x1b7b,0x297,0x297,0x297,0x297,0x297,0x297,0x297,0x297,0x297, +0x297,0x297,0x297,0x297,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x29a,0x1b81,0x1b81,0x1b81,0x1b81, +0x29a,0x1b81,0x1b81,0x29a,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81,0x1b81, +0x1b81,0x1b81,0x1b81,0x29a,0x1b84,0x1b8a,0x1b8a,0x1b87,0x1b87,0x1b87,0x2a0,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87, +0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87, +0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x2a0,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x1b87,0x2a0, +0x2a0,0x2a0,0x2a0,0x2a0,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b90,0x1b8d, 0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d, -0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x2ac,0x1b8a,0x1b8a,0x1b8a,0x1b8a, -0x1b8a,0x1b8a,0x1b8a,0x1b8a,0x1b8a,0x1b8a,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x1554,0x1554,0x1554,0x1554, -0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1554,0x1b93,0x1b93,0x1b93,0x1b93, -0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b93,0x1b90,0x2af,0x2af,0x2af,0x2af,0x2af, -0x2af,0x2af,0x2af,0x2af,0x2af,0x2af,0x2af,0x2af,0x2af,0x2af,0x2af,0x2af,0x1b9c,0x1b9c,0x1b9c,0x1b9c, -0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x2b2,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x2b2, -0x1b9c,0x1b9c,0x2b2,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x2b2,0x1b99, -0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x2b2,0x1b99, -0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x1b99,0x2b2,0x1b99,0x1b99,0x2b2,0x2b2,0x2b2,0x1ba2,0x1ba2,0x1ba2,0x1ba2, -0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x2b5,0x2b5,0x1ba2,0x1ba2,0x1ba2,0x1ba2, -0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x2b5, -0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f, -0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8, +0x1b8d,0x1b8d,0x1b8d,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x2a3, +0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3, +0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3,0x2a3, +0x1b96,0x1b96,0x1b93,0x1b93,0x1b93,0x1b93,0x1b99,0x1b99,0x1b99,0x1b99,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6, +0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6,0x2a6, +0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf,0x1aaf, +0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f, +0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x2a9, +0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x1b9c,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9,0x2a9, +0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d, +0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba5,0x1ba2,0x2ac, +0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac,0x2ac, +0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x1bae,0x2af,0x1bae,0x1bae,0x1bae,0x1bae, +0x1bae,0x1bae,0x1bae,0x2af,0x1bae,0x1bae,0x2af,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab, +0x1bab,0x1bab,0x2af,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab, +0x1bab,0x1bab,0x2af,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x1bab,0x2af,0x1bab,0x1bab,0x2af,0x2af,0x2af, +0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x2b2,0x2b2, +0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4, +0x1bb4,0x1bb4,0x1bb4,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x2b2,0x1bb1,0x1bb1,0x1bb1,0x1bb1, +0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x2b5,0x2b5,0x2b5,0x2b5, +0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5, +0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x2b5,0x1c05,0x1c05,0x1c05, +0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0e,0x1c0e,0x1c0e,0x2b8,0x2b8, 0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8, -0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x2b8,0x1bf3,0x1bf3,0x1bf3,0x1bf9,0x1bf9,0x1bf9,0x1bf9, -0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bfc,0x1bfc,0x1bfc,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb, -0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x1bff,0x1bff,0x1bff,0x1bff, -0x1bff,0x1bff,0x1bff,0x1bff,0x1bff,0x1bff,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be, -0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be, -0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02, -0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x1c02,0x2c1,0x2c1,0x2c1,0x2c1, -0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x1c05,0x1c05,0x1c1a,0x1c11,0x1c17,0x1c17,0x1c17,0x1c17, -0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x2c4,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17, -0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17, -0x1c11,0x1c11,0x1c05,0x1c05,0x1c05,0x1c05,0x1c05,0x2c4,0x2c4,0x2c4,0x1c11,0x1c11,0x1c05,0x1c14,0x1c08,0x1c1d, -0x1c1d,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0e,0x1c0e,0x1c0e,0x1c0e, -0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4,0x1c26,0x1c26,0x1c26,0x1c26, -0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c26,0x1c20,0x1c20,0x1c20,0x1c20,0x1c23,0x1c23,0x1c23,0x1c23, -0x1c23,0x1c23,0x1c23,0x1c23,0x1c23,0x1c23,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2ca,0x2ca,0x2ca,0x2ca, +0x1c11,0x1c11,0x1c11,0x1c11,0x1c11,0x1c11,0x1c11,0x1c11,0x1c11,0x1c11,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb, +0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb, +0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x2bb,0x1c14,0x1c14,0x1c14,0x1c14, +0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14,0x1c14, +0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x2be,0x1c17,0x1c17,0x1c2c,0x1c23, +0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x2c1,0x1c29,0x1c29, +0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29,0x1c29, +0x1c29,0x1c29,0x1c29,0x1c29,0x1c23,0x1c23,0x1c17,0x1c17,0x1c17,0x1c17,0x1c17,0x2c1,0x2c1,0x2c1,0x1c23,0x1c23, +0x1c17,0x1c26,0x1c1a,0x1c2f,0x1c2f,0x1c1d,0x1c1d,0x1c1d,0x1c1d,0x1c1d,0x1c1d,0x1c1d,0x1c1d,0x1c1d,0x1c1d,0x1c1d, +0x1c20,0x1c20,0x1c20,0x1c20,0x1c20,0x1c20,0x1c20,0x1c20,0x1c20,0x1c20,0x2c1,0x2c1,0x2c1,0x2c1,0x2c1,0x2c1, +0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c38,0x1c32,0x1c32,0x1c32,0x1c32, +0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x1c35,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4,0x2c4, +0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, +0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, +0x2c7,0x2c7,0x95d,0x95d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d, +0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, +0x2c7,0x2c7,0x2c7,0x2c7,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0x12a5, +0x12a5,0x12a5,0x2ca,0x2ca,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97, +0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0x2ca,0x2ca, 0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca, -0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x18db,0x2dc,0x2dc,0x2dc, -0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc,0x2ca,0x2ca,0x2ca,0x2ca, 0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca, -0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x95d,0x95d,0x1c3b,0x1c3b,0x1c3b,0x1c3b, -0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x2ca,0x2ca,0x2ca,0x2ca, -0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0x2ca,0xc6c,0xc6c,0xc6c,0xc6c, -0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0x129f,0x129f,0x129f,0x2cd,0x2cd,0xe94,0xe94,0xe94,0xe94, -0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94, -0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd, -0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd, -0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0x2cd,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88, -0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88, -0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0x2d0,0x2d0,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1, -0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x1bab,0x1bab,0x1bab, -0x1bab,0x1c29,0x2d3,0x2d3,0x2d3,0x2d3,0x2d3,0x2d3,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8, -0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8, -0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x2d6,0x2d6,0x1785,0x1785,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9, -0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db, -0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4, -0x1af4,0x1af4,0x1af4,0x2df,0x2df,0x2df,0x2df,0x2df,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b, -0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x3e7,0x3db,0x3db,0x3db,0x3db,0x3db,0x3db,0x3db, -0x3db,0x3e7,0x3e7,0x3e7,0x3e7,0x3e1,0x111f,0x12f6,0x3ea,0x927,0x92a,0x3d8,0x3d8,0x111c,0x12f3,0x12f3, -0x3ed,0x3ed,0x3ed,0x3ed,0x3ed,0x3ed,0x3ed,0x3ed,0x111c,0x3db,0x3db,0x3e7,0xcae,0x3ea,0x3ea,0x3ea, +0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b, +0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0x2cd,0x2cd, +0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7, +0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x1bbd,0x1bbd,0x1bbd,0x1bbd,0x1c3b,0x2d0,0x2d0,0x2d0,0x2d0,0x2d0,0x2d0, +0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1, +0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x2d3,0x2d3, +0x1794,0x1794,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6,0x2d6, +0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea, +0x18ea,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9,0x2d9, +0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59, +0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x2dc,0x2dc,0x2dc,0x2dc,0x2dc, +0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d, +0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59, +0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x2df,0x2df, +0x3e7,0x3db,0x3db,0x3db,0x3db,0x3db,0x3db,0x3db,0x3db,0x3e7,0x3e7,0x3e7,0x3e7,0x3e1,0x1125,0x12fc, +0x3ea,0x927,0x92a,0x3d8,0x3d8,0x1122,0x12f9,0x12f9,0x3ed,0x3ed,0x3ed,0x3ed,0x3ed,0x3ed,0x3ed,0x3ed, +0x1122,0x3db,0x3db,0x3e7,0xcb1,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea, 0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea, -0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3db,0x3db,0x8af,0x8b2,0x945,0x945, -0x945,0x945,0x945,0x945,0x945,0x945,0x945,0x945,0x3e4,0xf7e,0xf7b,0x12f9,0x12f9,0x12f9,0x12f9,0x12f9, -0x14b8,0x1122,0x1122,0xed0,0xed0,0xda1,0xed0,0xed0,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea, -0x3ea,0x3ed,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ed,0x3ea,0x3ea,0x3ed,0x3ea,0x3ea,0x3ea, -0x3ea,0x3ea,0x12f3,0x12f6,0x3de,0x3ea,0x3e7,0x3e7,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489, -0x489,0x12ff,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489, -0x489,0x489,0x12ff,0x1857,0x1857,0xf9c,0x47a,0x483,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5, -0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0xba3, -0xba3,0xdb0,0xdb0,0x8b5,0xdad,0x13da,0x13da,0x13da,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8, +0x3ea,0x3ea,0x3db,0x3db,0x8af,0x8b2,0x945,0x945,0x945,0x945,0x945,0x945,0x945,0x945,0x945,0x945, +0x3e4,0xf81,0xf7e,0x12ff,0x12ff,0x12ff,0x12ff,0x12ff,0x14c1,0x1128,0x1128,0xed3,0xed3,0xda4,0xed3,0xed3, +0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ed,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea, +0x3ea,0x3ed,0x3ea,0x3ea,0x3ed,0x3ea,0x3ea,0x3ea,0x3ea,0x3ea,0x12f9,0x12fc,0x3de,0x3ea,0x3e7,0x3e7, +0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x1305,0x489,0x489,0x489,0x489,0x489,0x489, +0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x1305,0x1866,0x1866,0xf9f,0x47a,0x483, +0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5, +0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0x4c5,0xba6,0xba6,0xdb3,0xdb3,0x8b5,0xdb0,0x13e3,0x13e3,0x13e3, 0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8, -0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4ce,0x4ce,0x4ce,0x1137,0x1137,0x1137,0x1137,0x1137, -0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb, +0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8,0x4c8, +0x4ce,0x4ce,0x4ce,0x113d,0x113d,0x113d,0x113d,0x113d,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb, 0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb, -0x4cb,0x4cb,0x1134,0x1134,0x1134,0x1134,0x1134,0x1134,0x4d1,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce, +0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x4cb,0x113a,0x113a,0x113a,0x113a,0x113a,0x113a, +0x4d1,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce, 0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce, -0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4ce,0x4da,0x4d4,0x4da,0x4d4, +0x4ce,0x4ce,0x4ce,0x4ce,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4, 0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4, -0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4d4,0x4d4, -0x4d4,0x4d4,0x4d7,0x9a2,0xfc9,0xfc9,0xfcc,0xfc9,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4, +0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4d4,0x4d4,0x4d4,0x4d4,0x4d7,0x9a2,0xfcc,0xfcc,0xfcf,0xfcc, 0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4, -0x4da,0x4d4,0xfcc,0xfc9,0xfcc,0xfc9,0xfcc,0xfc9,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6, -0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x6a5,0x6a5,0x6a8,0x504,0x6b4,0x6b1,0x6b1,0x6ae, -0x52e,0x52e,0x4ec,0x4ec,0x4ec,0x4ec,0x4ec,0xb34,0x6b7,0x510,0x6cf,0x6d2,0x525,0x6b7,0x513,0x513, -0x504,0x51f,0x51f,0x6a5,0x52b,0x528,0x6ab,0x4fe,0x4f5,0x4f5,0x4f8,0x4f8,0x4f8,0x4f8,0x4f8,0x4fb, -0x4f8,0x4f8,0x4f8,0x4ef,0x537,0x534,0x531,0x531,0x6c3,0x519,0x516,0x6c0,0x6bd,0x6ba,0x6cc,0x507, -0x6c9,0x6c9,0x51c,0x51f,0x6c6,0x6c6,0x51c,0x51f,0x501,0x504,0x504,0x504,0x522,0x50d,0x50a,0xbb8, -0xad7,0xad7,0xad4,0xad4,0xad4,0xad4,0xbaf,0xbaf,0xbaf,0xbaf,0xbb5,0xcdb,0xcd8,0xdbc,0xdbf,0xbb2, -0xdbf,0xdbf,0xdbf,0xdbf,0xdbc,0xdbf,0xdbf,0xbac,0x55b,0x55b,0x55b,0x55b,0x55b,0x55b,0x55b,0x558, -0x55e,0x73e,0x55b,0x9a5,0x9c6,0xada,0xada,0xada,0xbbe,0xbbe,0xdc5,0xdc5,0xdc5,0xdc5,0x1140,0x1143, -0x1143,0x1314,0x14a6,0x14d0,0x14d3,0x14d3,0x16da,0x185a,0x56a,0x56a,0x582,0x6e4,0x567,0x6de,0x56a,0x57f, -0x567,0x6e4,0x579,0x582,0x582,0x582,0x579,0x579,0x582,0x582,0x582,0x6ea,0x567,0x582,0x6e7,0x567, -0x576,0x582,0x582,0x582,0x582,0x582,0x567,0x567,0x56d,0x6de,0x6e1,0x567,0x582,0x567,0x6ed,0x567, -0x582,0x570,0x588,0x6f0,0x582,0x582,0x573,0x579,0x582,0x582,0x585,0x582,0x579,0x57c,0x57c,0x57c, -0x57c,0xae3,0xae0,0xcde,0xdce,0xbd3,0xbd6,0xbd6,0xbd0,0xbcd,0xbcd,0xbcd,0xbcd,0xbd6,0xbd3,0xbd3, -0xbd3,0xbd3,0xbca,0xbcd,0xdcb,0xedc,0xedf,0xfd2,0x1146,0x1146,0x1146,0x6f6,0x6f3,0x58b,0x58e,0x58e, -0x58e,0x58e,0x58e,0x6f3,0x6f6,0x6f6,0x6f3,0x58e,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc, -0x6fc,0x6fc,0x6fc,0x6fc,0x597,0x597,0x597,0x597,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9, -0x6f9,0x6f9,0x591,0x591,0x591,0x591,0x591,0x591,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d, -0x59a,0x59d,0x59d,0x59d,0x59d,0x59d,0x5a0,0x59a,0x59d,0x59d,0x59a,0x59a,0x59a,0x59a,0x59d,0x59d, -0x6ff,0x6ff,0x59a,0x59a,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d, -0x59d,0x5a0,0x5a0,0x5a0,0x59d,0x59d,0x702,0x59d,0x702,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d, -0x59a,0x59d,0x59a,0x59a,0x59a,0x59a,0x59a,0x59a,0x59d,0x59d,0x59a,0x6ff,0x59a,0x59a,0x59a,0xae9, -0xae9,0xae9,0xae9,0xae9,0xae9,0xae9,0xae9,0xae9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9,0xbd9, -0xbd9,0xbd9,0xbd9,0xbd9,0x705,0x5a3,0x705,0x705,0x5a6,0x5a3,0x5a3,0x705,0x705,0x5a6,0x5a3,0x705, -0x5a6,0x5a3,0x5a3,0x705,0x5a3,0x705,0x5b2,0x5af,0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x5a3, -0x5a3,0x705,0x705,0x705,0x705,0x5a3,0x5a3,0x705,0x5a6,0x705,0x5a6,0x705,0x705,0x705,0x705,0x705, -0x70b,0x5a9,0x705,0x5a9,0x5a9,0x5a3,0x5a3,0x5a3,0x705,0x705,0x705,0x705,0x5a3,0x5a3,0x5a3,0x5a3, -0x705,0x705,0x5a3,0x5a3,0x5a3,0x5a6,0x5a3,0x5a3,0x5a6,0x5a3,0x5a3,0x5a6,0x705,0x5a6,0x5a3,0x5a3, -0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, -0x5a3,0x5a3,0x5a3,0x5a3,0x708,0x705,0x5a6,0x5a3,0x705,0x705,0x705,0x705,0x5a3,0x5a3,0x705,0x705, -0x5a3,0x5a6,0x708,0x708,0x5a6,0x5a6,0x5a3,0x5a3,0x5a6,0x5a6,0x5a3,0x5a3,0x5a6,0x5a6,0x5a3,0x5a3, -0x5a3,0x5a3,0x5a3,0x5a3,0x5a6,0x5a6,0x705,0x705,0x5a6,0x5a6,0x705,0x705,0x5a6,0x5a6,0x5a3,0x5a3, -0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x705,0x5a3,0x5a3, -0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a6,0x5a6,0x5a6,0x5a6, -0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x705, +0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0x4da,0x4d4,0xfcf,0xfcc,0xfcf,0xfcc,0xfcf,0xfcc, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9, +0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e6,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9,0x4e9, +0x6a5,0x6a5,0x6a8,0x504,0x6b4,0x6b1,0x6b1,0x6ae,0x52e,0x52e,0x4ec,0x4ec,0x4ec,0x4ec,0x4ec,0xb37, +0x6b7,0x510,0x6cf,0x6d2,0x525,0x6b7,0x513,0x513,0x504,0x51f,0x51f,0x6a5,0x52b,0x528,0x6ab,0x4fe, +0x4f5,0x4f5,0x4f8,0x4f8,0x4f8,0x4f8,0x4f8,0x4fb,0x4f8,0x4f8,0x4f8,0x4ef,0x537,0x534,0x531,0x531, +0x6c3,0x519,0x516,0x6c0,0x6bd,0x6ba,0x6cc,0x507,0x6c9,0x6c9,0x51c,0x51f,0x6c6,0x6c6,0x51c,0x51f, +0x501,0x504,0x504,0x504,0x522,0x50d,0x50a,0xbbb,0xada,0xada,0xad7,0xad7,0xad7,0xad7,0xbb2,0xbb2, +0xbb2,0xbb2,0xbb8,0xcde,0xcdb,0xdbf,0xdc2,0xbb5,0xdc2,0xdc2,0xdc2,0xdc2,0xdbf,0xdc2,0xdc2,0xbaf, +0x55b,0x55b,0x55b,0x55b,0x55b,0x55b,0x55b,0x558,0x55e,0x73e,0x55b,0x9a5,0x9c6,0xadd,0xadd,0xadd, +0xbc1,0xbc1,0xdc8,0xdc8,0xdc8,0xdc8,0x1146,0x1149,0x1149,0x131a,0x14af,0x14d9,0x14dc,0x14dc,0x16e9,0x1869, +0x56a,0x56a,0x582,0x6e4,0x567,0x6de,0x56a,0x57f,0x567,0x6e4,0x579,0x582,0x582,0x582,0x579,0x579, +0x582,0x582,0x582,0x6ea,0x567,0x582,0x6e7,0x567,0x576,0x582,0x582,0x582,0x582,0x582,0x567,0x567, +0x56d,0x6de,0x6e1,0x567,0x582,0x567,0x6ed,0x567,0x582,0x570,0x588,0x6f0,0x582,0x582,0x573,0x579, +0x582,0x582,0x585,0x582,0x579,0x57c,0x57c,0x57c,0x57c,0xae6,0xae3,0xce1,0xdd1,0xbd6,0xbd9,0xbd9, +0xbd3,0xbd0,0xbd0,0xbd0,0xbd0,0xbd9,0xbd6,0xbd6,0xbd6,0xbd6,0xbcd,0xbd0,0xdce,0xedf,0xee2,0xfd5, +0x114c,0x114c,0x114c,0x6f6,0x6f3,0x58b,0x58e,0x58e,0x58e,0x58e,0x58e,0x6f3,0x6f6,0x6f6,0x6f3,0x58e, +0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x6fc,0x597,0x597,0x597,0x597, +0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x6f9,0x591,0x591,0x591,0x591,0x591,0x591, +0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59a,0x59d,0x59d,0x59d,0x59d,0x59d,0x5a0,0x59a, +0x59d,0x59d,0x59a,0x59a,0x59a,0x59a,0x59d,0x59d,0x6ff,0x6ff,0x59a,0x59a,0x59d,0x59d,0x59d,0x59d, +0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x5a0,0x5a0,0x5a0,0x59d,0x59d,0x702,0x59d, +0x702,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59d,0x59a,0x59d,0x59a,0x59a,0x59a,0x59a,0x59a,0x59a, +0x59d,0x59d,0x59a,0x6ff,0x59a,0x59a,0x59a,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec, +0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0x705,0x5a3,0x705,0x705, +0x5a6,0x5a3,0x5a3,0x705,0x705,0x5a6,0x5a3,0x705,0x5a6,0x5a3,0x5a3,0x705,0x5a3,0x705,0x5b2,0x5af, +0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x5a3,0x5a3,0x705,0x705,0x705,0x705,0x5a3,0x5a3,0x705, +0x5a6,0x705,0x5a6,0x705,0x705,0x705,0x705,0x705,0x70b,0x5a9,0x705,0x5a9,0x5a9,0x5a3,0x5a3,0x5a3, +0x705,0x705,0x705,0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x705,0x5a3,0x5a3,0x5a3,0x5a6,0x5a3,0x5a3, +0x5a6,0x5a3,0x5a3,0x5a6,0x705,0x5a6,0x5a3,0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x5a3, +0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x708,0x705,0x5a6,0x5a3, +0x705,0x705,0x705,0x705,0x5a3,0x5a3,0x705,0x705,0x5a3,0x5a6,0x708,0x708,0x5a6,0x5a6,0x5a3,0x5a3, +0x5a6,0x5a6,0x5a3,0x5a3,0x5a6,0x5a6,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a6,0x5a6,0x705,0x705, +0x5a6,0x5a6,0x705,0x705,0x5a6,0x5a6,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, +0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x5a3,0x5a3, +0x5a3,0x5a3,0x5a3,0x5a3,0x5a6,0x5a6,0x5a6,0x5a6,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, +0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x705,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, -0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, -0x5a6,0x5a6,0x5a6,0x5a6,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a6,0x5a6,0x5a6,0x5a6,0x5a3,0x5ac, -0x5a3,0x5a3,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc,0xbdc, -0x5b5,0xaec,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5be,0x5bb,0x5be,0x5bb,0x5b5,0x5b5,0x5b5,0x5b5, -0x5b5,0x5b5,0x70e,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x7fe,0x7fe,0x5b5,0x5b5,0x5b5,0x5b5, -0x5b8,0x5b8,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x804,0x801,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5, +0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a6,0x5a6,0x5a6,0x5a6,0x5a3,0x5a3,0x5a3,0x5a3, +0x5a3,0x5a3,0x5a6,0x5a6,0x5a6,0x5a6,0x5a3,0x5ac,0x5a3,0x5a3,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf, +0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0x5b5,0xaef,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5, +0x5be,0x5bb,0x5be,0x5bb,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x70e,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5, +0x5b5,0x5b5,0x7fe,0x7fe,0x5b5,0x5b5,0x5b5,0x5b5,0x5b8,0x5b8,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5, +0x5b5,0x804,0x801,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5, 0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5, -0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0xaec, -0xbe2,0xaec,0xaec,0xaec,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1, +0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0x5b5,0xaef,0xbe5,0xaef,0xaef,0xaef,0x5c1,0x5c1,0x5c1,0x5c1, 0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1, -0x5c1,0x5c1,0x5c1,0x5c1,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x5c7,0xc3f, -0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f,0xc3f, -0xc3f,0xc3f,0xc3f,0xd4d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d, -0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x5ca,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd, -0x5cd,0x5cd,0x5cd,0x5cd,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d, -0x5cd,0x5cd,0x5cd,0x5cd,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d, -0x71d,0x71d,0x71d,0x71d,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720, -0x720,0x720,0x720,0x720,0x5d0,0x5d0,0x720,0x720,0x720,0x720,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5, -0xbe5,0xbe5,0xbe5,0xbe5,0x726,0x726,0x5d3,0x723,0x723,0x723,0x723,0x723,0x723,0x723,0x5d3,0x5d3, -0x5d3,0x5d3,0x5d6,0x5d6,0x5d6,0x5d6,0x726,0x726,0x5d6,0x5d6,0x726,0x726,0x5d3,0x5d3,0x5d3,0x5d3, -0x726,0x726,0x5d6,0x5d6,0x726,0x726,0x5d3,0x5d3,0x5d3,0x5d3,0x726,0x726,0x723,0x5d3,0x5d6,0x726, -0x5d3,0x5d3,0x723,0x726,0x726,0x726,0x5d6,0x5d6,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3, -0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x726,0x723,0x726,0x723,0x5d3,0x5d6,0x5d6,0x5d6,0x5d6,0x5d6, -0x5d6,0x5d3,0x5d3,0x723,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xaf2,0xbe8,0xbe8,0xbe8,0xbe8, -0xbe8,0xc57,0xc57,0xbe8,0x5dc,0x5dc,0x5dc,0x5dc,0x5d9,0x72f,0x72f,0x5d9,0x5d9,0x729,0x5d9,0x5d9, -0x5d9,0x5d9,0x729,0x729,0x5d9,0x5d9,0x5d9,0x5d9,0xd56,0xd56,0xbeb,0xbeb,0xdd7,0xaf5,0x5dc,0x5dc, -0x72c,0x5df,0x72c,0x5dc,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9, -0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5dc,0x5dc,0x5dc, -0x5d9,0x5d9,0x5d9,0x5d9,0x72f,0x5d9,0x72f,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x807,0x807,0x807,0x807, -0x807,0x807,0x807,0x807,0x807,0x807,0x807,0x807,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9, -0x5d9,0x5d9,0x5d9,0x5d9,0x72f,0x72f,0x5e2,0x72f,0x729,0x729,0x5d9,0x729,0x72c,0x729,0x729,0x5d9, -0x729,0x72f,0x5e2,0x72f,0xaf5,0xaf5,0xbee,0xbee,0xbee,0xbee,0xbee,0xbee,0xbee,0xbee,0xbee,0xbee, -0xbee,0xbee,0xdd4,0xe8b,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5, -0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e8,0x139b,0x139b,0x139b,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x14d9,0x5ee,0x5ee,0x5ee,0x5ee,0x139b,0x5e8,0x5e8,0x5ee,0x5ee,0x139e,0x139e, -0x5f4,0x5f4,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x139b,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x735,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x139b,0x5e8,0x139b,0x5e8,0x5e8,0x5e8,0x5e8,0x139b, -0x139b,0x139b,0x5e8,0x1299,0x5e8,0x5e8,0x5e8,0x5f1,0x5f1,0x5f1,0x5f1,0x1320,0x1320,0x5e8,0x5eb,0x5eb, -0x5ee,0x5e8,0x5e8,0x5e8,0xbf4,0xbf1,0xbf4,0xbf1,0xbf4,0xbf1,0xbf4,0xbf1,0xbf4,0xbf1,0xbf4,0xbf1, -0xbf4,0xbf1,0x732,0x732,0x732,0x732,0x732,0x732,0x732,0x732,0x732,0x732,0x5e8,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x139b,0x5e8,0x5e8,0x5e8, -0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x139b,0x615,0x615,0x615,0x615, +0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x5c1,0x717,0x717,0x717,0x717, +0x717,0x717,0x717,0x717,0x717,0x717,0x5c7,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42, +0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xc42,0xd50,0x71d,0x71d,0x71d,0x71d, +0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d, +0x5ca,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x5cd,0x71d,0x71d,0x71d,0x71d, +0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x5cd,0x5cd,0x5cd,0x5cd,0x71d,0x71d,0x71d,0x71d, +0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x720,0x720,0x720,0x720, +0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x720,0x5d0,0x5d0,0x720,0x720, +0x720,0x720,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0xbe8,0x726,0x726,0x5d3,0x723, +0x723,0x723,0x723,0x723,0x723,0x723,0x5d3,0x5d3,0x5d3,0x5d3,0x5d6,0x5d6,0x5d6,0x5d6,0x726,0x726, +0x5d6,0x5d6,0x726,0x726,0x5d3,0x5d3,0x5d3,0x5d3,0x726,0x726,0x5d6,0x5d6,0x726,0x726,0x5d3,0x5d3, +0x5d3,0x5d3,0x726,0x726,0x723,0x5d3,0x5d6,0x726,0x5d3,0x5d3,0x723,0x726,0x726,0x726,0x5d6,0x5d6, +0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x5d3,0x726,0x723, +0x726,0x723,0x5d3,0x5d6,0x5d6,0x5d6,0x5d6,0x5d6,0x5d6,0x5d3,0x5d3,0x723,0xaf5,0xaf5,0xaf5,0xaf5, +0xaf5,0xaf5,0xaf5,0xaf5,0xbeb,0xbeb,0xbeb,0xbeb,0xbeb,0xc5a,0xc5a,0xbeb,0x5dc,0x5dc,0x5dc,0x5dc, +0x5d9,0x72f,0x72f,0x5d9,0x5d9,0x729,0x5d9,0x5d9,0x5d9,0x5d9,0x729,0x729,0x5d9,0x5d9,0x5d9,0x5d9, +0xd59,0xd59,0xbee,0xbee,0xdda,0xaf8,0x5dc,0x5dc,0x72c,0x5df,0x72c,0x5dc,0x5d9,0x5d9,0x5d9,0x5d9, +0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9, +0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5dc,0x5dc,0x5dc,0x5d9,0x5d9,0x5d9,0x5d9,0x72f,0x5d9,0x72f,0x5d9, +0x5d9,0x5d9,0x5d9,0x5d9,0x807,0x807,0x807,0x807,0x807,0x807,0x807,0x807,0x807,0x807,0x807,0x807, +0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x5d9,0x72f,0x72f,0x5e2,0x72f, +0x729,0x729,0x5d9,0x729,0x72c,0x729,0x729,0x5d9,0x729,0x72f,0x5e2,0x72f,0xaf8,0xaf8,0xbf1,0xbf1, +0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xdd7,0xe8e,0x5e5,0x5e5,0x5e5,0x5e5, +0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5,0x5e5, +0x5e8,0x13a4,0x13a4,0x13a4,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x14e2,0x5ee,0x5ee,0x5ee, +0x5ee,0x13a4,0x5e8,0x5e8,0x5ee,0x5ee,0x13a7,0x13a7,0x5f4,0x5f4,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, +0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x13a4,0x5e8,0x5e8,0x5e8, +0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, +0x5e8,0x735,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, +0x13a4,0x5e8,0x13a4,0x5e8,0x5e8,0x5e8,0x5e8,0x13a4,0x13a4,0x13a4,0x5e8,0x129f,0x5e8,0x5e8,0x5e8,0x5f1, +0x5f1,0x5f1,0x5f1,0x1326,0x1326,0x5e8,0x5eb,0x5eb,0x5ee,0x5e8,0x5e8,0x5e8,0xbf7,0xbf4,0xbf7,0xbf4, +0xbf7,0xbf4,0xbf7,0xbf4,0xbf7,0xbf4,0xbf7,0xbf4,0xbf7,0xbf4,0x732,0x732,0x732,0x732,0x732,0x732, +0x732,0x732,0x732,0x732,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, +0x5e8,0x5e8,0x5e8,0x5e8,0x13a4,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8,0x5e8, +0x5e8,0x5e8,0x5e8,0x13a4,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615, 0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615, -0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x60c,0x60c,0x60c,0x60c,0x60c,0x60c, +0x615,0x615,0x60c,0x60c,0x60c,0x60c,0x60c,0x60c,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f, 0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f, -0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0xb46,0xb46,0xb46,0xb46, -0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0xb46,0x615,0x615,0x95a,0x615, -0x615,0x615,0x615,0x615,0x615,0x615,0x60c,0x60c,0xbf7,0xd7a,0x1b0f,0x1b0f,0x612,0x618,0x615,0x60f, +0x60f,0x60f,0x60f,0x60f,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49,0xb49, +0xb49,0xb49,0xb49,0xb49,0x615,0x615,0x95a,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x60c,0x60c, +0xbfa,0xd7d,0x1b21,0x1b21,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f, 0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f, -0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x615,0x60f,0x615,0x60f, -0x615,0x60f,0x615,0x60f,0x615,0x60f,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f, -0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x615,0x60f,0x612,0x618,0x615,0x60f,0x615,0x60f, -0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x615,0x60f,0x1323,0x1323,0x1323,0x1323,0x1323,0x1323, -0x1323,0x1323,0x1323,0x1323,0x1323,0x1323,0x1323,0x1323,0x615,0x60f,0x615,0x60f,0x615,0x60f,0x612,0x618, 0x612,0x618,0x615,0x60f,0x615,0x60f,0x615,0x60f,0x615,0x60f,0x615,0x60f,0x615,0x60f,0x615,0x60f, -0x612,0x615,0x60f,0x612,0x615,0x60f,0x612,0x618,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f, -0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x612, -0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615, -0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f, -0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x612,0x612,0x612,0x612,0x612,0x612,0x612, -0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x60f,0x615,0x918,0x91b,0x1b0f,0x1b0f,0x1b0f,0x1b0f, -0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x1b0f,0x612,0x60f,0x612,0x612, -0x612,0x612,0x612,0x612,0x60f,0x612,0x60f,0x60f,0x612,0x612,0x60f,0x60f,0x612,0x612,0x60f,0x612, -0x60f,0x612,0x60f,0x60f,0x612,0x60f,0x60f,0x612,0x60f,0x612,0x60f,0x60f,0x612,0x60f,0x612,0x612, -0x60f,0x60f,0x60f,0x612,0x60f,0x60f,0x60f,0x60f,0x60f,0x612,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f, +0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f, +0x615,0x60f,0x612,0x618,0x615,0x60f,0x615,0x60f,0x612,0x618,0x615,0x60f,0x612,0x618,0x615,0x60f, +0x615,0x60f,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329,0x1329, +0x615,0x60f,0x615,0x60f,0x615,0x60f,0x612,0x618,0x612,0x618,0x615,0x60f,0x615,0x60f,0x615,0x60f, +0x615,0x60f,0x615,0x60f,0x615,0x60f,0x615,0x60f,0x612,0x615,0x60f,0x612,0x615,0x60f,0x612,0x618, 0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f, -0x612,0x612,0x60f,0x60f,0x612,0x60f,0x612,0x60f,0x60f,0x60f,0x60f,0x60f,0x612,0x612,0x612,0x612, -0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612, -0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x618, +0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612, 0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615, +0x615,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f, +0x60f,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618, +0x60f,0x615,0x918,0x91b,0x1b21,0x1b21,0x1b21,0x1b21,0x1b21,0x1b21,0x1b21,0x1b21,0x1b21,0x1b21,0x1b21,0x1b21, +0x1b21,0x1b21,0x1b21,0x1b21,0x612,0x60f,0x612,0x612,0x612,0x612,0x612,0x612,0x60f,0x612,0x60f,0x60f, +0x612,0x612,0x60f,0x60f,0x612,0x612,0x60f,0x612,0x60f,0x612,0x60f,0x60f,0x612,0x60f,0x60f,0x612, +0x60f,0x612,0x60f,0x60f,0x612,0x60f,0x612,0x612,0x60f,0x60f,0x60f,0x612,0x60f,0x60f,0x60f,0x60f, +0x60f,0x612,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f, +0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x60f,0x612,0x612,0x60f,0x60f,0x612,0x60f,0x612,0x60f, +0x60f,0x60f,0x60f,0x60f,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612, +0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x612, +0x612,0x612,0x612,0x612,0x612,0x612,0x612,0x618,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615, 0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615, -0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618, -0x618,0x618,0x618,0x618,0x618,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615, -0x61b,0x61b,0x61b,0x61b,0xfde,0xfde,0xfde,0x14dc,0x14dc,0x14dc,0x14dc,0x14dc,0x14dc,0x14dc,0x16e0,0x16e0, -0x864,0x86a,0x86a,0x876,0x876,0x867,0x85e,0x867,0x85e,0x867,0x85e,0x867,0x85e,0x867,0x85e,0x867, -0x62a,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x62a, -0x624,0x627,0x62d,0x62a,0x624,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627, -0x62d,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627, +0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618, +0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x618,0x615,0x615,0x615, +0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x615,0x61b,0x61b,0x61b,0x61b,0xfe1,0xfe1,0xfe1,0x14e5, +0x14e5,0x14e5,0x14e5,0x14e5,0x14e5,0x14e5,0x16ef,0x16ef,0x864,0x86a,0x86a,0x876,0x876,0x867,0x85e,0x867, +0x85e,0x867,0x85e,0x867,0x85e,0x867,0x85e,0x867,0x62a,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x62a, +0x624,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x62a,0x624,0x627, +0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x62a,0x624,0x62a,0x624,0x62a, +0x624,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627, 0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627, -0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x62d,0x62a,0x624,0x627,0x714,0x714,0x714,0x714, -0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714, +0x62d,0x62a,0x624,0x627,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714, +0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x714,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711, 0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711, -0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711, -0x711,0x711,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a, -0x71a,0x71a,0x71a,0x71a,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717, -0x717,0x717,0x717,0x717,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d, +0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x711,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a, +0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x71a,0x717,0x717,0x717,0x717, +0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x717,0x71d,0x71d,0x71d,0x71d, 0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d, -0x71d,0x71d,0x71d,0x71d,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738, +0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x71d,0x738,0x738,0x738,0x738, 0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738, -0x738,0x738,0x738,0x738,0xc45,0x8c7,0x8c1,0x8be,0x8c4,0x8bb,0x74d,0x750,0x750,0x750,0x750,0x750, -0x750,0x750,0x750,0x750,0x8cd,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d, +0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0x738,0xc48,0x8c7,0x8be,0x8bb, +0x8c1,0x8c4,0x74d,0x750,0x750,0x750,0x750,0x750,0x750,0x750,0x750,0x750,0x8cd,0x74d,0x74d,0x74d, 0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d, -0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x8ca,0x8ca,0x753,0x8dc,0x8df,0x8e5,0x80a,0x816,0x8fa,0x813, -0x8d3,0x8d0,0x8d3,0x8d0,0x8d9,0x8d6,0x8d9,0x8d6,0x8d3,0x8d0,0x810,0x8e5,0x8d3,0x8d0,0x8d3,0x8d0, -0x8d3,0x8d0,0x8d3,0x8d0,0x8eb,0x8f1,0x8ee,0x8ee,0x759,0x795,0x795,0x795,0x795,0x795,0x795,0x78f, -0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f, -0x78f,0x78f,0x78f,0x75c,0x777,0x756,0x77d,0x780,0x77a,0x792,0x792,0x792,0x792,0x792,0x792,0x78c, -0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c, -0x78c,0x78c,0x78c,0x75c,0x777,0x756,0x777,0xc48,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8, +0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x74d,0x8ca,0x8ca, +0x753,0x8dc,0x8df,0x8e5,0x80a,0x816,0x8fa,0x813,0x8d3,0x8d0,0x8d3,0x8d0,0x8d9,0x8d6,0x8d9,0x8d6, +0x8d3,0x8d0,0x810,0x8e5,0x8d3,0x8d0,0x8d3,0x8d0,0x8d3,0x8d0,0x8d3,0x8d0,0x8eb,0x8f1,0x8ee,0x8ee, +0x759,0x795,0x795,0x795,0x795,0x795,0x795,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f, +0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x78f,0x75c,0x777,0x756,0x77d,0x780, +0x77a,0x792,0x792,0x792,0x792,0x792,0x792,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c, +0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x78c,0x75c,0x777,0x756,0x777,0xc4b, +0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8, 0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8, -0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x7f8,0x1293,0x1293,0x1293,0x1293,0x1293,0x7fb, -0x810,0x813,0x813,0x813,0x813,0x813,0x813,0x813,0x813,0x813,0x933,0x933,0x933,0x933,0x819,0x819, -0x8e8,0x8f7,0x8f7,0x8f7,0x8f7,0x8f4,0x80d,0x8e2,0xb19,0xb19,0xb19,0xc5a,0xc78,0xc75,0xb37,0x8b8, -0x81f,0x81c,0x81f,0x822,0x81c,0x81f,0x81c,0x81f,0x81c,0x81f,0x81c,0x81c,0x81c,0x81c,0x81c,0x81c, -0x81f,0x81f,0x81c,0x81f,0x81f,0x81c,0x81f,0x81f,0x81c,0x81f,0x81f,0x81c,0x81f,0x81f,0x81c,0x81c, -0xc7b,0x831,0x82b,0x831,0x82b,0x831,0x82b,0x831,0x82b,0x831,0x82b,0x82b,0x82e,0x82b,0x82e,0x82b, -0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b, -0x82e,0x82b,0x82e,0x831,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b, -0x82e,0x82e,0x82b,0x82e,0x82e,0x82b,0x82e,0x82e,0x82b,0x82e,0x82e,0x82b,0x82e,0x82e,0x82b,0x82b, -0x82b,0x82b,0x82b,0x831,0x82b,0x831,0x82b,0x831,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x831,0x82b, -0x82b,0x82b,0x82b,0x82b,0x82e,0x831,0x831,0x82e,0x82e,0x82e,0x82e,0x900,0x903,0x834,0x837,0xc63, +0x7f8,0x7f8,0x1299,0x1299,0x1299,0x1299,0x1299,0x7fb,0x810,0x813,0x813,0x813,0x813,0x813,0x813,0x813, +0x813,0x813,0x933,0x933,0x933,0x933,0x819,0x819,0x8e8,0x8f7,0x8f7,0x8f7,0x8f7,0x8f4,0x80d,0x8e2, +0xb1c,0xb1c,0xb1c,0xc5d,0xc7b,0xc78,0xb3a,0x8b8,0x81f,0x81c,0x81f,0x822,0x81c,0x81f,0x81c,0x81f, +0x81c,0x81f,0x81c,0x81c,0x81c,0x81c,0x81c,0x81c,0x81f,0x81f,0x81c,0x81f,0x81f,0x81c,0x81f,0x81f, +0x81c,0x81f,0x81f,0x81c,0x81f,0x81f,0x81c,0x81c,0xc7e,0x831,0x82b,0x831,0x82b,0x831,0x82b,0x831, +0x82b,0x831,0x82b,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b, +0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x82b,0x82e,0x831,0x82b,0x82e,0x82b,0x82e, +0x82b,0x82e,0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x82e,0x82e,0x82b,0x82e,0x82e,0x82b,0x82e,0x82e, +0x82b,0x82e,0x82e,0x82b,0x82e,0x82e,0x82b,0x82b,0x82b,0x82b,0x82b,0x831,0x82b,0x831,0x82b,0x831, +0x82b,0x82b,0x82b,0x82b,0x82b,0x82b,0x831,0x82b,0x82b,0x82b,0x82b,0x82b,0x82e,0x831,0x831,0x82e, +0x82e,0x82e,0x82e,0x900,0x903,0x834,0x837,0xc66,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d, 0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d, +0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x840,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d, 0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d, -0x840,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d, -0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x83d,0x849,0x849,0x849,0x849, +0x83d,0x83d,0x83d,0x83d,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849, 0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849, -0x849,0x849,0x849,0x849,0x849,0x849,0x849,0x849,0xd5f,0xd5f,0xe8e,0x843,0x90c,0x90c,0x90c,0x90c, -0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0xd59,0xd59,0xd59,0xd59,0x84c,0x84c,0x84c,0x84c, +0xd62,0xd62,0xe91,0x843,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c, +0xd5c,0xd5c,0xd5c,0xd5c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c, 0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c, -0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x84c,0x1a58,0x912,0x912,0x912,0x912, -0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x84f,0x84f,0x84f, -0x84f,0x84f,0x84f,0xd62,0xd62,0xd62,0xd62,0x915,0x915,0x915,0x915,0x915,0x84f,0x84f,0x84f,0x84f, +0x84c,0x84c,0x84c,0x1a6a,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912, +0x912,0x912,0x912,0x912,0x912,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0xd65,0xd65,0xd65,0xd65,0x915, +0x915,0x915,0x915,0x915,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f, 0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f, -0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0xd62,0xd62, -0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, +0x84f,0x84f,0x84f,0x84f,0x84f,0x84f,0xd65,0xd65,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, 0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852, -0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855, +0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x852,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912, 0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855, -0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91, -0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91,0xe91, -0x1104,0x1104,0x1104,0x1104,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858, +0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855,0x855, +0x855,0x855,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94, +0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0x110a,0x110a,0x110a,0x110a,0x858,0x858,0x858,0x858, 0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858, -0x858,0x858,0x858,0x858,0x858,0x858,0x85b,0x85b,0x858,0x85b,0x858,0x85b,0x85b,0x858,0x858,0x858, -0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x85b,0x858,0x85b,0x858,0x85b,0x85b,0x858,0x858,0x85b, -0x85b,0x85b,0x858,0x858,0x858,0x858,0x1497,0x1497,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c, -0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c, +0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x85b,0x85b, +0x858,0x85b,0x858,0x85b,0x85b,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x858,0x85b, +0x858,0x85b,0x858,0x85b,0x85b,0x858,0x858,0x85b,0x85b,0x85b,0x858,0x858,0x858,0x858,0x14a0,0x14a0, +0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f, +0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c, 0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c, -0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x90c,0x12d2,0x12d2,0x12d2,0x12d2,0x127b,0x127b,0x127b,0x127b, -0x127b,0x127b,0x127b,0x127b,0xd59,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66, -0xc66,0xc66,0xc66,0xc66,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f, +0x12d8,0x12d8,0x12d8,0x12d8,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0x1281,0xd5c,0xc69,0xc69,0xc69, +0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0x90f,0x90f,0x90f,0x90f, 0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f, -0x90f,0x90f,0x90f,0x90f,0x90f,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66,0xc66, -0xc66,0xc66,0xc66,0xc66,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912, +0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0x90f,0xc69,0xc69,0xc69, +0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0xc69,0x912,0x912,0x912,0x912, 0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912, -0x912,0x912,0x912,0xd62,0x99c,0x97e,0x97e,0x97e,0x97e,0x978,0x97e,0x97e,0x990,0x97e,0x97e,0x97b, -0x987,0x98d,0x98d,0x98d,0x98d,0x98d,0x990,0x978,0x984,0x978,0x978,0x978,0x96c,0x96c,0x978,0x978, -0x978,0x978,0x978,0x978,0x993,0x993,0x993,0x993,0x993,0x993,0x993,0x993,0x993,0x993,0x978,0x978, -0x978,0x978,0x978,0x978,0x978,0x978,0x978,0x978,0x97b,0x96c,0x978,0x96c,0x978,0x96c,0x98a,0x981, -0x98a,0x981,0x999,0x999,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8, +0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0x912,0xd65,0x99c,0x97e,0x97e,0x97e, +0x97e,0x978,0x97e,0x97e,0x990,0x97e,0x97e,0x97b,0x987,0x98d,0x98d,0x98d,0x98d,0x98d,0x990,0x978, +0x984,0x978,0x978,0x978,0x96c,0x96c,0x978,0x978,0x978,0x978,0x978,0x978,0x993,0x993,0x993,0x993, +0x993,0x993,0x993,0x993,0x993,0x993,0x978,0x978,0x978,0x978,0x978,0x978,0x978,0x978,0x978,0x978, +0x97b,0x96c,0x978,0x96c,0x978,0x96c,0x98a,0x981,0x98a,0x981,0x999,0x999,0x9a8,0x9a8,0x9a8,0x9a8, 0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8, -0x9a8,0x9a8,0x9a8,0x9a8,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab, +0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9a8,0x9ab,0x9ab,0x9ab,0x9ab, 0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab, -0x9ab,0x9ab,0x9ab,0x9ab,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae, +0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ab,0x9ae,0x9ae,0x9ae,0x9ae, 0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae, -0x9ae,0x9ae,0x9ae,0x9ae,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7, +0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9ae,0x9b7,0x9b7,0x9b7,0x9b7, 0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7, -0x9b7,0x9b7,0x9b1,0x9b1,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba, +0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b1,0x9b1,0x9ba,0x9ba,0x9ba,0x9ba, 0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba, -0x9ba,0x9ba,0x9b4,0x9b4,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7, +0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9b4,0x9b4,0x9b7,0x9b7,0x9b7,0x9b7, 0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7, -0x9b7,0x9b7,0x9b7,0x9b7,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba, +0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9b7,0x9ba,0x9ba,0x9ba,0x9ba, 0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba, -0x9ba,0x9ba,0x9ba,0x9ba,0x9bd,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0, +0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9ba,0x9bd,0x9c0,0x9c0,0x9c0, +0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0, +0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9bd,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0, 0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0, -0x9bd,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0, -0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0x9c0,0xa4d,0xa4d,0xfc3,0xa4d, -0xa4d,0xa4d,0xa50,0xa4d,0xfc3,0xa4d,0xa4d,0xfba,0xa47,0xa3b,0xa3b,0xa3b,0xa3b,0xa4a,0xa3b,0xfab, -0xfab,0xfab,0xa3b,0xa3e,0xa47,0xa41,0xfb1,0xfbd,0xfbd,0xfab,0xfab,0xfc3,0xb3d,0xb3d,0xb3d,0xb3d, -0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xb3d,0xa53,0xa53,0xa44,0xa44,0xa44,0xa44,0xa4d,0xa4d,0xa4d,0xa4d, -0xa4d,0xa4d,0xa4a,0xa4a,0xa3b,0xa3b,0xfc3,0xfc3,0xfc3,0xfc3,0xfab,0xfab,0xa4d,0xa4d,0xa4d,0xa4d, +0x9c0,0x9c0,0x9c0,0x9c0,0xa4d,0xa4d,0xfc6,0xa4d,0xa4d,0xa4d,0xa50,0xa4d,0xfc6,0xa4d,0xa4d,0xfbd, +0xa47,0xa3b,0xa3b,0xa3b,0xa3b,0xa4a,0xa3b,0xfae,0xfae,0xfae,0xa3b,0xa3e,0xa47,0xa41,0xfb4,0xfc0, +0xfc0,0xfae,0xfae,0xfc6,0xb40,0xb40,0xb40,0xb40,0xb40,0xb40,0xb40,0xb40,0xb40,0xb40,0xa53,0xa53, +0xa44,0xa44,0xa44,0xa44,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4a,0xa4a,0xa3b,0xa3b,0xfc6,0xfc6, +0xfc6,0xfc6,0xfae,0xfae,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d, 0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d, -0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa4d,0xa62,0xa62,0xa62,0xa62, -0xa62,0xa62,0xa62,0xdb9,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, +0xa4d,0xa4d,0xa4d,0xa4d,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdbc,0xa62,0xa62,0xa62,0xa62, 0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, -0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdb9,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, -0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68, +0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xdbc, +0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62,0xa62, +0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68, 0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68, -0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa68,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e, -0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6b,0xa71,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0x113d, -0x113d,0x113d,0x113d,0x113d,0x113d,0x113d,0x113d,0x113d,0x113a,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e, +0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6b,0xa71,0xa6e, +0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143,0x1143, +0x1140,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e, 0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e, -0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa6e,0xa83,0xa83,0xa83,0xa83, +0xa6e,0xa6e,0xa6e,0xa6e,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83, 0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83, -0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xa83,0xaa7,0xaa7,0xaa7,0xaaa, -0xaaa,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7, -0xa8f,0xa8f,0xaa4,0xa86,0xa86,0xa86,0xa86,0xa86,0xa86,0xa86,0xaa4,0xaa4,0xaa7,0xaa7,0xaa7,0xaa7, +0xa83,0xa83,0xa83,0xa83,0xaa7,0xaa7,0xaa7,0xaaa,0xaaa,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7, +0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xa8f,0xa8f,0xaa4,0xa86,0xa86,0xa86,0xa86,0xa86, +0xa86,0xa86,0xaa4,0xaa4,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7, 0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7, -0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xaa7,0xac8,0xac8,0xac8,0xac8, -0xac8,0xab3,0xab3,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8, -0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8, -0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xacb,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8, -0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8,0xac8, -0xac8,0xac8,0xac8,0xac8,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec, -0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xaec,0xbe2, -0xbe2,0xbe2,0xbe2,0xbe2,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8, -0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8,0xaf8, -0xaf8,0xaf8,0xaf8,0xaf8,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a, -0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a,0xb0a, -0xb0a,0xb0a,0xb0a,0xb0a,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10, -0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10,0xb10, -0xb10,0xb10,0xb10,0xb10,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c, -0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0xb1c,0x13a1,0x13a1,0x13a1,0x1ad3, -0x1ad3,0x1ad3,0x1ad3,0x1ad3,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f, +0xaa7,0xaa7,0xaa7,0xaa7,0xacb,0xacb,0xacb,0xacb,0xacb,0xab6,0xab6,0xacb,0xacb,0xacb,0xacb,0xacb, +0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb, +0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xace, +0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb, +0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xacb,0xaef,0xaef,0xaef,0xaef, +0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef, +0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xaef,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xafb,0xafb,0xafb,0xafb, +0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb, +0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xafb,0xb0d,0xb0d,0xb0d,0xb0d, +0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d, +0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb0d,0xb13,0xb13,0xb13,0xb13, +0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13, +0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb13,0xb1f,0xb1f,0xb1f,0xb1f, 0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f, -0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0xb1f,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6, +0xb1f,0xb1f,0xb1f,0xb1f,0x13aa,0x13aa,0x13aa,0x1ae5,0x1ae5,0x1ae5,0x1ae5,0x1ae5,0xb22,0xb22,0xb22,0xb22, 0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22, -0xb22,0xb22,0xb22,0xb22,0xb22,0xb25,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22, -0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22, -0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb28,0xb28,0xc69,0xc69,0xb28,0xb28,0xb28,0xb28, -0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xc69,0xb28,0xb28,0xb28, -0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb28,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c, -0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c, -0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0xb4c,0x14df,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xced,0xced, -0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52, -0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xb52,0xcea,0xcea,0xd38,0xd38,0xd38,0xd38, -0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xb55,0xb55,0xb55,0xb55, +0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0xb22,0x1ae8,0x1ae8, +0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0x1ae8,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25, +0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb28,0xb25,0xb25, +0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25, +0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25,0xb25, +0xb2b,0xb2b,0xc6c,0xc6c,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b, +0xb2b,0xb2b,0xb2b,0xb2b,0xc6c,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b,0xb2b, +0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f, +0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0xb4f,0x14e8, +0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xcf0,0xcf0,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55, 0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55, -0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb55,0xb58,0xb58,0xb58,0xb58, +0xb55,0xb55,0xced,0xced,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b, +0xd3b,0xd3b,0xd3b,0xd3b,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58, 0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58, -0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb58,0xb67,0xb67,0xb67,0xb67, -0xb67,0xb5e,0xb6a,0xb70,0xb70,0xb70,0xb64,0xb64,0xb64,0xb6d,0xb61,0xb61,0xb61,0xb61,0xb61,0xb5b, -0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb70,0xb70,0xb70,0xb70,0xb70,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb67,0xb67, -0xb70,0xb70,0xb70,0xb64,0xb64,0xb70,0xb70,0xb70,0xb70,0xb70,0xb70,0xb70,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb70,0xb70,0xb70,0xb70,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb64,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0xb64, -0xb64,0xb64,0xb64,0xb64,0xb64,0xb64,0x16e3,0x16e3,0xb7c,0xb73,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb73,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb73,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb73,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, +0xb58,0xb58,0xb58,0xb58,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b, +0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b,0xb5b, +0xb5b,0xb5b,0xb5b,0xb5b,0xb6a,0xb6a,0xb6a,0xb6a,0xb6a,0xb61,0xb6d,0xb73,0xb73,0xb73,0xb67,0xb67, +0xb67,0xb70,0xb64,0xb64,0xb64,0xb64,0xb64,0xb5e,0xb5e,0xb5e,0xb5e,0xb5e,0xb5e,0xb5e,0xb5e,0xb73, +0xb73,0xb73,0xb73,0xb73,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67, +0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67, +0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb6a,0xb6a,0xb73,0xb73,0xb73,0xb67,0xb67,0xb73,0xb73,0xb73, +0xb73,0xb73,0xb73,0xb73,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67, +0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb73,0xb73,0xb73,0xb73,0xb67,0xb67, +0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb6a,0xb6a,0xb6a,0xb6a,0xb6a, +0xb6a,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67, +0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0xb67,0x16f2,0x16f2, +0xb7f,0xb76,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb76,0xb7c,0xb7c,0xb7c,0xb7c, +0xb7c,0xb7c,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb76,0xb7c,0xb7c,0xb7c,0xb7c, 0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb73,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb76,0xb76,0xb76,0xb76, -0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76, -0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb76,0xb7c,0xb7c,0xb7c,0xb7c, +0xb7c,0xb76,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb76,0xb7c,0xb7c, 0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, -0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, -0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, +0xb7c,0xb7c,0xb7c,0xb7c,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, 0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79,0xb79, +0xb79,0xb79,0xb79,0xb79,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7c,0xb7c, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, 0xb7c,0xb7c,0xb7c,0xb7c,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f, -0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f, -0xb7f,0xb7f,0xb7f,0xb7f,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85, -0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85, -0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0xb85,0x1adc,0x1adc,0x1adc,0x1adc,0x1adc,0x1adc,0x1adc,0x1ba8,0x1ba8, -0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88, +0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7f,0xb7c,0xb7c, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c, +0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7c,0xb7f,0xb7f,0xb7f,0xb7f,0xb82,0xb82,0xb82,0xb82, +0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82, +0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb82,0xb88,0xb88,0xb88,0xb88, 0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88, -0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2, -0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbdf,0xbe2,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf, -0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xbdf,0xce1,0xce4,0xdd1,0xdd1,0xdd1,0xdd1,0xdd1,0xdd1,0xdd1, -0xdd1,0xdd1,0xdd1,0xdd1,0xee8,0xee8,0xee8,0xee8,0xbee,0xbee,0xbee,0xbee,0xbee,0xbee,0xbee,0xbee, -0xbee,0xbee,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xce7,0xdd4,0xe88,0xdd4,0xdd4,0xdd4,0xdd4, -0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xfd8,0x1272,0x1272,0xddd,0xddd,0xddd,0xddd,0xddd,0xde3,0xde0,0xefa, -0xefa,0xefa,0xefa,0x13e0,0xfea,0x13e0,0x132c,0x132c,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21, -0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc21,0xc4e,0xc4b,0xc4e,0xc4b,0xc4e,0xc4b, -0x10fe,0x10fb,0xff0,0xfed,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24, -0xc24,0xc24,0xc24,0xc24,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27, -0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27, -0xc27,0xc27,0xc27,0xc27,0xc2a,0xc2a,0xc2a,0xc30,0xc2d,0xc54,0xc51,0xc30,0xc2d,0xc30,0xc2d,0xc30, -0xc2d,0xc30,0xc2d,0xc30,0xc2d,0xc30,0xc2d,0xc30,0xc2d,0xc30,0xc2d,0xc30,0xc2d,0xc2a,0xc2a,0xc2a, -0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a, +0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0xb88,0x1aee, +0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1bba,0x1bba,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b, +0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b, +0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xb8b,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5, +0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe5,0xbe2,0xbe5, +0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xbe2,0xce4, +0xce7,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xeeb,0xeeb,0xeeb,0xeeb, +0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xbf1,0xcea,0xcea,0xcea,0xcea,0xcea,0xcea, +0xcea,0xcea,0xdd7,0xe8b,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xfdb,0x1278,0x1278, +0xde0,0xde0,0xde0,0xde0,0xde0,0xde6,0xde3,0xefd,0xefd,0xefd,0xefd,0x13e9,0xfed,0x13e9,0x1332,0x1332, +0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24,0xc24, +0xc24,0xc24,0xc51,0xc4e,0xc51,0xc4e,0xc51,0xc4e,0x1104,0x1101,0xff3,0xff0,0xc27,0xc27,0xc27,0xc27, +0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc27,0xc2a,0xc2a,0xc2a,0xc2a, 0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a, -0xc30,0xc2d,0xc30,0xc2d,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a, -0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a, -0xc30,0xc2d,0xc2a,0xc2a,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33, -0xc39,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33, -0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33, -0xc33,0xc33,0xc33,0xc33,0xc39,0xc39,0xc39,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33, -0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33,0xc33, -0xc33,0xc33,0xc33,0xc33,0xc36,0xc33,0xc33,0xc33,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c, -0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c, -0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xc6c,0xce7,0xd53,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4, -0xdd4,0xdd4,0xe88,0xe88,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xdd4,0xeeb,0xfd8,0xfd8,0xfd8,0xfd8,0xfd8, -0xfd8,0xfd8,0xfd8,0xfd8,0xfd8,0x1296,0x1296,0x1275,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b, -0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b, -0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd0b,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd11,0xd11, -0xd11,0xd11,0xd11,0xd0e,0xd23,0xd23,0xd23,0xd1d,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23, -0xd23,0xd23,0xd23,0xd1d,0xd23,0xd23,0xd23,0xd23,0xd17,0xd17,0xd20,0xd20,0xd20,0xd20,0xd14,0xd14, -0xd14,0xd14,0xd14,0xd1a,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9, -0xde6,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9,0xde9,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23, -0xd23,0xd23,0xd23,0xd23,0xd23,0xd23,0xd1d,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23,0xd23, -0xd23,0xd23,0xd23,0xd23,0xd23,0xd17,0xd17,0xd17,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a, -0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a, -0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd1a,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26, -0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xdec,0xdec,0xdec,0xdec,0xdec,0xdec,0xefd,0xefd,0xefd,0xefd, -0xefd,0xefd,0xefd,0x1107,0x1107,0xff3,0xff3,0xff3,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29, -0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29, -0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f, -0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f, -0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd2f,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38, -0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38, -0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd38,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44, -0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44, -0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd44,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50, -0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50, -0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xd50,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2, -0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2, -0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf2,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8, -0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf5,0xdf5,0xdf5, -0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8, -0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8, -0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xeb8,0xeb8,0xe0a,0xe0a,0xf00,0xf00,0xf00,0xf00, -0xf00,0xf00,0xf00,0xfff,0xfff,0x1002,0xfff,0xfff,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc, -0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xe19,0xe16,0xe19,0xe16,0xe19,0xe16,0xe19,0xe16, -0xe19,0xe16,0xe19,0xe16,0xe19,0xe16,0xe19,0xe16,0xe19,0xe16,0xe19,0xe16,0xe19,0xe16,0xe19,0xe16, -0xe19,0xe16,0xe19,0xe16,0xe19,0xe16,0xe19,0xe16,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25, -0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25, -0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe25,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b, -0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0x1b1e,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, +0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2a,0xc2d,0xc2d,0xc2d,0xc33, +0xc30,0xc57,0xc54,0xc33,0xc30,0xc33,0xc30,0xc33,0xc30,0xc33,0xc30,0xc33,0xc30,0xc33,0xc30,0xc33, +0xc30,0xc33,0xc30,0xc33,0xc30,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d, +0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d, +0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc33,0xc30,0xc33,0xc30,0xc2d,0xc2d,0xc2d,0xc2d, +0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d, +0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc2d,0xc33,0xc30,0xc2d,0xc2d,0xc36,0xc36,0xc36,0xc36, +0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc3c,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36, +0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36, +0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc3c,0xc3c,0xc3c,0xc36, +0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36, +0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc36,0xc39,0xc36,0xc36,0xc36, +0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f, +0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f,0xc6f, +0xcea,0xd56,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xdd7,0xe8b,0xe8b,0xdd7,0xdd7,0xdd7,0xdd7, +0xdd7,0xdd7,0xeee,0xfdb,0xfdb,0xfdb,0xfdb,0xfdb,0xfdb,0xfdb,0xfdb,0xfdb,0xfdb,0x129c,0x129c,0x127b, +0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e, +0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e,0xd0e, +0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd14,0xd14,0xd14,0xd14,0xd14,0xd11,0xd26,0xd26,0xd26,0xd20, +0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd20,0xd26,0xd26,0xd26,0xd26, +0xd1a,0xd1a,0xd23,0xd23,0xd23,0xd23,0xd17,0xd17,0xd17,0xd17,0xd17,0xd1d,0xdec,0xdec,0xdec,0xdec, +0xdec,0xdec,0xdec,0xdec,0xdec,0xdec,0xdec,0xdec,0xde9,0xdec,0xdec,0xdec,0xdec,0xdec,0xdec,0xdec, +0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd20,0xd26, +0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd26,0xd1a,0xd1a,0xd1a, +0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d, +0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d,0xd1d, +0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xd29,0xdef,0xdef, +0xdef,0xdef,0xdef,0xdef,0xf00,0xf00,0xf00,0xf00,0xf00,0xf00,0xf00,0x110d,0x110d,0xff6,0xff6,0xff6, +0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c, +0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c,0xd2c, +0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32, +0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32,0xd32, +0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b, +0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b,0xd3b, +0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47, +0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47,0xd47, +0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53, +0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53,0xd53, +0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5, +0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5,0xdf5, +0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb, +0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8,0xdf8, +0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb, +0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb,0xdfb, +0xebb,0xebb,0xe0d,0xe0d,0xf03,0xf03,0xf03,0xf03,0xf03,0xf03,0xf03,0x1002,0x1002,0x1005,0x1002,0x1002, +0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff, +0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19, +0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19,0xe1c,0xe19, +0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, 0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28, -0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0x1b1b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b, +0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0x1b30, 0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b, -0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2,0xeb2, -0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xe43,0xf03, -0xf03,0xf03,0xf03,0x1005,0x1005,0x1005,0x1005,0x1005,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c, -0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c, -0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe4c,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55, -0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55, -0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe55,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e, +0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0xe2b,0x1b2d, +0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e, +0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e,0xe2e, +0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xe46,0xe46,0xe46,0xe46,0xe46,0xe46,0xe46,0xe46, +0xe46,0xe46,0xe46,0xe46,0xe46,0xe46,0xe46,0xf06,0xf06,0xf06,0xf06,0x1008,0x1008,0x1008,0x1008,0x1008, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f,0xe4f, +0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58, +0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58,0xe58, +0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61, +0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe61,0xe5b, 0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e, -0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe58,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, -0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b,0xe5b, -0xe5b,0xe5b,0xe5b,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe67,0xe67,0xe67,0xe67,0xe67,0xe67,0xe67,0xe67, -0xe67,0xe67,0xe67,0xe67,0xe67,0xe67,0xe64,0xe64,0xe64,0xe64,0xe64,0xe64,0xe64,0xe64,0xe61,0xe6a, -0x1011,0x100b,0x101a,0x1008,0xe67,0xe67,0x1008,0x1008,0xe79,0xe79,0xe6d,0xe79,0xe79,0xe79,0xe70,0xe79, -0xe79,0xe79,0xe79,0xe6d,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79, -0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe79,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c, +0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe5e,0xe61,0xe61,0xe61,0xe61,0xe61, +0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe6a,0xe67,0xe67, +0xe67,0xe67,0xe67,0xe67,0xe67,0xe67,0xe64,0xe6d,0x1014,0x100e,0x101d,0x100b,0xe6a,0xe6a,0x100b,0x100b, +0xe7c,0xe7c,0xe70,0xe7c,0xe7c,0xe7c,0xe73,0xe7c,0xe7c,0xe7c,0xe7c,0xe70,0xe7c,0xe7c,0xe7c,0xe7c, 0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c, -0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe7c,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94, -0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94, -0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xe94,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5, -0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0xeb5,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110, -0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0x1110,0xee8,0xee8,0xee8,0xee5,0xee5,0xee5,0xee5,0xee5, -0x1149,0x1392,0x1392,0x1392,0x1392,0x1317,0x1317,0x1317,0x1395,0x131a,0x131a,0x1395,0x14d6,0x14d6,0x14d6,0x14d6, -0x14d6,0x14d6,0x14d6,0x1797,0x1797,0x1797,0x1797,0x185d,0xefd,0xefd,0xefd,0xefd,0xff3,0xff3,0xff3,0xff3, -0xff3,0xff3,0xff3,0xff3,0xff3,0xff3,0xff3,0xff3,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6, -0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0xffc,0x14f1, -0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f1,0x14f4,0x1866,0x1866, -0x18e7,0x1866,0x1bc6,0x179d,0x132f,0x1152,0xf00,0xf00,0xf1e,0xf1e,0xf1e,0xf1e,0xf30,0xf39,0xf3c,0xf39, -0xf3c,0xf39,0xf3c,0xf39,0xf3c,0xf39,0xf3c,0xf39,0xf39,0xf39,0xf3c,0xf39,0xf39,0xf39,0xf39,0xf39, -0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39,0xf39, -0xf21,0xf1e,0xf1e,0xf1e,0xf1e,0xf1e,0xf1e,0xf33,0xf1e,0xf33,0xf30,0xf30,0xf45,0xf42,0xf45,0xf45, -0xf45,0xf42,0xf42,0xf45,0xf42,0xf45,0xf42,0xf45,0xf42,0x102c,0x102c,0x102c,0x1167,0x1023,0x102c,0x1023, -0xf42,0xf45,0xf42,0xf42,0x1023,0x1023,0x1023,0x1023,0x1026,0x1029,0x1167,0x1167,0xf48,0xf48,0x103e,0x1035, -0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x1035,0x1035,0x103e,0x1035, -0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0xf4e,0xf4e,0xf4e,0xf4e, -0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e, -0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf4e,0xf5d,0xf5d,0xf5d,0xf5d, -0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d, -0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0xf5d,0x1512, -0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512,0x1512, -0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63, -0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63,0xf63, -0xfab,0xfc3,0xfba,0xfc0,0xfc0,0xfc3,0xfc3,0xfba,0xfba,0xfc0,0xfc0,0xfc0,0xfc0,0xfc0,0xfc3,0xfc3, -0xfc3,0xfab,0xfab,0xfab,0xfab,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3, -0xfc3,0xfc3,0xfab,0xfba,0xfbd,0xfab,0xfab,0xfc0,0xfc0,0xfc0,0xfc0,0xfc0,0xfc0,0xfae,0xfc3,0xfc0, -0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0xfb7,0x1131,0x1131,0x112e,0x112b,0xfb4,0xfb4, -0xfdb,0xfdb,0xfdb,0xfdb,0x1296,0x1296,0x1275,0x1275,0x1275,0x1272,0x1272,0x1272,0x1272,0x1275,0x1398,0x1275, -0x1275,0x1275,0x1272,0x1275,0x1296,0x1272,0x1272,0x1272,0x1275,0x1275,0x1272,0x1272,0x1275,0x1272,0x1272,0x1275, -0xff6,0xff6,0xff6,0xff6,0xff6,0xff3,0xff3,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0x14eb,0x14eb,0x14eb, -0x1107,0xff3,0xff3,0xff3,0xff3,0x12a2,0x127e,0x127e,0x127e,0x127e,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb, -0x1017,0x1017,0x1014,0x100e,0x1014,0x100e,0x1014,0x100e,0x1014,0x100e,0x100b,0x100b,0x100b,0x100b,0x1020,0x101d, -0x100b,0x1164,0x13ec,0x13ef,0x13ef,0x13ec,0x13ec,0x13ec,0x13ec,0x13ec,0x13f2,0x13f2,0x1506,0x14fa,0x14fa,0x14f7, -0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x1032,0x102f,0x102f,0x103e,0x1035,0x133b,0x1338,0x16ec, -0x133b,0x1338,0x13fb,0x13f8,0x1509,0x1509,0x150f,0x1509,0x150f,0x1509,0x150f,0x1509,0x150f,0x1509,0x150f,0x1509, -0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035, -0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x1035, -0x1038,0x1035,0x1035,0x1035,0x1035,0x1035,0x1035,0x1035,0x1035,0x103e,0x1035,0x103e,0x1035,0x103e,0x103e,0x1035, -0x1041,0x1041,0x1047,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d, -0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d,0x104d, -0x104d,0x1047,0x1041,0x1041,0x1041,0x1041,0x1047,0x1047,0x1041,0x1041,0x104a,0x1404,0x1401,0x1401,0x104d,0x104d, -0x1044,0x1044,0x1044,0x1044,0x1044,0x1044,0x1044,0x1044,0x1044,0x1044,0x1407,0x1407,0x1407,0x1407,0x1407,0x1407, -0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062, -0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062,0x1062, -0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b, -0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106b,0x106e,0x106e,0x106e,0x1071,0x106e,0x106e,0x1074,0x1074, -0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077, -0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077,0x1077, -0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1083,0x107a,0x1089,0x1086, -0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080, -0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080,0x1080, -0x1341,0x133e,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x1098,0x1119, -0x108c,0x108c,0x108c,0x1092,0x140a,0x140a,0x140a,0x140a,0x140a,0x140a,0x140a,0x140a,0x108f,0x108f,0x1092,0x109e, -0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095, -0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095,0x109b,0x1095, -0x151e,0x151b,0x151e,0x151b,0x1521,0x1521,0x16f5,0x140a,0x10a7,0x10a7,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa, -0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa, -0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10a7,0x10a7,0x10a7,0x10a7,0x10a7,0x10a7,0x10a7,0x10a7, -0x10a7,0x10a7,0x10a7,0x10a7,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b0,0x10b0,0x10b0,0x10b0,0x10b0,0x10b3, -0x10b3,0x10b3,0x110d,0x10bc,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb,0x10cb, -0x10cb,0x10cb,0x10cb,0x10cb,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b6,0x10b9,0x10b9, -0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9, -0x10b9,0x10b9,0x10b9,0x10b9,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da, -0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da,0x10da, -0x10da,0x10da,0x10da,0x10da,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec, -0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec,0x10ec, -0x10ec,0x10ec,0x10ec,0x10ec,0x10f5,0x10f5,0x10f5,0x10f5,0x110a,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5, -0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5,0x10f5, -0x10f5,0x10f5,0x10f5,0x10f5,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8, -0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8,0x10f8, -0x10f8,0x10f8,0x10f8,0x10f8,0x1104,0x1104,0x1104,0x1104,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c,0x129c, -0x1494,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x18c6,0x18c6,0x18c6,0x18c6,0x18c6,0x18c6, -0x18c6,0x18c6,0x18c6,0x18c6,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179, -0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1179,0x1170,0x1170,0x1173,0x1173,0x1179,0x1170, -0x1170,0x1170,0x1170,0x1170,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f, +0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f, +0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f,0xe7f, +0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97, +0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97,0xe97, +0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8,0xeb8, +0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113,0x1113, +0xeeb,0xeeb,0xeeb,0xee8,0xee8,0xee8,0xee8,0xee8,0x114f,0x139b,0x139b,0x139b,0x139b,0x131d,0x131d,0x131d, +0x139e,0x1320,0x1320,0x139e,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x14df,0x17a6,0x17a6,0x17a6,0x17a6,0x186c, +0xf00,0xf00,0xf00,0xf00,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6,0xff6, +0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9,0xff9, +0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fa, +0x14fa,0x14fa,0x14fa,0x14fa,0x14fa,0x14fd,0x1875,0x1875,0x18f6,0x1875,0x1bd8,0x17ac,0x1335,0x1158,0xf03,0xf03, +0xf21,0xf21,0xf21,0xf21,0xf33,0xf3c,0xf3f,0xf3c,0xf3f,0xf3c,0xf3f,0xf3c,0xf3f,0xf3c,0xf3f,0xf3c, +0xf3c,0xf3c,0xf3f,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c, +0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf3c,0xf24,0xf21,0xf21,0xf21,0xf21,0xf21,0xf21,0xf36, +0xf21,0xf36,0xf33,0xf33,0xf48,0xf45,0xf48,0xf48,0xf48,0xf45,0xf45,0xf48,0xf45,0xf48,0xf45,0xf48, +0xf45,0x102f,0x102f,0x102f,0x116d,0x1026,0x102f,0x1026,0xf45,0xf48,0xf45,0xf45,0x1026,0x1026,0x1026,0x1026, +0x1029,0x102c,0x116d,0x116d,0xf4b,0xf4b,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038, +0x1041,0x1038,0x1041,0x1038,0x1038,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038, +0x1041,0x1038,0x1041,0x1038,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51, +0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51,0xf51, +0xf51,0xf51,0xf51,0xf51,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60, +0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60, +0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0xf60,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b, +0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0x151b,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66, +0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66, +0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xf66,0xfae,0xfc6,0xfbd,0xfc3,0xfc3,0xfc6,0xfc6,0xfbd, +0xfbd,0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfc6,0xfc6,0xfc6,0xfae,0xfae,0xfae,0xfae,0xfc6,0xfc6,0xfc6, +0xfc6,0xfc6,0xfc6,0xfc6,0xfc6,0xfc6,0xfc6,0xfc6,0xfc6,0xfc6,0xfae,0xfbd,0xfc0,0xfae,0xfae,0xfc3, +0xfc3,0xfc3,0xfc3,0xfc3,0xfc3,0xfb1,0xfc6,0xfc3,0xfba,0xfba,0xfba,0xfba,0xfba,0xfba,0xfba,0xfba, +0xfba,0xfba,0x1137,0x1137,0x1134,0x1131,0xfb7,0xfb7,0xfde,0xfde,0xfde,0xfde,0x129c,0x129c,0x127b,0x127b, +0x127b,0x1278,0x1278,0x1278,0x1278,0x127b,0x13a1,0x127b,0x127b,0x127b,0x1278,0x127b,0x129c,0x1278,0x1278,0x1278, +0x127b,0x127b,0x1278,0x1278,0x127b,0x1278,0x1278,0x127b,0xff9,0xff9,0xff9,0xff9,0xff9,0xff6,0xff6,0xff9, +0xff9,0xff9,0xff9,0xff9,0xff9,0x14f4,0x14f4,0x14f4,0x110d,0xff6,0xff6,0xff6,0xff6,0x12a8,0x1284,0x1284, +0x1284,0x1284,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x101a,0x101a,0x1017,0x1011,0x1017,0x1011,0x1017,0x1011, +0x1017,0x1011,0x100e,0x100e,0x100e,0x100e,0x1023,0x1020,0x100e,0x116a,0x13f5,0x13f8,0x13f8,0x13f5,0x13f5,0x13f5, +0x13f5,0x13f5,0x13fb,0x13fb,0x150f,0x1503,0x1503,0x1500,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038, +0x1035,0x1032,0x1032,0x1041,0x1038,0x1341,0x133e,0x16fb,0x1341,0x133e,0x1404,0x1401,0x1512,0x1512,0x1518,0x1512, +0x1518,0x1512,0x1518,0x1512,0x1518,0x1512,0x1518,0x1512,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038, +0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038, +0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1038,0x103b,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038,0x1038, +0x1038,0x1041,0x1038,0x1041,0x1038,0x1041,0x1041,0x1038,0x1044,0x1044,0x104a,0x1050,0x1050,0x1050,0x1050,0x1050, +0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050, +0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x1050,0x104a,0x1044,0x1044,0x1044,0x1044,0x104a,0x104a, +0x1044,0x1044,0x104d,0x140d,0x140a,0x140a,0x1050,0x1050,0x1047,0x1047,0x1047,0x1047,0x1047,0x1047,0x1047,0x1047, +0x1047,0x1047,0x1410,0x1410,0x1410,0x1410,0x1410,0x1410,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065, +0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065, +0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x1065,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e, +0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e,0x106e, +0x1071,0x1071,0x1071,0x1074,0x1071,0x1071,0x1077,0x1077,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a, +0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a, +0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x107a,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083, +0x1083,0x1083,0x1083,0x1083,0x1086,0x107d,0x108c,0x1089,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083, +0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083, +0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1083,0x1347,0x1344,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098, +0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x109b,0x111f,0x108f,0x108f,0x108f,0x1095,0x1413,0x1413,0x1413,0x1413, +0x1413,0x1413,0x1413,0x1413,0x1092,0x1092,0x1095,0x10a1,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098, +0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098, +0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x109e,0x1098,0x1527,0x1524,0x1527,0x1524,0x152a,0x152a,0x1704,0x1413, +0x10aa,0x10aa,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad, +0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad,0x10ad, +0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10aa,0x10bc,0x10bc,0x10bc,0x10bc, +0x10bc,0x10bc,0x10b3,0x10b3,0x10b3,0x10b3,0x10b3,0x10b6,0x10b6,0x10b6,0x1116,0x10bf,0x10ce,0x10ce,0x10ce,0x10ce, +0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10ce,0x10b9,0x10b9,0x10b9,0x10b9, +0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10b9,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc, +0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10bc,0x10e0,0x10e0,0x10e0,0x10e0, +0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0, +0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10e0,0x10f2,0x10f2,0x10f2,0x10f2, +0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2, +0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10f2,0x10fb,0x10fb,0x10fb,0x10fb, +0x1110,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb, +0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fb,0x10fe,0x10fe,0x10fe,0x10fe, +0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe, +0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x10fe,0x110a,0x110a,0x110a,0x110a, +0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x12a2,0x149d,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785, +0x1785,0x1785,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x117f,0x117f,0x117f,0x117f, 0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f,0x117f, -0x117f,0x117f,0x117f,0x117f,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a, -0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a,0x119a, -0x119a,0x119a,0x119a,0x119a,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6, -0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6,0x11a6, -0x11a6,0x11a6,0x11a3,0x11a9,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5, -0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5,0x11b5, -0x11b5,0x11b5,0x11b5,0x11b5,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb, -0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x12e7,0x11c1,0x12ea,0x11c1,0x11c1,0x11c1,0x11c1,0x11be,0x11be,0x11be,0x11c1, -0x16f8,0x16fb,0x1923,0x1920,0x11c4,0x11c4,0x11c4,0x11d3,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9, -0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9, -0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11d9,0x11c7,0x11d3,0x11d3,0x11c4,0x11c4,0x11c4,0x11c4,0x11d3,0x11d3, -0x11c4,0x11c4,0x11d3,0x11d3,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5, -0x11e5,0x11e5,0x11e5,0x11e5,0x11e8,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11e5,0x11df,0x11df,0x11df,0x11e5,0x11e2, -0x1527,0x152a,0x152d,0x152d,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7, -0x11f7,0x11f7,0x11f7,0x11f7,0x11eb,0x11f7,0x11eb,0x11eb,0x11eb,0x1200,0x1200,0x11eb,0x11eb,0x1200,0x11f7,0x1200, -0x1200,0x11f7,0x11eb,0x11ee,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7, -0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7,0x11f7, -0x11f7,0x11f7,0x11f7,0x11f7,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212, -0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212,0x1212, -0x1212,0x1212,0x1212,0x1212,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a, -0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a,0x122a, -0x122a,0x1227,0x1227,0x1227,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233, -0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233,0x1233, -0x1233,0x1233,0x1233,0x1233,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242, -0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242,0x1242, -0x1242,0x1242,0x1242,0x1242,0x1248,0x1248,0x1254,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257, -0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x125a,0x1257, -0x125a,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x1257,0x125a, -0x1257,0x1257,0x1257,0x1257,0x1254,0x1254,0x1254,0x1248,0x1248,0x1248,0x1248,0x1254,0x1254,0x124e,0x124b,0x1251, -0x1251,0x1260,0x125d,0x125d,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263, -0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263, -0x1263,0x1263,0x1263,0x1263,0x1269,0x1269,0x1269,0x1266,0x1266,0x1266,0x1263,0x1263,0x1263,0x1263,0x1266,0x1263, -0x1263,0x1263,0x1269,0x1266,0x1269,0x1266,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263, -0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263, -0x1263,0x1269,0x1266,0x1266,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263,0x1263, -0x1263,0x1263,0x1263,0x1bcf,0x19f5,0x19f5,0x19f5,0x19f5,0x19f5,0x19f5,0x19f5,0x19f8,0x19f2,0x1be1,0x1be1,0x1be1, -0x1be4,0x1bde,0x1be4,0x1bde,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1287, -0x1287,0x1287,0x126c,0x1929,0x138f,0x1290,0x138f,0x138f,0x138f,0x138f,0x138f,0x138f,0x138f,0x138f,0x138f,0x138f, -0x138f,0x1290,0x138f,0x1290,0x1275,0x1275,0x131d,0x1272,0x131d,0x131d,0x131d,0x131d,0x1272,0x1272,0x1296,0x1272, -0x1272,0x1272,0x1272,0x1272,0x1272,0x1275,0x1296,0x1296,0x1275,0x1296,0x1272,0x1275,0x1275,0x1278,0x1296,0x1272, -0x1272,0x1296,0x1275,0x1275,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x1281,0x1281, -0x1281,0x1281,0x13a4,0x1386,0x128a,0x13a4,0x13a4,0x13a4,0x13a4,0x13a4,0x13a4,0x13a4,0x13a4,0x13a4,0x13a4,0x1827, -0x1827,0x1827,0x1827,0x1827,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1530, -0x1530,0x1a76,0x1a76,0x1a76,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284,0x1284, -0x1284,0x1284,0x1284,0x1284,0x138f,0x138f,0x1290,0x138f,0x138f,0x138f,0x1290,0x138f,0x138f,0x138f,0x128a,0x128a, -0x128a,0x128a,0x128a,0x1389,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x128d,0x138c,0x138c,0x138c,0x138c, -0x138c,0x138c,0x138c,0x128d,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x140d,0x140d, -0x19d4,0x1a76,0x1a76,0x1a76,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x128d,0x138c,0x128d, -0x128d,0x138c,0x138c,0x128d,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1, -0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1,0x12b1, -0x12b1,0x12b1,0x12b1,0x12b1,0x133b,0x1338,0x133b,0x1338,0x133b,0x1338,0x133b,0x1338,0x133b,0x1338,0x13fb,0x150f, -0x150f,0x150f,0x17a3,0x1917,0x150f,0x150f,0x16ef,0x16ef,0x16ef,0x16e9,0x16ef,0x16e9,0x191a,0x1917,0x19d1,0x19ce, -0x19d1,0x19ce,0x19d1,0x19ce,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f, -0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f,0x135f, -0x135f,0x135f,0x135f,0x135f,0x1374,0x1365,0x1374,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377, -0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377,0x1377, -0x1377,0x1377,0x1377,0x1377,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x137d,0x137d,0x137d,0x137d, -0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d, -0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x1383,0x1383,0x1383,0x1383, -0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383, -0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x1383,0x13ad,0x13aa,0x18cc,0x18cc, -0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc, -0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b3,0x13b3,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b3,0x13b6,0x13b6,0x13b6,0x13b3,0x13b6,0x13b3,0x13b6, -0x13b3,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b9,0x13b6,0x13b6,0x13b6,0x13b6,0x13b3,0x13b6,0x13b3,0x13b3,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b3,0x13b3,0x13b3,0x13b3, -0x13b3,0x13b3,0x13b3,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3, -0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x13b3,0x1539,0x1539,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c, -0x153c,0x153c,0x153c,0x153c,0x153c,0x1779,0x1779,0x1779,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x153c,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x153c,0x1779,0x1779, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b9,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x1539,0x1539,0x153c,0x153c, -0x13b6,0x13b6,0x13b9,0x13b9,0x13b9,0x16a4,0x13b6,0x13b9,0x13b6,0x13b6,0x13b9,0x153f,0x153f,0x153c,0x153c,0x1779, -0x1779,0x1779,0x1779,0x1779,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x153c,0x153c,0x153c,0x16a4,0x153c,0x153c,0x153c,0x1779,0x1779,0x1779,0x177c,0x177c,0x177c,0x177c,0x177c, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x153c, -0x13b6,0x153c,0x13b9,0x13b9,0x13b6,0x13b6,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9, -0x13b9,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b9, -0x13b9,0x13b9,0x13b9,0x13b9,0x13b9,0x13b6,0x13b6,0x13b6,0x13b9,0x13b6,0x13b6,0x13b6,0x13b6,0x13b9,0x13b9,0x13b9, -0x13b6,0x13b9,0x13b9,0x13b9,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b9,0x13b6,0x13b9,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x16a4,0x13b6,0x13b6,0x13b6,0x13b6,0x153c,0x153c,0x1779, -0x1410,0x1410,0x1410,0x1410,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539,0x153c,0x1779,0x1779,0x1779,0x1779,0x16fe, -0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6,0x13b6, -0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153f,0x153f,0x153c,0x153c, -0x153c,0x153c,0x1830,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c, -0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539,0x153c,0x13b6, -0x13b6,0x13b6,0x13b6,0x13b6,0x149a,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc, -0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x149a,0x13bc,0x13bc,0x13bc,0x149a,0x13bc,0x149a,0x13bc,0x149a,0x13bc,0x149a, -0x13bc,0x13bc,0x13bc,0x149a,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x149a,0x149a,0x13bc,0x13bc,0x13bc,0x13bc, -0x149a,0x13bc,0x149a,0x149a,0x13bc,0x13bc,0x13bc,0x13bc,0x149a,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc, -0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x16aa,0x16aa,0x177f,0x177f,0x13bf,0x13bf,0x13bf,0x13bc,0x13bc,0x13bc,0x13bf, -0x13bf,0x13bf,0x13bf,0x13bf,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629, -0x1629,0x1629,0x1629,0x1629,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2, -0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2, -0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c5,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2, -0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c5,0x13c5,0x13c5,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2, -0x13c2,0x13c2,0x13c2,0x13c2,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8, -0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8, -0x13c8,0x13c8,0x13c8,0x13c8,0x17ac,0x17ac,0x17a9,0x1701,0x1416,0x1416,0x1416,0x1416,0x1416,0x1416,0x1413,0x1413, -0x1413,0x1413,0x1413,0x1413,0x1416,0x1416,0x1416,0x1416,0x1416,0x1416,0x1416,0x1416,0x1416,0x1416,0x1416,0x1416, -0x1416,0x1416,0x1416,0x1545,0x1419,0x1548,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419,0x1419, -0x1419,0x1548,0x1548,0x1548,0x1548,0x1548,0x1548,0x1704,0x1704,0x1b4b,0x17b2,0x17b2,0x17b2,0x17b2,0x17b2,0x17b2, -0x17b2,0x17b2,0x1a79,0x1a79,0x1422,0x1422,0x1422,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434, -0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434,0x1434, -0x1434,0x1434,0x1434,0x1434,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f, -0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f,0x144f, -0x144f,0x144f,0x144f,0x144f,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455, -0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455,0x1455, -0x1455,0x1455,0x1455,0x19da,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458, +0x117f,0x117f,0x1176,0x1176,0x1179,0x1179,0x117f,0x1176,0x1176,0x1176,0x1176,0x1176,0x1185,0x1185,0x1185,0x1185, +0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185, +0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x1185,0x11a0,0x11a0,0x11a0,0x11a0, +0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0, +0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11a0,0x11ac,0x11ac,0x11ac,0x11ac, +0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac, +0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11ac,0x11a9,0x11af,0x11bb,0x11bb,0x11bb,0x11bb, +0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb, +0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11bb,0x11c1,0x11c1,0x11c1,0x11c1, +0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x11c1,0x12ed,0x11c7,0x12f0, +0x11c7,0x11c7,0x11c7,0x11c7,0x11c4,0x11c4,0x11c4,0x11c7,0x1707,0x170a,0x1932,0x192f,0x11ca,0x11ca,0x11ca,0x11d9, +0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df, +0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11df,0x11cd, +0x11d9,0x11d9,0x11ca,0x11ca,0x11ca,0x11ca,0x11d9,0x11d9,0x11ca,0x11ca,0x11d9,0x11d9,0x11eb,0x11eb,0x11eb,0x11eb, +0x11eb,0x11eb,0x11eb,0x11eb,0x11eb,0x11eb,0x11eb,0x11eb,0x11eb,0x11eb,0x11eb,0x11eb,0x11ee,0x11eb,0x11eb,0x11eb, +0x11eb,0x11eb,0x11eb,0x11e5,0x11e5,0x11e5,0x11eb,0x11e8,0x1530,0x1533,0x1536,0x1536,0x11fd,0x11fd,0x11fd,0x11fd, +0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11f1,0x11fd,0x11f1,0x11f1, +0x11f1,0x1206,0x1206,0x11f1,0x11f1,0x1206,0x11fd,0x1206,0x1206,0x11fd,0x11f1,0x11f4,0x11fd,0x11fd,0x11fd,0x11fd, +0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd, +0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x11fd,0x1218,0x1218,0x1218,0x1218, +0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218, +0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1218,0x1230,0x1230,0x1230,0x1230, +0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230, +0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x1230,0x122d,0x122d,0x122d,0x1239,0x1239,0x1239,0x1239, +0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239, +0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1239,0x1248,0x1248,0x1248,0x1248, +0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248, +0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x1248,0x124e,0x124e,0x125a,0x125d, +0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d, +0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x1260,0x125d,0x1260,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d, +0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x125d,0x1260,0x125d,0x125d,0x125d,0x125d,0x125a,0x125a,0x125a,0x124e, +0x124e,0x124e,0x124e,0x125a,0x125a,0x1254,0x1251,0x1257,0x1257,0x1266,0x1263,0x1263,0x1269,0x1269,0x1269,0x1269, +0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269, +0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x126f,0x126f,0x126f,0x126c, +0x126c,0x126c,0x1269,0x1269,0x1269,0x1269,0x126c,0x1269,0x1269,0x1269,0x126f,0x126c,0x126f,0x126c,0x1269,0x1269, +0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269, +0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x126f,0x126c,0x126c,0x1269,0x1269,0x1269,0x1269, +0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1269,0x1be1,0x1a07,0x1a07,0x1a07,0x1a07, +0x1a07,0x1a07,0x1a07,0x1a0a,0x1a04,0x1bf3,0x1bf3,0x1bf3,0x1bf6,0x1bf0,0x1bf6,0x1bf0,0x128a,0x128a,0x128a,0x128a, +0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128d,0x128d,0x128d,0x1272,0x1938,0x1398,0x1296,0x1398,0x1398, +0x1398,0x1398,0x1398,0x1398,0x1398,0x1398,0x1398,0x1398,0x1398,0x1296,0x1398,0x1296,0x127b,0x127b,0x1323,0x1278, +0x1323,0x1323,0x1323,0x1323,0x1278,0x1278,0x129c,0x1278,0x1278,0x1278,0x1278,0x1278,0x1278,0x127b,0x129c,0x129c, +0x127b,0x129c,0x1278,0x127b,0x127b,0x127e,0x129c,0x1278,0x1278,0x129c,0x127b,0x127b,0x1395,0x1395,0x1395,0x1395, +0x1395,0x1395,0x1395,0x1395,0x1395,0x1395,0x1287,0x1287,0x1287,0x1287,0x13ad,0x138f,0x1290,0x13ad,0x13ad,0x13ad, +0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x13ad,0x1836,0x1836,0x1836,0x1836,0x1836,0x128a,0x128a,0x128a,0x128a, +0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x1539,0x1539,0x1a88,0x1a88,0x1a88,0x128a,0x128a,0x128a,0x128a, +0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x128a,0x1398,0x1398,0x1296,0x1398, +0x1398,0x1398,0x1296,0x1398,0x1398,0x1398,0x1290,0x1290,0x1290,0x1290,0x1290,0x1392,0x1395,0x1395,0x1395,0x1395, +0x1395,0x1395,0x1395,0x1293,0x1395,0x1395,0x1395,0x1395,0x1395,0x1395,0x1395,0x1293,0x1395,0x1395,0x1395,0x1395, +0x1395,0x1395,0x1395,0x1395,0x1395,0x1395,0x1416,0x1416,0x19e6,0x1a88,0x1a88,0x1a88,0x1395,0x1395,0x1395,0x1395, +0x1395,0x1395,0x1395,0x1395,0x1395,0x1293,0x1395,0x1293,0x1293,0x1395,0x1395,0x1293,0x12b7,0x12b7,0x12b7,0x12b7, +0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7, +0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x12b7,0x1341,0x133e,0x1341,0x133e, +0x1341,0x133e,0x1341,0x133e,0x1341,0x133e,0x1404,0x1518,0x1518,0x1518,0x17b2,0x1926,0x1518,0x1518,0x16fe,0x16fe, +0x16fe,0x16f8,0x16fe,0x16f8,0x1929,0x1926,0x19e3,0x19e0,0x19e3,0x19e0,0x19e3,0x19e0,0x1365,0x1365,0x1365,0x1365, +0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365, +0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x1365,0x137a,0x136b,0x137a,0x1380, +0x1380,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d, +0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x137d,0x136b,0x136b,0x136b,0x136b, +0x136b,0x136b,0x136b,0x136b,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386, +0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386,0x1386, +0x1386,0x1386,0x1386,0x1386,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c,0x138c, +0x138c,0x138c,0x138c,0x138c,0x13b6,0x13b3,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db, +0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db, +0x18db,0x18db,0x18db,0x18db,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bc,0x13bc,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bc,0x13bf,0x13bf,0x13bf,0x13bc,0x13bf,0x13bc,0x13bf,0x13bc,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13c2,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bc,0x13bf,0x13bc,0x13bc,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc, +0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x13bc,0x1542,0x1542, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1788,0x1788,0x1788, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x1545,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x1545,0x1788,0x1788,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13c2,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1542,0x1542,0x1545,0x1545,0x13bf,0x13bf,0x13c2,0x13c2,0x13c2,0x16b3,0x13bf,0x13c2, +0x13bf,0x13bf,0x13c2,0x1548,0x1548,0x1545,0x1545,0x1788,0x1788,0x1788,0x1788,0x1788,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x1545,0x1545,0x1545,0x16b3,0x1545,0x1545,0x1545, +0x1788,0x1788,0x1788,0x178b,0x178b,0x178b,0x178b,0x178b,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x1545,0x13bf,0x1545,0x13c2,0x13c2,0x13bf,0x13bf,0x13c2,0x13c2, +0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2, +0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13c2,0x13bf,0x13bf,0x13bf, +0x13c2,0x13bf,0x13bf,0x13bf,0x13bf,0x13c2,0x13c2,0x13c2,0x13bf,0x13c2,0x13c2,0x13c2,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13c2,0x13bf,0x13c2,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x16b3,0x13bf,0x13bf,0x13bf,0x13bf,0x1545,0x1545,0x1788,0x1419,0x1419,0x1419,0x1419,0x1542,0x1542,0x1542,0x1542, +0x1542,0x1542,0x1545,0x1788,0x1788,0x1788,0x1788,0x170d,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf, +0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1548,0x1548,0x1545,0x1545,0x1545,0x1545,0x183f,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1545,0x13bf,0x13bf,0x13bf,0x13bf,0x13bf,0x14a3,0x13c5,0x13c5,0x13c5, +0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x14a3,0x13c5,0x13c5, +0x13c5,0x14a3,0x13c5,0x14a3,0x13c5,0x14a3,0x13c5,0x14a3,0x13c5,0x13c5,0x13c5,0x14a3,0x13c5,0x13c5,0x13c5,0x13c5, +0x13c5,0x13c5,0x14a3,0x14a3,0x13c5,0x13c5,0x13c5,0x13c5,0x14a3,0x13c5,0x14a3,0x14a3,0x13c5,0x13c5,0x13c5,0x13c5, +0x14a3,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x13c5,0x16b9,0x16b9,0x178e, +0x178e,0x13c8,0x13c8,0x13c8,0x13c5,0x13c5,0x13c5,0x13c8,0x13c8,0x13c8,0x13c8,0x13c8,0x1638,0x1638,0x1638,0x1638, +0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x13cb,0x13cb,0x13cb,0x13cb, +0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb, +0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13ce, +0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb, +0x13ce,0x13ce,0x13ce,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13cb,0x13d1,0x13d1,0x13d1,0x13d1, +0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1, +0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x13d1,0x17bb,0x17bb,0x17b8,0x1710, +0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141c,0x141c,0x141c,0x141c,0x141c,0x141c,0x141f,0x141f,0x141f,0x141f, +0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x141f,0x154e,0x1422,0x1551,0x1422,0x1422, +0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1422,0x1551,0x1551,0x1551,0x1551,0x1551,0x1551,0x1713, +0x1713,0x1b5d,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x17c1,0x1a8b,0x1a8b,0x142b,0x142b,0x142b,0x143d, +0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d, +0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x143d,0x1458,0x1458,0x1458,0x1458, 0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458, -0x1458,0x1458,0x1458,0x1458,0x145e,0x145e,0x146a,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470, -0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470, -0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x146a,0x146a,0x146a,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e, -0x145e,0x145e,0x145e,0x146a,0x146d,0x1470,0x1473,0x1473,0x1470,0x1476,0x1476,0x1461,0x1464,0x170a,0x170d,0x170d, -0x170d,0x154e,0x1a82,0x1a7f,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x154b,0x1713, -0x1716,0x1710,0x1719,0x1719,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491, -0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491,0x1491, -0x1491,0x1491,0x1491,0x1491,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb, -0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x18ff,0x18ff, -0x18ff,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x19c8,0x14eb,0x14eb, -0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x1863,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff, -0x18ff,0x18ff,0x18ff,0x18ff,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c, -0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539,0x1539, -0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c, -0x153f,0x153c,0x153c,0x153c,0x153c,0x16a7,0x16a7,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c, -0x182d,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c, -0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x153c,0x155d,0x155d,0x155d,0x155d, -0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d, -0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x155d,0x156f,0x156f,0x156f,0x156f, -0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f, -0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x156f,0x1575,0x1575,0x1575,0x1575, -0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575, -0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1575,0x1578,0x1578,0x1578,0x1578, +0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x1458,0x145e,0x145e,0x145e,0x145e, +0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e, +0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x145e,0x19ec,0x1461,0x1461,0x1461,0x1461, +0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461, +0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1461,0x1467,0x1467,0x1473,0x1479, +0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479, +0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1479,0x1473, +0x1473,0x1473,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1467,0x1473,0x1476,0x1479,0x147c,0x147c, +0x1479,0x147f,0x147f,0x146a,0x146d,0x1719,0x171c,0x171c,0x171c,0x1557,0x1a94,0x1a91,0x1470,0x1470,0x1470,0x1470, +0x1470,0x1470,0x1470,0x1470,0x1470,0x1470,0x1554,0x1722,0x1725,0x171f,0x1728,0x1728,0x149a,0x149a,0x149a,0x149a, +0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a, +0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x149a,0x14f4,0x14f4,0x14f4,0x14f4, +0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4, +0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x190e,0x190e,0x190e,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4, +0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x19da,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x14f4,0x1872,0x190e, +0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1542,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1548,0x1545,0x1545,0x1545,0x1545,0x16b6,0x16b6,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x183c,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545,0x1545, +0x1545,0x1545,0x1545,0x1545,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566, +0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566,0x1566, +0x1566,0x1566,0x1566,0x1566,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578, 0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578, -0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x1578,0x15a2,0x15a2,0x15a2,0x15a2, -0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x15a2,0x159c,0x159c,0x159c,0x1590,0x1590,0x1590,0x159c,0x159c, -0x1590,0x159f,0x1593,0x1590,0x15a5,0x15a5,0x1599,0x15a5,0x15a5,0x1596,0x17b5,0x1bdb,0x15b7,0x15b7,0x15b7,0x15b7, -0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7, -0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15b7,0x15a8,0x15c0,0x15c0,0x15c0,0x15c0, -0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0, -0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15c0,0x15ba,0x15c3,0x15c3,0x15c3,0x15c3,0x15c6,0x15c6,0x15c6,0x15c6, +0x1578,0x1578,0x1578,0x1578,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e, +0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e,0x157e, +0x157e,0x157e,0x157e,0x157e,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581, +0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581,0x1581, +0x1581,0x1581,0x1581,0x1581,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1,0x15b1, +0x15ab,0x15ab,0x15ab,0x159f,0x159f,0x159f,0x15ab,0x15ab,0x159f,0x15ae,0x15a2,0x159f,0x15b4,0x15b4,0x15a8,0x15b4, +0x15b4,0x15a5,0x17c4,0x1bed,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6, 0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6, -0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15c6,0x15e1,0x15e1,0x15e1,0x15e1, -0x15e1,0x15e1,0x15e1,0x15e1,0x15d8,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1, -0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15e1,0x15ea,0x15ea,0x15ea,0x15ea, -0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea, -0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15ea,0x15fc,0x15fc,0x15fc,0x15fc, -0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15f9,0x15f9,0x15f9,0x15ed, -0x15ed,0x15ed,0x15ed,0x15ed,0x15ed,0x15ed,0x15ed,0x15f9,0x15f9,0x15ed,0x15f9,0x15f0,0x15fc,0x15fc,0x15fc,0x15fc, -0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc, -0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x1620,0x1620,0x1620,0x1620, -0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620, -0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x1620,0x161d,0x161d,0x161d,0x1629,0x1629,0x1629,0x1629, -0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629,0x1629, -0x1629,0x1629,0x162f,0x162f,0x162f,0x162c,0x162c,0x162c,0x1629,0x1629,0x1629,0x1629,0x163e,0x163e,0x163e,0x163e, -0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x1632,0x1632,0x1632,0x1632, -0x1632,0x1632,0x1632,0x1644,0x1644,0x1638,0x1635,0x1635,0x1635,0x1635,0x1635,0x1635,0x163e,0x163e,0x163e,0x163e, -0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e, -0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x163e,0x164a,0x164a,0x164a,0x164a, -0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a,0x164a, -0x164a,0x164a,0x164a,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x1647,0x164d,0x164d,0x164d,0x164d, +0x15c6,0x15c6,0x15c6,0x15b7,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf, +0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15cf,0x15c9, +0x15d2,0x15d2,0x15d2,0x15d2,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5, +0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5,0x15d5, +0x15d5,0x15d5,0x15d5,0x15d5,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15e7,0x15f0,0x15f0,0x15f0, +0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0,0x15f0, +0x15f0,0x15f0,0x15f0,0x15f0,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9, +0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9,0x15f9, +0x15f9,0x15f9,0x15f9,0x15f9,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b, +0x160b,0x160b,0x160b,0x160b,0x1608,0x1608,0x1608,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x15fc,0x1608, +0x1608,0x15fc,0x1608,0x15ff,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b, +0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b,0x160b, +0x160b,0x160b,0x160b,0x160b,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f, +0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f,0x162f, +0x162f,0x162c,0x162c,0x162c,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638, +0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x1638,0x163e,0x163e,0x163e,0x163b,0x163b,0x163b, +0x1638,0x1638,0x1638,0x1638,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d, +0x164d,0x164d,0x164d,0x164d,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1641,0x1653,0x1653,0x1647,0x1644,0x1644, +0x1644,0x1644,0x1644,0x1644,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d, 0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d, -0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x164d,0x1671,0x1671,0x1671,0x1671, -0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671, -0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x1671,0x167a,0x167a,0x167a,0x167a, -0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a, -0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x167a,0x1692,0x1692,0x1692,0x1692, -0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x167d,0x168c,0x168c,0x167d, -0x167d,0x167d,0x167d,0x167d,0x167d,0x168c,0x167d,0x168f,0x168f,0x167d,0x168f,0x167d,0x1692,0x1692,0x1692,0x1692, -0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692, -0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x1692,0x169b,0x169b,0x169b,0x169b, -0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b, -0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x169b,0x16a1,0x16a1,0x16a1,0x16a1, +0x164d,0x164d,0x164d,0x164d,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659, +0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1659,0x1656,0x1656,0x1656,0x1656,0x1656, +0x1656,0x1656,0x1656,0x1656,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c, +0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c,0x165c, +0x165c,0x165c,0x165c,0x165c,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680, +0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680,0x1680, +0x1680,0x1680,0x1680,0x1680,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689, +0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689,0x1689, +0x1689,0x1689,0x1689,0x1689,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1, +0x16a1,0x16a1,0x16a1,0x16a1,0x168c,0x169b,0x169b,0x168c,0x168c,0x168c,0x168c,0x168c,0x168c,0x169b,0x168c,0x169e, +0x169e,0x168c,0x169e,0x168c,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1, 0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1, -0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x16a1,0x18ff,0x18ff,0x18ff,0x18ff, -0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x16e6,0x16e6,0x16e6,0x16e6,0x18ff,0x18ff,0x18ff,0x18ff, -0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x18ff,0x19c8,0x1707,0x1707,0x1707,0x1707, -0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707, -0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1707,0x1746,0x1746,0x1746,0x1746, -0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746, -0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x174c,0x1749, -0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746,0x1746, -0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f, -0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f,0x174f, -0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752, -0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752,0x1752, -0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764, -0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764,0x1764, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767,0x1767, -0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a, -0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a, -0x176a,0x176a,0x176a,0x176d,0x176d,0x176d,0x176d,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a,0x176a, -0x176a,0x176a,0x176a,0x176a,0x176a,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176a,0x176d,0x176d, -0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d, -0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d,0x176d, -0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785, -0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785,0x1785, -0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x186f,0x1ae5,0x1a3a,0x1a3a,0x1a3d, -0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x1788,0x178b,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x18d5, -0x1788,0x1788,0x1788,0x1788,0x1788,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836, -0x1836,0x1836,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3, -0x1788,0x19b3,0x19b3,0x1a3a,0x1a3a,0x1a3a,0x1a3a,0x1a3a,0x1a3a,0x1a3a,0x1a3a,0x1ae2,0x1bb4,0x1a3d,0x1a3d,0x1a3d, -0x18d2,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d2,0x18d2, -0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1a79,0x1b4b,0x1b4e,0x1b48,0x1b48,0x1b48,0x1b48,0x1b48,0x1b48, -0x1b48,0x1b48,0x1b48,0x192c,0x17af,0x17af,0x17af,0x17af,0x17af,0x17af,0x17af,0x17af,0x17af,0x17af,0x17af,0x17af, -0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1839,0x1836,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2, -0x1839,0x18d5,0x18d5,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1839,0x1836,0x17b8,0x1839,0x1839,0x1839,0x1a3a, -0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x17b8,0x1836,0x1836,0x1836,0x1836,0x1836,0x18d2,0x19b3,0x19b3,0x19b3, -0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x1836,0x18d2, -0x17cd,0x17cd,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca, -0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca,0x17ca, -0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd, -0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd,0x17cd, -0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b, -0x181b,0x181b,0x181b,0x181b,0x181b,0x1818,0x1818,0x1818,0x1803,0x1803,0x1803,0x1803,0x1803,0x1803,0x1803,0x1803, -0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b, -0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b,0x181b, -0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, -0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f,0x183f, -0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842, -0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842,0x1842, -0x1842,0x1842,0x1842,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee,0x1aee, -0x1899,0x1899,0x1899,0x1899,0x19ec,0x19ec,0x189c,0x189c,0x189c,0x189c,0x1884,0x1884,0x1884,0x1884,0x1884,0x1884, -0x1884,0x1884,0x1884,0x1884,0x1884,0x1884,0x1884,0x1896,0x1887,0x188a,0x188d,0x189f,0x189f,0x193e,0x1890,0x1890, -0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899, -0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899,0x1899, -0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba, -0x18ba,0x18ba,0x18ba,0x18a5,0x18ab,0x18a8,0x18a8,0x18a8,0x18a8,0x18b7,0x18bd,0x18a8,0x18a8,0x18a8,0x18a8,0x18b4, -0x18ba,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba, -0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba,0x18ba, -0x18c6,0x18c6,0x18c6,0x18c6,0x18c6,0x18c6,0x18c6,0x18c6,0x18c6,0x18c6,0x18c6,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad, -0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ad9,0x1ba5,0x1ba5,0x1ba5, -0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc, -0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc,0x18cc, -0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x19b3,0x19b3,0x19b3,0x19b3, -0x19b3,0x1a3a,0x1ae2,0x19b3,0x19b3,0x19b3,0x19b3,0x1ae5,0x1ae2,0x1bb4,0x19b3,0x1a3a,0x19b3,0x19b3,0x19b3,0x19b3, -0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x18d2,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3, -0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b3, +0x16a1,0x16a1,0x16a1,0x16a1,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa, +0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa,0x16aa, +0x16aa,0x16aa,0x16aa,0x16aa,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0, +0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0,0x16b0, +0x16b0,0x16b0,0x16b0,0x16b0,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e, +0x16f5,0x16f5,0x16f5,0x16f5,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e,0x190e, +0x190e,0x190e,0x190e,0x19da,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716, +0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716,0x1716, +0x1716,0x1716,0x1716,0x1716,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755, +0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755, +0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x175b,0x1758,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755, +0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x1755,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e, +0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e, +0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x175e,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761, +0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761, +0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1761,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773, +0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773, +0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1773,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776, +0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776, +0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1776,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779, +0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779, +0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x177c,0x177c,0x177c,0x177c,0x1779, +0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x1779,0x177c,0x177c,0x177c, +0x177c,0x177c,0x177c,0x177c,0x177c,0x1779,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c, +0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c, +0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x177c,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794, +0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794, +0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x1794,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e,0x187e, +0x187e,0x187e,0x187e,0x187e,0x1af7,0x1a4c,0x1a4c,0x1a4f,0x1797,0x1797,0x1797,0x1797,0x1797,0x1797,0x1797,0x1797, +0x179a,0x1848,0x1848,0x1848,0x1848,0x1848,0x1848,0x18e4,0x1797,0x1797,0x1797,0x1797,0x1797,0x1845,0x1845,0x1845, +0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1, +0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x1797,0x19c5,0x19c5,0x1a4c,0x1a4c,0x1a4c,0x1a4c,0x1a4c, +0x1a4c,0x1a4c,0x1a4c,0x1af4,0x1bc6,0x1a4f,0x1a4f,0x1a4f,0x18e1,0x18e4,0x18e4,0x18e4,0x18e4,0x18e4,0x18e4,0x18e4, +0x18e4,0x18e4,0x18e4,0x18e4,0x18e4,0x18e4,0x18e1,0x18e1,0x1a8b,0x1a8b,0x1a8b,0x1a8b,0x1a8b,0x1a8b,0x1a8b,0x1a8b, +0x1b5d,0x1b60,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x1b5a,0x193b,0x17be,0x17be,0x17be,0x17be, +0x17be,0x17be,0x17be,0x17be,0x17be,0x17be,0x17be,0x17be,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1848,0x1845, +0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x1848,0x18e4,0x18e4,0x1848,0x1848,0x1848,0x1848,0x1848, +0x1848,0x1848,0x1845,0x17c7,0x1848,0x1848,0x1848,0x1a4c,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x17c7,0x1845, +0x1845,0x1845,0x1845,0x1845,0x18e1,0x19c5,0x19c5,0x19c5,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845, +0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x1845,0x18e1,0x17dc,0x17dc,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9, +0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9, +0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17d9,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc, +0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc, +0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x17dc,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a, +0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x1827,0x1827,0x1827, +0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x1812,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a, +0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a, +0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x182a,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e, +0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e, +0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x184e,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851, +0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851, +0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1851,0x1b00,0x1b00,0x1b00,0x1b00,0x1b00, +0x1b00,0x1b00,0x1b00,0x1b00,0x1b00,0x1b00,0x1b00,0x1b00,0x18a8,0x18a8,0x18a8,0x18a8,0x19fe,0x19fe,0x18ab,0x18ab, +0x18ab,0x18ab,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x1893,0x18a5, +0x1896,0x1899,0x189c,0x18ae,0x18ae,0x194d,0x189f,0x189f,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8, +0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8, +0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18a8,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9, +0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18b4,0x18ba,0x18b7,0x18b7,0x18b7, +0x18b7,0x18c6,0x18cc,0x18b7,0x18b7,0x18b7,0x18b7,0x18c3,0x18c9,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7,0x18b7, +0x18b7,0x18b7,0x18b7,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9, +0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18c9,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5,0x18d5, +0x18d5,0x18d5,0x18d5,0x19bf,0x19bf,0x19bf,0x19bf,0x19bf,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb, +0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1aeb,0x1bb7,0x1bb7,0x1bb7,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db, 0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db, -0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db, -0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de, -0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x18de,0x1bb7, -0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1, -0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1, -0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953, -0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953,0x1953, -0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e, -0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e,0x196e, -0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974, -0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974,0x1974, -0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f, -0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f,0x198f, -0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992, -0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992,0x1992, -0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b, -0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x199b,0x1998,0x1998,0x1998, -0x19b3,0x19b3,0x19b3,0x1ae2,0x1ae2,0x1a3a,0x1a3a,0x1a3a,0x1a3a,0x1a3a,0x1a3a,0x1ae2,0x1ae2,0x1ae2,0x1a3a,0x1a3a, -0x19b3,0x19b3,0x19b3,0x19b3,0x19b3,0x19b6,0x19b6,0x19b3,0x19b6,0x19b6,0x1a3a,0x1a3d,0x1a3a,0x1a3a,0x1a3a,0x1a3a, -0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef, -0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef,0x19ef, -0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16, -0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16,0x1a16, -0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f, -0x1a55,0x1a55,0x1a1f,0x1a55,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a1f,0x1a25,0x1a25,0x1a25, -0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31, -0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31, -0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4, -0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4,0x1ac4, -0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0, -0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0,0x1ad0, -0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4, -0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4,0x1af4, -0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7, -0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7,0x1af7, -0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c, -0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c,0x1b6c, -0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d, -0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d,0x1b8d, +0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18db,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1, +0x18e1,0x18e1,0x18e1,0x18e1,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x1a4c,0x1af4,0x19c5,0x19c5,0x19c5,0x19c5,0x1af7, +0x1af4,0x1bc6,0x19c5,0x1a4c,0x19c5,0x19c5,0x19c5,0x19c5,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x18e1,0x19c5, +0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5, +0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea, +0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea, +0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ea,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed, +0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed, +0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x18ed,0x1bc9,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0, +0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0, +0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x18f0,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962, +0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962, +0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x1962,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d, +0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d, +0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x197d,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983, +0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983, +0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x1983,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1, +0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1, +0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a1,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4, +0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4, +0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19a4,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad, +0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19ad, +0x19ad,0x19ad,0x19ad,0x19ad,0x19ad,0x19aa,0x19aa,0x19aa,0x19c5,0x19c5,0x19c5,0x1af4,0x1af4,0x1a4c,0x1a4c,0x1a4c, +0x1a4c,0x1a4c,0x1a4c,0x1af4,0x1af4,0x1af4,0x1a4c,0x1a4c,0x19c5,0x19c5,0x19c5,0x19c5,0x19c5,0x19c8,0x19c8,0x19c5, +0x19c8,0x19c8,0x1a4c,0x1a4f,0x1a4c,0x1a4c,0x1a4c,0x1a4c,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01, +0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01, +0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a01,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28, +0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28, +0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31, +0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a67,0x1a67,0x1a31,0x1a67,0x1a31,0x1a31,0x1a31,0x1a31, +0x1a31,0x1a31,0x1a31,0x1a31,0x1a31,0x1a37,0x1a37,0x1a37,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43, +0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43, +0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1a43,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6, +0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6, +0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ad6,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2, +0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2, +0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1ae2,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06, +0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06, +0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b06,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09, +0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09, +0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b09,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e, +0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e, +0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b7e,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f, 0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f, -0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f, -0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2, -0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2,0x1ba2, -0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc,0x1bfc, -0x1bfc,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9,0x1bf9, -0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b, -0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b,0x1c3b, -0,0,0,0 +0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1b9f,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1, +0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1, +0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb1,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4, +0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4, +0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1bb4,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e, +0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0e,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b, +0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c0b,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d, +0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d, +0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c4d,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59, +0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59, +0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0x1c59,0,0,0,0 }; static const UTrie2 propsVectorsTrie={ propsVectorsTrie_index, - propsVectorsTrie_index+5348, + propsVectorsTrie_index+5368, nullptr, - 5348, - 27344, + 5368, + 27396, 0xa40, - 0x1564, + 0x1578, 0x0, 0x0, 0x110000, - 0x7fb0, + 0x7ff8, nullptr, 0, false, false, 0, nullptr }; -static const uint32_t propsVectors[7230]={ +static const uint32_t propsVectors[7260]={ 0x67,0,0,0x67,0,0xe00000,0x67,0x80000,0x20,0x867,0,0,0xa67,0,0,0xb67, 0,0,0xd67,0,0,0xe67,0,0,0x1067,0,0,0x1167,0,0,0x1267,0, 0,0x1367,0,0,0x1467,0,0,0x1567,0,0,0x1667,0,0,0x1767,0,0, 0x1867,0,0,0x1967,0,0,0x1a67,0,0,0x1b67,0,0,0x1d67,0,0,0x1f67, 0,0,0x2067,0,0,0x2267,0,0,0x2367,0,0,0x2467,0,0,0x2567,0, 0,0x2767,0,0,0x2867,0x80000,0x20,0x2967,0,0,0x2a67,0,0x1600000,0x2b67,0,0, -0x2d67,0,0,0x3167,0x20000000,0,0x3267,0x20000000,0,0x3a67,0,0,0x3b67,0,0,0x3c67, -0,0,0x3e67,0,0,0x4067,0,0,0x4167,0,0,0x4467,0,0,0x4867,0, -0,0x4967,0,0,0x4a67,0,0,0x5067,0,0,0x5167,0,0,0x5467,0,0, -0x5567,0,0,0x5667,0x80000,0x20,0x5767,0,0,0x5867,0,0,0x5967,0,0,0x5b67, -0,0,0x5c67,0,0,0x5d67,0,0,0x6067,0x80000,0x20,0x6267,0,0,0x6367,0, -0,0x6467,0,0,0x6567,0,0,0x6f67,0,0,0x7067,0,0,0x7367,0x20000000,0, -0x7567,0,0,0x7667,0,0,0x7767,0,0,0x7867,0,0,0x7a67,0,0,0x7b67, -0,0,0x7c67,0,0,0x7e67,0,0,0x7f67,0,0,0x8167,0,0,0x8267,0, -0,0x8467,0,0,0x8567,0,0,0x8667,0,0,0x8767,0,0,0x8967,0,0, -0x8b67,0,0,0x8c67,0,0,0x8e67,0x20000000,0,0x8f67,0,0,0x9067,0,0,0x9167, -0,0,0x9267,0,0,0x9367,0,0,0x9567,0,0,0x9667,0,0,0x9767,0, -0,0x9867,0,0,0x9967,0,0,0x9a67,0,0,0x9c67,0,0,0x9f67,0,0, -0xa167,0,0,0xa367,0,0,0xa467,0,0,0xa567,0,0,0xa667,0,0,0xa767, -0,0,0xa867,0,0,0xa967,0,0,0xaa67,0,0xe00000,0xab67,0,0xe00000,0xac67,0, -0,0xad67,0,0,0xae67,0,0,0xaf67,0,0,0xb167,0,0,0xb267,0,0, -0xb467,0,0,0xb567,0,0,0xb767,0,0,0xb867,0,0,0xb967,0,0,0xba67, -0,0,0xbc67,0,0,0xbd67,0,0,0xbe67,0,0,0xbf67,0,0,0xc067,0, -0,0xc167,0,0,0xc367,0,0xe00000,0xc467,0,0xe00000,0xc667,0,0,0xc767,0,0, -0xc867,0,0,0xc967,0,0,0xca67,0,0,0xcc67,0,0xe00000,0xcf67,0,0xe00000,0xd067, -0,0xe00000,0xd367,0,0,0xd467,0,0,0xd567,0,0,0xd667,0,0,0xd867,0, -0,0xda67,0,0,0xdb67,0,0,0xdc67,0,0,0xdd67,0,0,0xde67,0,0, -0xdf67,0,0,0xe067,0,0,0xe167,0,0,0xe267,0,0,0xe367,0,0xe00000,0xe467, -0,0,0xe567,0,0,0xe667,0,0,0xe767,0,0,0xe867,0,0,0xe967,0, -0,0xea67,0,0,0xeb67,0,0,0xec67,0,0,0xed67,0,0,0xee67,0,0, -0xef67,0,0,0xf167,0,0,0xf367,0,0,0xf567,0,0,0xf667,0,0,0xf767, -0,0,0xf867,0,0,0xf967,0,0,0xfa67,0,0xe00000,0xfb67,0,0,0xfc67,0, -0,0xfd67,0,0,0xfe67,0,0,0x10167,0,0,0x10267,0,0,0x10367,0,0, -0x10467,0,0,0x10667,0,0,0x10767,0,0,0x10867,0,0,0x10967,0,0,0x10a67, -0,0,0x10b67,0,0,0x10c67,0,0,0x10d67,0,0,0x10e67,0,0,0x10f67,0, -0,0x11067,0,0,0x11367,0,0,0x11467,0,0,0x11567,0,0,0x11667,0,0, -0x11767,0,0,0x11867,0,0,0x11967,0,0xe00000,0x11a67,0,0,0x11b67,0,0,0x11c67, -0,0,0x11d67,0,0,0x11e67,0,0,0x11f67,0,0,0x12067,0,0,0x12167,0, -0,0x12267,0,0,0x12367,0,0,0x12467,0,0,0x12567,0,0,0x12667,0,0, -0x12767,0,0,0x12867,0,0,0x12967,0,0,0x12a67,0,0xe00000,0x12b67,0,0,0x12c67, -0,0,0x12d67,0,0,0x12f67,0,0,0x13067,0,0,0x13167,0,0,0x13267,0, -0,0x13367,0,0,0x13467,0,0,0x13567,0,0,0x13667,0,0,0x13767,0,0, -0x13867,0,0,0x13967,0,0,0x13a67,0,0,0x13b67,0,0,0x13c67,0,0,0x13d67, -0,0,0x13f67,0,0,0x14067,0,0,0x14167,0,0,0x14367,0,0,0x14467,0, -0,0x14567,0,0,0x14667,0,0,0x14767,0,0,0xa0067,0,0xe00000,0xa4f67,0,0xe00000, -0xa5f67,0,0xe00000,0xac567,0,0xe00000,0xad167,0,0xe00000,0xb0067,0,0xe00000,0xb1267,0,0xe00000,0xb2e67, +0x2d67,0,0,0x3167,0x20000000,0,0x3267,0x20000000,0,0x3a67,0,0,0x3b67,0,0,0x3e67, +0,0,0x4067,0,0,0x4167,0,0,0x4467,0,0,0x4867,0,0,0x4967,0, +0,0x4a67,0,0,0x5067,0,0,0x5167,0,0,0x5467,0,0,0x5567,0,0, +0x5667,0x80000,0x20,0x5767,0,0,0x5867,0,0,0x5967,0,0,0x5b67,0,0,0x5c67, +0,0,0x5d67,0,0,0x6067,0x80000,0x20,0x6267,0,0,0x6367,0,0,0x6467,0, +0,0x6567,0,0,0x6f67,0,0,0x7067,0,0,0x7367,0x20000000,0,0x7567,0,0, +0x7667,0,0,0x7767,0,0,0x7867,0,0,0x7a67,0,0,0x7b67,0,0,0x7c67, +0,0,0x7e67,0,0,0x7f67,0,0,0x8167,0,0,0x8267,0,0,0x8467,0, +0,0x8567,0,0,0x8667,0,0,0x8767,0,0,0x8967,0,0,0x8b67,0,0, +0x8c67,0,0,0x8e67,0x20000000,0,0x8f67,0,0,0x9067,0,0,0x9167,0,0,0x9267, +0,0,0x9367,0,0,0x9567,0,0,0x9667,0,0,0x9767,0,0,0x9867,0, +0,0x9967,0,0,0x9a67,0,0,0x9c67,0,0,0x9f67,0,0,0xa167,0,0, +0xa367,0,0,0xa467,0,0,0xa567,0,0,0xa667,0,0,0xa767,0,0,0xa867, +0,0,0xa967,0,0,0xaa67,0,0xe00000,0xab67,0,0xe00000,0xac67,0,0,0xad67,0, +0,0xae67,0,0,0xaf67,0,0,0xb167,0,0,0xb267,0,0,0xb467,0,0, +0xb567,0,0,0xb767,0,0,0xb867,0,0,0xb967,0,0,0xba67,0,0,0xbc67, +0,0,0xbd67,0,0,0xbe67,0,0,0xbf67,0,0,0xc067,0,0,0xc167,0, +0,0xc367,0,0xe00000,0xc467,0,0xe00000,0xc667,0,0,0xc767,0,0,0xc867,0,0, +0xc967,0,0,0xca67,0,0,0xcc67,0,0xe00000,0xcf67,0,0xe00000,0xd067,0,0xe00000,0xd367, +0,0,0xd467,0,0,0xd567,0,0,0xd667,0,0,0xd867,0,0,0xda67,0, +0,0xdb67,0,0,0xdc67,0,0,0xdd67,0,0,0xde67,0,0,0xdf67,0,0, +0xe067,0,0,0xe167,0,0,0xe267,0,0,0xe367,0,0xe00000,0xe467,0,0,0xe567, +0,0,0xe667,0,0,0xe767,0,0,0xe867,0,0,0xe967,0,0,0xea67,0, +0,0xeb67,0,0,0xec67,0,0,0xed67,0,0,0xee67,0,0,0xef67,0,0, +0xf167,0,0,0xf367,0,0,0xf567,0,0,0xf667,0,0,0xf767,0,0,0xf867, +0,0,0xf967,0,0,0xfa67,0,0xe00000,0xfb67,0,0,0xfc67,0,0,0xfd67,0, +0,0xfe67,0,0,0x10167,0,0,0x10267,0,0,0x10367,0,0,0x10467,0,0, +0x10667,0,0,0x10767,0,0,0x10867,0,0,0x10967,0,0,0x10a67,0,0,0x10b67, +0,0,0x10c67,0,0,0x10d67,0,0,0x10e67,0,0,0x10f67,0,0,0x11067,0, +0,0x11367,0,0,0x11467,0,0,0x11567,0,0,0x11667,0,0,0x11767,0,0, +0x11867,0,0,0x11967,0,0xe00000,0x11a67,0,0,0x11b67,0,0,0x11c67,0,0,0x11d67, +0,0,0x11e67,0,0,0x11f67,0,0,0x12067,0,0,0x12167,0,0,0x12267,0, +0,0x12367,0,0,0x12467,0,0,0x12567,0,0,0x12667,0,0,0x12767,0,0, +0x12867,0,0,0x12967,0,0,0x12a67,0,0xe00000,0x12b67,0,0,0x12c67,0,0,0x12d67, +0,0,0x12f67,0,0,0x13067,0,0,0x13167,0,0,0x13267,0,0,0x13367,0, +0,0x13467,0,0,0x13567,0,0,0x13667,0,0,0x13767,0,0,0x13867,0,0, +0x13967,0,0,0x13a67,0,0,0x13b67,0,0,0x13c67,0,0,0x13d67,0,0,0x13f67, +0,0,0x14067,0,0,0x14167,0,0,0x14367,0,0,0x14467,0,0,0x14567,0, +0,0x14667,0,0,0x14767,0,0,0xa0067,0,0xe00000,0xa4f67,0,0xe00000,0xa5f67,0,0xe00000, +0xac567,0,0xe00000,0xad167,0,0xe00000,0xb0067,0,0xe00000,0xb1267,0,0xe00000,0xb2e67,0,0xe00000,0xb4867, 0,0xe00000,0x11000100,0,0x900020,0x11000100,0x40000001,0x440020,0x11000100,0x40000001,0x643020,0x11000100,0x40000001,0xa5a040,0x11000100,0x40000001, 0x116a8a0,0x11000200,0,0x900020,0x11000200,0x4000001,0xc4000b,0x11000200,0x7c00100,0x220402,0x11000200,0x24000000,0x200000,0x11000200,0x24000008,0x1710000, 0x11000200,0x40000001,0x1d3b020,0x11000219,0x7c00100,0x220401,0x11000219,0x7c00100,0x250401,0x11000319,0x7c00100,0x220401,0x11000319,0x7c00100,0x220402,0x11000319, @@ -3590,7 +3603,7 @@ static const uint32_t propsVectors[7230]={ 0x250400,0x11000908,0x7c00100,0x250401,0x11000a03,0x4000000,0x200400,0x11000a03,0x4000000,0x201000,0x11000a03,0x4000000,0x270000,0x11000a03,0x7c00100,0x220400, 0x11000a03,0x7c00100,0x220402,0x11000a03,0x7c00100,0x250400,0x11000a03,0x7c00500,0x230400,0x11000a03,0xc000010,0x1049400,0x11000b13,0x2802500,0x962460,0x11000b13, 0x4000000,0x200000,0x11000b13,0x4000000,0x201000,0x11000b13,0x4000000,0x230400,0x11000b13,0x4000002,0x400000,0x11000b13,0x4000010,0x200000,0x11000b13,0x7c00100, -0x2633800,0x11000c00,0x80000000,0x218960,0x11000c02,0x2802100,0x962460,0x11000c02,0x2802400,0x962460,0x11000c02,0x4000000,0x200000,0x11000c02,0x4000000,0x1329400, +0x2633800,0x11000c00,0x80000000,0x1329960,0x11000c02,0x2802100,0x962460,0x11000c02,0x2802400,0x962460,0x11000c02,0x4000000,0x200000,0x11000c02,0x4000000,0x1329400, 0x11000c02,0x4000000,0x1329800,0x11000c02,0x4000000,0x1500000,0x11000c02,0x6800000,0x1329800,0x11000c02,0x7c00100,0x230400,0x11000c02,0x7c00100,0x230401,0x11000c02, 0x7c00100,0x230402,0x11000c02,0x7c00500,0x230400,0x11000c02,0x7d00100,0x230400,0x11000f01,0x2802400,0x962460,0x11000f0a,0x2802100,0x962460,0x11000f0a,0x2802400, 0x962460,0x11000f0a,0x2806400,0x962460,0x11000f0a,0x4000000,0x200000,0x11000f0a,0x6800100,0x962540,0x11000f0a,0x7c00100,0x230400,0x11000f0a,0x7c00100,0x230401, @@ -3614,7 +3627,7 @@ static const uint32_t propsVectors[7230]={ 0x201c00,0x11002800,0x6800020,0x201c00,0x11002800,0x24000000,0x200000,0x11002800,0x24000000,0x200002,0x11002800,0x24000000,0x810000,0x11002800,0x24000000,0x1410000, 0x11002800,0x24000000,0x1500000,0x11002800,0x24000000,0x1500002,0x11002800,0x24000002,0x400000,0x11002800,0x24000006,0xc0000b,0x11002800,0x24000008,0x1410000,0x11002800, 0x24000008,0x1710000,0x11002800,0x24000020,0x1001400,0x11002800,0x24000020,0x1500002,0x11002800,0x2c000010,0x1248000,0x11002800,0x2c000010,0x1248002,0x11002800,0x40000001, -0x63b020,0x11002800,0x40080000,0x918820,0x11002801,0x80000,0x2a65620,0x11002801,0x82000,0x962460,0x11002900,0x4000000,0x20000e,0x11002900,0x4000000,0x20000f, +0x63b020,0x11002800,0x40080000,0x918820,0x11002801,0x2880000,0x2a65620,0x11002801,0x2882000,0x962460,0x11002900,0x4000000,0x20000e,0x11002900,0x4000000,0x20000f, 0x11002900,0x4000020,0x20000e,0x11002900,0x4000020,0x20000f,0x11002900,0x4000020,0x81000e,0x11002900,0x4000020,0x81000f,0x11002900,0x4000020,0x141000e,0x11002900, 0x4000020,0x141000f,0x11002900,0x4000022,0x20000e,0x11002900,0x4000022,0x20000f,0x11002a00,0x4000000,0x1500000,0x11002a00,0x4000000,0x1600000,0x11002a00,0x4000000, 0x1600002,0x11002b01,0x2000,0x962460,0x11002b01,0x2802020,0x962460,0x11002c00,0x4000000,0x200000,0x11002c00,0x4000000,0x200002,0x11002c00,0x4000000,0x20000f, @@ -3670,17 +3683,17 @@ static const uint32_t propsVectors[7230]={ 0x4000000,0x141000c,0x110a5400,0x4000000,0x150000c,0x110a5400,0x4000000,0x160000c,0x110a5400,0x4000002,0xe7000c,0x110a5400,0x4000010,0x87140c,0x110a5400,0x4000010, 0xe7000c,0x110a5400,0x4000010,0x120140c,0x110a5400,0x4000010,0x127100c,0x110a5400,0x4000020,0xe0000c,0x110a5400,0x4000026,0xe7000c,0x110a5400,0xc000010,0x80ac0c, 0x110a5400,0xc000010,0xb4800c,0x11400c0c,0x4000010,0xb00000,0x11400c0c,0x4000010,0x1071400,0x11400c17,0xc000010,0xb48000,0x11400c1e,0x7c00900,0x230400,0x11400f4b, -0xc000010,0x448000,0x11400f5f,0xc000010,0x448000,0x11401d94,0x4000000,0x200000,0x11403dca,0x4000000,0xe00000,0x114457bf,0x4000004,0x120000a,0x114457bf,0x4000008, -0x81000a,0x114457bf,0x4000008,0x141000a,0x114457bf,0x4000010,0x87000a,0x114457bf,0xc000010,0x84800a,0x114457c8,0x3802500,0x126246a,0x114457c8,0x7c00d00,0x2530c0a, -0x114a3dbf,0x24000000,0x810000,0x114a3dbf,0x24000000,0x1410000,0x114a3dbf,0x24000008,0x810000,0x114a3dbf,0x24000008,0x1410000,0x114a3dbf,0x24000010,0x870000,0x114a3dbf, -0x2c000010,0x848000,0x114a3dc5,0x4000000,0xe00000,0x114a3dc5,0x24000000,0xe00000,0x114a3dc5,0x24000002,0xe00000,0x114a3dc5,0x24000002,0x1200000,0x114a3dc5,0x24000008, -0x810000,0x114a3dc5,0x24000008,0x1410000,0x114a3dc8,0x7c00900,0x930c00,0x114a3dc8,0x7c00900,0xe30c00,0x114a3dca,0x7c00300,0xe30000,0x114a3ec8,0x7000400,0x1200c02, -0x114a3fbf,0x4000004,0x1200000,0x114a3fc8,0x7c00d00,0x2530c00,0x114a42ca,0x4000000,0xe00000,0x114a42ca,0x4000000,0xe0000f,0x114a44ca,0x4000000,0xe00002,0x114a44ca, -0x4000000,0xe00003,0x114a45ca,0x4000000,0xe00002,0x114a45ca,0x4000000,0xe0000d,0x11505103,0x24000000,0x810000,0x11505103,0x24000000,0x1410000,0x1180090a,0x2802400, +0xc000010,0x448000,0x11400f5f,0xc000010,0x448000,0x11401d94,0x4000000,0x200000,0x11403dcc,0x4000000,0xe00000,0x114457c1,0x4000008,0x81000a,0x114457c1,0x4000008, +0x141000a,0x114457c1,0x4000010,0x87000a,0x114457c1,0x6800004,0x120000a,0x114457c1,0xc000010,0x84800a,0x114457ca,0x3802500,0x126246a,0x114457ca,0x7c00d00,0x2530c0a, +0x114a3dc1,0x24000000,0x810000,0x114a3dc1,0x24000000,0x1410000,0x114a3dc1,0x24000008,0x810000,0x114a3dc1,0x24000008,0x1410000,0x114a3dc1,0x24000010,0x870000,0x114a3dc1, +0x2c000010,0x848000,0x114a3dc7,0x4000000,0xe00000,0x114a3dc7,0x24000000,0xe00000,0x114a3dc7,0x24000002,0xe00000,0x114a3dc7,0x24000002,0x1200000,0x114a3dc7,0x24000008, +0x810000,0x114a3dc7,0x24000008,0x1410000,0x114a3dca,0x7c00900,0x930c00,0x114a3dca,0x7c00900,0xe30c00,0x114a3dcc,0x7c00300,0xe30000,0x114a3eca,0x7000400,0x1200c02, +0x114a3fc1,0x6800004,0x1200000,0x114a3fca,0x7c00d00,0x2530c00,0x114a42cc,0x4000000,0xe00000,0x114a42cc,0x4000000,0xe0000f,0x114a44cc,0x4000000,0xe00002,0x114a44cc, +0x4000000,0xe00003,0x114a45cc,0x4000000,0xe00002,0x114a45cc,0x4000000,0xe0000d,0x11505113,0x24000000,0x810000,0x11505113,0x24000000,0x1410000,0x1180090a,0x2802400, 0x962460,0x11800c27,0x2802100,0x962460,0x11800c27,0x2802500,0x962460,0x11800f32,0x2802400,0x962460,0x11800f3f,0x2802400,0x962460,0x11820700,0x2802400,0x962460, -0x11820700,0x2802500,0x962460,0x118a3dcb,0x2802400,0x962460,0x118a3ec8,0x2802400,0x962460,0x11c00904,0x2802400,0x962460,0x11c00908,0x2802400,0x962460,0x11c00c2c, +0x11820700,0x2802500,0x962460,0x118a3dcd,0x2802400,0x962460,0x118a3eca,0x2802400,0x962460,0x11c00904,0x2802400,0x962460,0x11c00908,0x2802400,0x962460,0x11c00c2c, 0x6800000,0x1329800,0x11c00c30,0xc000010,0xb48000,0x11c00f78,0x6800000,0x1329800,0x11c0107d,0x6800000,0x1329800,0x11c01181,0x6800000,0x1329800,0x11c01285,0x6800000, -0x1329800,0x11c01489,0x4000000,0x200000,0x11c01489,0x6800000,0x1329800,0x11c0168d,0x6800000,0x1329800,0x11d05107,0x7c00100,0x230408,0x20000067,0x1000,0, +0x1329800,0x11c01489,0x4000000,0x200000,0x11c01489,0x6800000,0x1329800,0x11c0168d,0x6800000,0x1329800,0x11d05117,0x7c00100,0x230408,0x20000067,0x1000,0, 0x20000b13,0x2802400,0x962460,0x20000b13,0x2802500,0x962460,0x20001b27,0x2802100,0x962460,0x20001b27,0x2802100,0x962461,0x20001b27,0x2802400,0x962460,0x20001b27, 0x2802500,0x962460,0x20001b27,0x2806400,0x962460,0x20001b27,0x2902100,0x962462,0x20001b27,0x4000000,0x200000,0x20001b27,0x4000000,0x400000,0x20001b27,0x4000000, 0x500000,0x20001b27,0x4000000,0x810000,0x20001b27,0x4000000,0xb00000,0x20001b27,0x4000000,0xc0000b,0x20001b27,0x4000000,0x1410000,0x20001b27,0x4000010,0xb00000, @@ -3692,7 +3705,7 @@ static const uint32_t propsVectors[7230]={ 0x200400,0x3000080e,0x7c00100,0x220400,0x30000908,0x2000,0x962460,0x30000908,0x7c00100,0x220400,0x30000908,0x7c00100,0x220401,0x30000908,0x7c00100,0x250400, 0x30000908,0x7c00100,0x250401,0x30000a03,0x4000006,0x400400,0x30000c02,0x4000000,0x200000,0x30000c02,0x7c00100,0x230400,0x30000d22,0x2802100,0x962460,0x30000d22, 0x2802400,0x962460,0x30000d22,0x2802500,0x962460,0x30000d22,0x4000000,0x200000,0x30000d22,0x4000010,0x200000,0x30000d22,0x7c00100,0x230400,0x30000d22,0xc000010, -0x248000,0x30000d22,0x80000000,0x218960,0x30000e25,0x2802500,0x962460,0x30000e25,0x7c00100,0x230400,0x30001821,0x2802100,0x962460,0x30001821,0x2806400,0x962460, +0x248000,0x30000d22,0x80000000,0x218560,0x30000e25,0x2802500,0x962460,0x30000e25,0x7c00100,0x230400,0x30001821,0x2802100,0x962460,0x30001821,0x2806400,0x962460, 0x30001821,0x4000000,0x200000,0x30001821,0x6800100,0x962540,0x30001821,0x6800100,0x962541,0x30001821,0x7c00100,0x230400,0x30001b27,0x2802100,0x962460,0x30001b27, 0x2802400,0x962460,0x30001b27,0x4000000,0x200000,0x30001b27,0x4000000,0x400000,0x30001b27,0x7c00100,0x230400,0x30001c1c,0x2802100,0x1862460,0x30001c1c,0x2802400, 0x1862460,0x30001c1c,0x2806400,0x1862460,0x30001c1c,0x4000000,0x200000,0x30001c1c,0x6800100,0x1862400,0x30001c1c,0x6800100,0x1862540,0x30001c1c,0x7c00100,0x1830000, @@ -3701,292 +3714,294 @@ static const uint32_t propsVectors[7230]={ 0x230400,0x30002128,0xc000010,0x248000,0x3000221d,0x4000000,0x810000,0x3000221d,0x4000000,0x1410000,0x3000221d,0x4000001,0x445800,0x3000221d,0x7c00100,0x230400, 0x30002300,0x4000010,0x400000,0x30002320,0x7c00100,0x230400,0x30002417,0x2802100,0x1862460,0x30002417,0x2802400,0x1862460,0x30002417,0x2806400,0x1862460,0x30002417, 0x2882000,0x1862460,0x30002417,0x4000000,0x200000,0x30002417,0x4000000,0x400000,0x30002417,0x4000000,0x1600000,0x30002417,0x4000010,0x400000,0x30002417,0x4000010, -0x1200000,0x30002417,0x6800000,0x1329800,0x30002417,0x6800100,0x1862540,0x30002417,0x7c00100,0x1830000,0x30002417,0x7d00100,0x1830000,0x3000251b,0x80000,0xc18820, -0x3000251b,0x2802100,0x962460,0x3000251b,0x3c02100,0x962460,0x3000251b,0x4000000,0x200000,0x3000251b,0x4000006,0x500000,0x3000251b,0x4000010,0x400000,0x3000251b, -0x4000010,0xb70000,0x3000251b,0x4000800,0x200000,0x3000251b,0x6800000,0x1329800,0x3000251b,0x7c00100,0x230400,0x3000251b,0x7c00900,0x230400,0x3000251b,0xc000010, -0xb48000,0x3000251b,0x12882000,0x962460,0x30002800,0x24000000,0x200000,0x30002800,0x2c000010,0x1248002,0x30002a00,0x4000000,0x1600000,0x30002b01,0x2000,0x962460, -0x30002c00,0x4000000,0x200000,0x30002c00,0x7c00100,0x220405,0x30002d19,0x7c00100,0x250400,0x30002e00,0x24000000,0x200000,0x30003000,0x24000000,0x200000,0x30003100, -0x24000000,0x200000,0x30003600,0x24000000,0x200000,0x30003700,0x24000000,0x200000,0x3000392e,0x24000000,0x200000,0x30005013,0x7c00100,0x2633801,0x30005600,0, -0x918820,0x30020600,0x4000400,0x500400,0x30020701,0x2802400,0x962460,0x30020701,0x2802400,0xc62460,0x300a3a11,0x4020000,0xe00000,0x300a3a11,0x4020000,0xe00002, -0x300a3b11,0x4020000,0xe00002,0x300a3c00,0x4008000,0xe00000,0x300a3c00,0x4010000,0xe00000,0x300a3d11,0x7c00300,0xe30002,0x300a4305,0x7c00100,0xe30400,0x300a4611, -0x7c40300,0xe30000,0x300a4829,0x7c00100,0xe30400,0x300a4829,0x7c00900,0x1230400,0x300a4929,0x4000000,0xe00000,0x3040259a,0x4000010,0x400000,0x3040259a,0x4000010, -0xb70000,0x3040259a,0xc000010,0xb48000,0x304028ba,0x4000001,0xc41c0b,0x304a3dca,0x4000000,0xe00000,0x30800c27,0x2802100,0x962460,0x30c01c92,0x6800000,0x1329800, -0x3100080e,0x7c00120,0x220402,0x3100080e,0x7c00120,0x250402,0x31005167,0x1000,0,0x3100581e,0x4000000,0x200000,0x3100581e,0x7c00100,0x230400,0x3100590d, -0x7c00100,0x230400,0x31005a09,0x7c00100,0x220400,0x31005a09,0x7c00100,0x250400,0x31005b00,0x4000000,0x200000,0x31005c00,0x80000,0x918820,0x31005c00,0x2802000, -0x962460,0x31005c00,0x2802400,0x962460,0x31005c00,0x4000000,0x200000,0x31005c00,0x4000000,0x200001,0x31005c00,0x6800000,0x962540,0x31005c00,0x6800400,0x962540, -0x31005c01,0x2802400,0x962460,0x31005d00,0x4000020,0x200005,0x31005d00,0x6800020,0x1329805,0x31005d00,0x7c00120,0x220405,0x31005d00,0x7c00120,0x250405,0x31006000, -0x82000,0x962460,0x31006000,0x180000,0x918820,0x310a5e11,0x7c40300,0xe30000,0x310a5f11,0x7c00300,0xe30001,0x32000419,0x7c00100,0x250400,0x3200080e,0x4000020, -0x200000,0x3200080e,0x7c00100,0x220400,0x3200080e,0x7c00100,0x250400,0x32000908,0x7c00100,0x220400,0x32000908,0x7c00100,0x250400,0x32000c02,0x7c00100,0x230400, -0x32000e25,0x7c00100,0x230400,0x32001d0c,0x7c00100,0x230400,0x32002800,0x80000,0x1e18820,0x32002800,0x80020,0x218820,0x32002800,0x4000001,0x445802,0x32002800, -0x24000000,0x200000,0x32002800,0x24000000,0x1500002,0x32002800,0x24000020,0x200000,0x32002800,0x2c000010,0x1248002,0x32002919,0x7c00100,0x22040f,0x32002a00,0x4000000, -0x1600000,0x32002b01,0x2000,0x962460,0x32002b01,0x2802000,0x962460,0x32002b01,0x2802020,0x962460,0x32002c00,0x4000000,0x200000,0x32002c00,0x4000020,0x200000, -0x32002c00,0x4000020,0x200005,0x32002c00,0x7c00120,0x220405,0x32002c00,0x7c00120,0x250405,0x32002e00,0x24000020,0x200000,0x32002f00,0x24000020,0x200000,0x32003000, -0x24000000,0x200000,0x32003000,0x24000020,0x200000,0x32003500,0x24000000,0x200000,0x32003600,0x24000020,0x200000,0x32003700,0x24000000,0x100000,0x32003700,0x24000000, -0x200000,0x32003800,0x24000000,0x810000,0x32003800,0x24000000,0x1410000,0x32005102,0x4000000,0x1500008,0x32005502,0x7c00100,0x230400,0x32006108,0x7c00100,0x220400, -0x32006108,0x7c00100,0x250400,0x3200622a,0x2802100,0x962460,0x3200622a,0x2806400,0x962460,0x3200622a,0x7c00100,0x230400,0x3200632b,0x2802100,0x962460,0x3200632b, -0x6804000,0x962540,0x3200632b,0x7c00100,0x230400,0x3200642c,0x2802100,0x962460,0x3200642c,0x7c00100,0x230400,0x3200652d,0x2802100,0x962460,0x3200652d,0x7c00100, -0x230400,0x32006600,0x24000020,0x200000,0x32006700,0x24000020,0x200000,0x32006800,0x24000020,0x200000,0x32006900,0x24000020,0x200000,0x32006900,0x24000020,0x810000, -0x32006900,0x24000020,0x1410000,0x32006a00,0x24000020,0x200000,0x32006a00,0x24000020,0x200001,0x32006a00,0x24000020,0x200002,0x32020701,0x2882000,0xc62460,0x32023300, -0x4000000,0x100000,0x32026c01,0x12882000,0x962460,0x32065700,0x4000000,0x810011,0x32065700,0x4000000,0x1410011,0x32086600,0x24000020,0x810000,0x32086600,0x24000020, -0x1410000,0x32086900,0x24000020,0x810000,0x32086900,0x24000020,0x1410000,0x320a3600,0x24000020,0x200000,0x320a3d11,0x7c00100,0x1230400,0x320a3e14,0x7c00100,0xe30010, -0x320a3e14,0x7c00100,0x2530000,0x320a3f16,0x7c00100,0xe30c10,0x320a4400,0x4000000,0xe00003,0x320a4929,0x4000000,0xe00000,0x320a4f11,0x7c00300,0xe30001,0x320a6b16, -0x7c00100,0x2530c00,0x32406396,0xc000010,0x448000,0x324a3dcd,0x4000000,0xe00000,0x324a3dcd,0x7c00100,0x1230400,0x324a3fc8,0x4000002,0x1200c00,0x324a53c5,0x24000000, -0xe00000,0x32820701,0x2802000,0x962460,0x40000419,0x7c00100,0x220400,0x40000519,0x7c00100,0x220400,0x40000600,0x4000400,0x200400,0x4000080e,0x7c00100,0x220400, -0x4000080e,0x7c00100,0x250400,0x4000080e,0x7c00100,0x250402,0x40000c02,0x2802100,0x962460,0x40000c02,0x2802400,0x962460,0x40000c02,0x2802500,0x962460,0x40000c02, -0x4000000,0x200000,0x40000c02,0x4000000,0x1071400,0x40000c02,0x7c00100,0x230400,0x40000c02,0x80000000,0x218960,0x40000d22,0x7c00100,0x230400,0x40000f0a,0x7c00100, -0x230400,0x40001004,0x7c00100,0x230400,0x40001110,0x2802100,0x962460,0x40001110,0x6800100,0x962540,0x4000120f,0x2802100,0x962460,0x4000120f,0x4000000,0x1600000, -0x4000120f,0x7c00100,0x230400,0x4000131f,0x7c00100,0x230400,0x40001423,0x4000000,0x200000,0x40001423,0x4000000,0x1600000,0x40001615,0x2802400,0x962460,0x40001615, -0x7c00100,0x230400,0x40002417,0x2802400,0x1862460,0x40002417,0x4000000,0x200000,0x40002800,0x6800000,0x201c00,0x40002800,0x24000002,0x200000,0x40002c00,0x4000000, -0x200002,0x40003000,0x24000000,0x200000,0x40003000,0x24000020,0x200000,0x40003700,0x24000000,0x200000,0x40005a09,0x7c00100,0x220400,0x40005a09,0x7c00100,0x250400, -0x40005d00,0x7c00120,0x220405,0x40006f30,0x2802100,0x962460,0x40006f30,0x2802400,0x962460,0x40006f30,0x4000000,0x200000,0x40006f30,0x6800000,0x1329800,0x40006f30, -0x6800100,0x962540,0x40006f30,0x7c00100,0x230400,0x40006f30,0xc000010,0xb48000,0x40007034,0x7c00100,0x1830000,0x40007117,0x4000000,0x200000,0x40007208,0x7c00100, -0x220400,0x4000720e,0x7c00100,0x220400,0x4000720e,0x7c00500,0x22040e,0x4000720e,0x7c00500,0x22040f,0x40007219,0x7c00100,0x220400,0x40007219,0x7c00500,0x220400, -0x40007219,0x7c00500,0x22040e,0x40007219,0x7c00500,0x22040f,0x40007300,0x24000000,0x200000,0x40007400,0x4000000,0x200000,0x40007531,0x7c00100,0x230400,0x40007631, -0x7c00100,0x230400,0x40007835,0x4000010,0x400000,0x40007835,0x7c00100,0x230400,0x40007933,0x7c00100,0x230400,0x40007a32,0x6800000,0x1329800,0x40007a32,0x7c00100, -0x230400,0x40007b2f,0x7c00100,0x230400,0x40007c00,0x4000000,0x200000,0x40020701,0x2802400,0x962460,0x40020701,0x2802400,0xc62460,0x40023300,0x4000000,0x200000, -0x40027d01,0x12882000,0x962460,0x400a3700,0x24000000,0x200000,0x400a3700,0x24000000,0xe00000,0x400a4400,0x4000000,0xe0000d,0x400a4412,0x4000000,0xe00002,0x400a4412, -0x4000000,0xe00003,0x400a4500,0x4000000,0xe0000d,0x400a5300,0x4000000,0x810010,0x400a5300,0x4000000,0x1410010,0x40507709,0x4000000,0x200000,0x4050770c,0x4000000, -0x400000,0x4050770f,0x4000000,0x200000,0x4050770f,0x4000000,0x400000,0x40c01489,0x4000000,0x200000,0x40d05107,0x4000000,0x200000,0x41000419,0x7c00100,0x220400, -0x41000419,0x7c00100,0x250400,0x4100080e,0x7c00100,0x220400,0x4100080e,0x7c00100,0x250400,0x41000908,0x7c00100,0x220400,0x41000908,0x7c00100,0x250400,0x41000b13, -0x2802000,0x962460,0x41000b13,0x2802100,0x962460,0x41000b13,0x4000000,0xb00000,0x41000c02,0x2802100,0x962460,0x41000c02,0x4000000,0x1500000,0x41000c02,0xc000010, -0xb48000,0x41000f0a,0x7c00100,0x230400,0x41001004,0x7c00100,0x230400,0x41001423,0x7c00100,0x230400,0x41001b27,0x4000000,0x500000,0x41001d0c,0x7c00100,0x22040f, -0x41001d0c,0x7c00100,0x230400,0x41001f0b,0x2802400,0x962460,0x41001f0b,0x4000000,0x200000,0x41001f0b,0x7c00100,0x230400,0x41002800,0x24000000,0x200000,0x41002800, -0x24000000,0x400000,0x41002919,0x7c00100,0x22040e,0x41002a00,0x4000000,0x1600000,0x41002b01,0x2802020,0x962460,0x41002c00,0x4000000,0x200000,0x41002c00,0x7c00120, -0x220405,0x41003000,0x24000000,0x200000,0x41003700,0x24000000,0x200000,0x41003700,0x24000000,0xe00000,0x41005d00,0x7c00120,0x220405,0x41006600,0x24000020,0x200000, -0x41006600,0x24000020,0x810000,0x41006600,0x24000020,0x1410000,0x41007208,0x7c00100,0x22040f,0x41007219,0x7c00100,0x220400,0x41007300,0x24000000,0x200000,0x41007e0e, -0x2802000,0x962460,0x41007e0e,0x4000000,0x200000,0x41007f0e,0x4000000,0x200000,0x41007f0e,0x7c00100,0x230400,0x41008002,0x7c00100,0x230400,0x41008137,0x2802100, -0x962460,0x41008137,0x4000000,0x200000,0x41008137,0x6800100,0x962540,0x41008137,0x7c00100,0x230400,0x41008301,0x2802000,0x962460,0x41008407,0x4000000,0x200000, -0x41008407,0x4000000,0x400000,0x41008407,0x4000000,0xb00000,0x41008407,0x7c00100,0x220400,0x41008407,0x7c00100,0x250400,0x4100850b,0x7c00100,0x230400,0x4100860b, -0x4000000,0x200000,0x4100860b,0x7c00100,0x230400,0x4100870c,0x7c00100,0x220400,0x41008838,0x7c00100,0x220400,0x41008838,0x7c00100,0x250400,0x41008939,0x2802000, -0x962460,0x41008939,0x2802100,0x962460,0x41008939,0x2806000,0x962460,0x41008939,0x4000000,0x200000,0x41008939,0x4000000,0x400000,0x41008939,0x7c00100,0x230400, -0x41008939,0xc000010,0x448000,0x41008a00,0x4000400,0x200400,0x41008b3b,0x4000000,0x1800000,0x41008b3b,0x6800000,0x1329800,0x41008b3b,0x7c00100,0x1830000,0x41008b3b, -0x7e00100,0x1830000,0x41008c3d,0x4000010,0x400000,0x41008c3d,0x7c00100,0x230400,0x41008d0e,0x7c00100,0x22040f,0x41008d19,0x7c00100,0x220400,0x41008d19,0x7c00100, -0x22040f,0x41008e00,0x24000000,0x200000,0x41008e00,0x24000000,0x400000,0x41008e00,0x24000000,0x1710000,0x41008e00,0x24000006,0x400000,0x41008f3a,0x2802100,0x962460, -0x41008f3a,0x2806000,0x962460,0x41008f3a,0x4000000,0x200000,0x41008f3a,0x6800100,0x962540,0x41008f3a,0x7c00100,0x230400,0x4100903c,0x7c00100,0x230400,0x4100903c, -0x7c00100,0x23040f,0x41020701,0x2802000,0x962460,0x41020701,0x2802000,0xc62460,0x410a3700,0x24000000,0x200000,0x410a3700,0x24000000,0xe00000,0x410a4412,0x4000000, -0xe00003,0x410a4711,0x7c40300,0xe30000,0x410a4f11,0x7c00300,0xe30001,0x410a9100,0x4000000,0x800010,0x410a9100,0x4000000,0x810010,0x410a9100,0x4000000,0x870010, -0x410a9100,0x4000000,0xb00010,0x410a9100,0x4000000,0xf00010,0x410a9100,0x4000000,0x1001410,0x410a9100,0x4000000,0x1071010,0x410a9100,0x4000000,0x1071410,0x410a9100, -0x4000000,0x1410010,0x41408ad0,0x4000400,0x200000,0x414a82ca,0x4000000,0xe00000,0x41808300,0x2802000,0x962460,0x41c01489,0x6800000,0x1329800,0x50000419,0x7c00100, -0x220400,0x50000419,0x7c00100,0x250400,0x5000080e,0x7c00100,0x220400,0x50000908,0x7c00100,0x220400,0x50000908,0x7c00100,0x250400,0x50000b13,0x2802500,0x962460, -0x50000f0a,0x7c00100,0x230400,0x50001615,0x2802100,0x962460,0x50001615,0x7c00100,0x230400,0x50002b01,0x2802020,0x962460,0x50002c00,0x4000000,0x200000,0x50002c19, -0x7c00100,0x220400,0x50002d19,0x7c00100,0x220400,0x50003000,0x24000000,0x200000,0x50003000,0x24000020,0x200000,0x50003700,0x24000000,0x200000,0x50005d00,0x7c00120, -0x220405,0x50005d00,0x7c00120,0x250405,0x50006108,0x7c00100,0x220400,0x50006108,0x7c00100,0x250400,0x50006600,0x24000020,0x200000,0x50007300,0x24000000,0x200000, -0x50008301,0x2802400,0x962460,0x50008a00,0x7c00500,0x230400,0x50009257,0x2802400,0x962460,0x50009257,0x4000000,0x200000,0x50009257,0x4000010,0x1071400,0x50009257, -0x6800000,0x1329800,0x50009257,0x7c00100,0x230400,0x50009257,0x7c00500,0x230400,0x50009257,0x7c00900,0x230400,0x50009257,0xc000010,0xb48000,0x5000933e,0x2802100, -0x962460,0x5000933e,0x2802400,0x962460,0x5000933e,0x4000000,0x200000,0x5000933e,0x4000000,0x400000,0x5000933e,0x4000010,0x400000,0x5000933e,0x6800000,0x1329800, -0x5000933e,0x6800100,0x962540,0x5000933e,0x6800100,0x962541,0x5000933e,0x6804400,0x962540,0x5000933e,0x7c00100,0x230400,0x5000933e,0x7c00100,0x230401,0x5000933e, -0xc000010,0x448000,0x50009419,0x7c00100,0x220400,0x50009419,0x7c00100,0x250400,0x50009500,0x4000400,0x200400,0x5000965a,0x4000000,0x500000,0x5000965a,0x7c00100, -0x230400,0x5000965a,0xc000010,0xb48000,0x5000975b,0x4000000,0x200000,0x5000975b,0x4000010,0x400000,0x5000975b,0x7c00100,0x230400,0x50009865,0x7c00100,0x230400, -0x50009965,0x4000010,0x400000,0x50009965,0x7c00100,0x230400,0x50409aca,0x4000000,0x200000,0x5100080e,0x7c00100,0x220400,0x5100080e,0x7c00100,0x250400,0x51000c02, -0x2802100,0x962460,0x51000c02,0x4000000,0x1500000,0x51000c02,0x4000020,0x200000,0x51000c02,0x7c00100,0x230400,0x51000f0a,0x7c00100,0x230400,0x51000f0a,0x7c00500, -0x230400,0x51001110,0x2802100,0x962460,0x5100131f,0x2802100,0x962460,0x51001423,0x7c00100,0x230400,0x51001524,0x2802100,0x962460,0x51001524,0x4000000,0x200000, -0x51001524,0x7c00100,0x230400,0x5100171a,0x2802100,0x962460,0x5100171a,0x4000000,0x200000,0x5100171a,0x4000000,0x1500000,0x5100171a,0x7c00100,0x230400,0x51001b27, -0x4000000,0x200000,0x51001b27,0x4000000,0x400000,0x51001b27,0x4000000,0x500000,0x51001b27,0x7c00100,0x230400,0x51001c1c,0x2802100,0x1862460,0x51001c1c,0x2802500, -0x1862460,0x51001c1c,0x2806400,0x1862460,0x51001c1c,0x4000000,0x1800000,0x51001c1c,0x6800000,0x1329800,0x51001c1c,0x6800100,0x1862400,0x51001c1c,0x6800100,0x1862540, -0x51001c1c,0x6800500,0x1862400,0x51001c1c,0x7c00100,0x1830000,0x5100251b,0x7c00100,0x230400,0x51002619,0x7c00100,0x220400,0x51002619,0x7c00100,0x250400,0x51002800, -0x80020,0x218820,0x51002c00,0x4000000,0x200000,0x51002d19,0x7c00100,0x230400,0x51003700,0x24000000,0x200000,0x51003700,0x24000000,0xe00000,0x51005201,0x2802400, -0x962460,0x51005c00,0x4000000,0x200000,0x51006108,0x7c00100,0x220400,0x51006108,0x7c00100,0x250400,0x51006600,0x24000020,0x200000,0x51006600,0x24000020,0x810000, -0x51006600,0x24000020,0x1410000,0x51007300,0x24000000,0x200000,0x51007300,0x24000020,0x200000,0x51008002,0x7c00100,0x230400,0x51008301,0x2802000,0x962460,0x51008301, -0x2802400,0x962460,0x51008301,0x2802400,0xc62460,0x51008a00,0x7c00500,0x230400,0x51008e00,0x24000000,0x200000,0x51008e00,0x24000000,0x400000,0x51008e00,0x24000000, -0x810000,0x51008e00,0x24000000,0x1400000,0x51008e00,0x24000000,0x1410000,0x51008e00,0x24000000,0x1710000,0x51008e00,0x24000002,0x200000,0x51008e00,0x24000500,0x230400, -0x51008e00,0x2c000010,0xb48000,0x51009419,0x7c00100,0x220400,0x51009419,0x7c00100,0x22040e,0x51009419,0x7c00100,0x22040f,0x51009419,0x7c00100,0x250400,0x51009500, -0x4000400,0x200400,0x51009500,0x7c00500,0x230400,0x51009519,0x7c00100,0x220400,0x51009519,0x7c00100,0x22040f,0x51009519,0x7c00100,0x230400,0x51009519,0x7c00100, -0x250400,0x51009b71,0x2802100,0x962460,0x51009b71,0x6800000,0x1329800,0x51009b71,0x6800100,0x962540,0x51009b71,0x6804400,0x962540,0x51009b71,0x7c00100,0x230400, -0x51009c52,0x2802100,0x962460,0x51009c52,0x2802400,0x962460,0x51009c52,0x2802d00,0x962460,0x51009c52,0x4000010,0x400000,0x51009c52,0x6800000,0x1329800,0x51009c52, -0x6800100,0x962540,0x51009c52,0x7c00100,0x230400,0x51009c52,0xc000010,0x448000,0x51009d6d,0x6800000,0x1329800,0x51009d6d,0x7c00100,0x230400,0x51009d6d,0x7c00500, -0x230400,0x51009d6d,0x7c00d00,0x230400,0x51009d6d,0xc000010,0x448000,0x51009e08,0x2802100,0x962460,0x51009f63,0x4000010,0x400000,0x51009f63,0x6800000,0x1329800, -0x51009f63,0x7c00100,0x230400,0x51009f63,0x7c00900,0x230400,0x51009f63,0xc000010,0x448000,0x51009f63,0xc000010,0xb48000,0x5100a008,0x2000,0x962460,0x5100a008, -0x2802400,0x962460,0x5100a008,0x4000000,0x200000,0x5100a008,0x7c00100,0x220400,0x5100a008,0x7c00100,0x230400,0x5100a008,0x7c00100,0x250400,0x5100a008,0x7c00500, -0x230400,0x5100a16f,0x2806400,0x962460,0x5100a16f,0x6800000,0x1329800,0x5100a16f,0x6800100,0x962540,0x5100a16f,0x7c00100,0x230400,0x5100a16f,0xc000010,0x448000, -0x5100a24f,0x2802100,0x962460,0x5100a24f,0x2802400,0x962460,0x5100a24f,0x6800000,0x1329800,0x5100a24f,0x7c00100,0x230400,0x5100a24f,0xc000010,0x448000,0x5100a36e, -0x2802100,0x962460,0x5100a36e,0x4000000,0x200000,0x5100a36e,0x6800100,0x962540,0x5100a36e,0x6804400,0x962540,0x5100a36e,0x7c00100,0x230400,0x5100a442,0x2802100, -0x962460,0x5100a442,0x4000000,0x200000,0x5100a442,0x6800000,0x1329800,0x5100a442,0x6800100,0x962540,0x5100a442,0x7c00100,0x230400,0x5100a442,0xc000010,0x448000, -0x5100a500,0x4000000,0x200000,0x5100a600,0x4000000,0x200000,0x5100a601,0x2802000,0x962460,0x5100a76b,0x7c00100,0x230400,0x5100a868,0x7c00100,0x230400,0x5100a96c, -0x4000000,0x200000,0x5100a96c,0x7c00100,0x230400,0x5100aa00,0x4000000,0xe00000,0x5100ab00,0x4000000,0xe00000,0x51086600,0x24000020,0x810000,0x51086600,0x24000020, -0x1410000,0x510a4005,0x7c00100,0xe30400,0x510a4711,0x7c40300,0xe30000,0x510a7300,0x24000000,0x200000,0x510aaa00,0x4000000,0xe00000,0x5140a2fe,0x4000400,0x400000, -0x514a82ca,0x4000000,0xe00000,0x51802bbc,0x2802000,0x962460,0x51c00908,0x2802400,0x962460,0x51c0a008,0x2802400,0x962460,0x52000f0a,0x2802100,0x962460,0x52000f0a, -0x6800100,0x962540,0x52000f0a,0x7c00100,0x230400,0x52001004,0x4000000,0x1600000,0x52001b00,0x4000000,0x200000,0x52001c1c,0x2802100,0x1862460,0x52001c1c,0x6800100, -0x1862400,0x52001c1c,0x6800500,0x1862400,0x52001e12,0x7c00100,0x2230500,0x52001e12,0x7c00100,0x2330520,0x52002128,0x4000002,0x400000,0x52002128,0x7c00100,0x230400, -0x52002a00,0x4000000,0x1500000,0x52002a00,0x4000000,0x1600000,0x52002d00,0x4000000,0x200006,0x52003000,0x24000000,0x200000,0x52006108,0x7c00100,0x220400,0x52006108, -0x7c00100,0x250400,0x52008301,0x2802400,0x962460,0x52008407,0x2802400,0x962460,0x52008407,0x7c00100,0x220400,0x52008407,0x7c00100,0x250400,0x52008b3b,0x6800000, -0x1800000,0x52008b3b,0x7c00100,0x1830000,0x52008e00,0x24000000,0x400000,0x52009419,0x7c00100,0x250400,0x5200975b,0x4000000,0x200000,0x5200ac7e,0x2802000,0x962460, -0x5200ac7e,0x2802100,0x962460,0x5200ac7e,0x2802400,0x962460,0x5200ac7e,0x4000010,0x200000,0x5200ac7e,0x7c00100,0x230400,0x5200ac7e,0xc000010,0x248000,0x5200ad28, -0x7c00100,0x230400,0x5200ae6a,0x2802100,0x1862460,0x5200ae6a,0x2802400,0x962460,0x5200ae6a,0x2802400,0x1862460,0x5200ae6a,0x2806000,0x1862460,0x5200ae6a,0x4000000, -0x1800000,0x5200ae6a,0x6800000,0x1329800,0x5200ae6a,0x6800100,0x1862400,0x5200ae6a,0x6800100,0x1862540,0x5200ae6a,0x7c00100,0x1830000,0x5200ae6a,0x7c00900,0x1830000, -0x5200ae6a,0xc000010,0x1848000,0x5200b083,0x4000010,0x400000,0x5200b083,0x7c00100,0x230400,0x5200b083,0xc000010,0x448000,0x5200b182,0x2802400,0x962460,0x5200b182, -0x4000000,0x200000,0x5200b182,0x4000010,0x400000,0x5200b182,0x7c00100,0x230400,0x5200b182,0xc000010,0x448000,0x5200b30a,0x2802400,0x962460,0x5200b30a,0x4000000, -0x200000,0x5200b30a,0x7c00100,0x230400,0x5200b54e,0x2802100,0x962460,0x5200b54e,0x2802400,0x962460,0x5200b54e,0x4000000,0x200000,0x5200b54e,0x4000010,0x400000, -0x5200b54e,0x6800000,0x1329800,0x5200b54e,0x6800100,0x962540,0x5200b54e,0x6804400,0x962540,0x5200b54e,0x7c00100,0x230400,0x5200b54e,0xc000010,0x448000,0x5200b61c, -0x4000000,0x1800000,0x5200b61c,0x6800500,0x1862400,0x5200b61c,0x7c00100,0x1830000,0x5200b61c,0x7c00900,0x1830000,0x5200b77f,0x2802100,0x1862460,0x5200b77f,0x2802400, -0x1862460,0x5200b77f,0x4000000,0x1800000,0x5200b77f,0x4000010,0x1800000,0x5200b77f,0x7c00100,0x1830000,0x5200b77f,0x7c00500,0x1830000,0x5200b77f,0x7c00900,0x1830000, -0x5200b77f,0x7e00100,0x1830000,0x5200b873,0x2802100,0x962460,0x5200b873,0x2806400,0x962460,0x5200b873,0x6800000,0x1329800,0x5200b873,0x6800100,0x962540,0x5200b873, -0x6800400,0x962540,0x5200b873,0x7c00100,0x230400,0x5200b873,0xc000010,0x448000,0x5200b912,0x7c00100,0x2230500,0x5200b912,0x7c00100,0x2330520,0x5200ba74,0x4000000, -0x200000,0x5200ba74,0x4000010,0x400000,0x5200ba74,0x7c00100,0x230400,0x5200bb85,0x4000000,0x200000,0x5200bb85,0x7c00100,0x230400,0x5200bc75,0x4000000,0x400000, -0x5200bc75,0x4000010,0x400000,0x5200bc75,0x7c00100,0x230400,0x5200bd7d,0x4000000,0x200000,0x5200bd7d,0x7c00100,0x230400,0x5200be7a,0x4000000,0x200000,0x5200be7a, -0x7c00100,0x230400,0x5200bf58,0x7c00100,0x230400,0x5200c002,0x4000000,0x200000,0x5200c178,0x2802100,0x962460,0x5200c178,0x2802400,0x962460,0x5200c178,0x2806400, -0x962460,0x5200c178,0x4000000,0x200000,0x5200c178,0x6800100,0x962540,0x5200c178,0x7c00100,0x230400,0x5200c178,0x7c00100,0x230401,0x5200c178,0xc000010,0x448000, -0x5200c178,0x80000000,0x218960,0x5200c247,0x7c00100,0x230400,0x5200c247,0x7c00100,0x830400,0x5200c247,0x7c00100,0x1430400,0x5200c300,0x4000000,0x200003,0x52022d00, -0x4000000,0x100006,0x52023700,0x24000000,0x100000,0x52023700,0x24000000,0xe00000,0x52023700,0x24000000,0x2800000,0x52024400,0x4000000,0x100000,0x52027300,0x24000000, -0x100000,0x5202c300,0x4000000,0x100000,0x5202c300,0x4000000,0x100002,0x5202c300,0x4000000,0x100003,0x5202c300,0x4000000,0x10000d,0x5202c300,0x4000100,0x150400, -0x5202c300,0x4000100,0x15040d,0x520a1e12,0x7c00100,0x2130480,0x520a3700,0x24000000,0xe00000,0x520a3800,0x24000000,0x100000,0x520a4711,0x7c40300,0xe30000,0x520a4f11, -0x7c00300,0xe30001,0x520a7300,0x24000000,0x100000,0x520ab412,0x7c00100,0x2130480,0x520ac400,0x4000000,0xe00002,0x520ac400,0x4000000,0xe0000d,0x520ac414,0x4000000, -0xe0000d,0x520ac511,0x7c40300,0xe30000,0x5240af9c,0x7c00100,0x230400,0x5240afa1,0x4000400,0x200000,0x5240afa3,0x6800400,0x962540,0x5240afa3,0x7c00100,0x230400, -0x5240afad,0x7c00100,0x230400,0x5240afaf,0x7c00100,0x230400,0x5240b2d2,0x4000000,0x200000,0x5240b2d2,0x4000000,0x1500000,0x5240b2dd,0x4000000,0x200000,0x5240b2eb, -0x4000000,0x200000,0x524a44ca,0x4000000,0xe00003,0x5250b501,0x7c00900,0x230400,0x5280af9c,0x2802400,0x962460,0x5280af9d,0x2802400,0x962460,0x5280afa3,0x2802400, -0x962460,0x5280afa5,0x2802400,0x962460,0x5280afa7,0x2802400,0x962460,0x52c0b3f8,0x2802400,0x962460,0x52c0b3fc,0x7c00100,0x230400,0x60000c02,0x2802100,0x962460, -0x60000c02,0x7c00100,0x230400,0x60000f0a,0x2802100,0x962460,0x60000f0a,0x6800100,0x962540,0x60000f0a,0x7c00100,0x230400,0x6000131f,0x4000000,0x200000,0x6000171a, -0x7c00100,0x230400,0x6000171a,0x7c00100,0x230560,0x60001b27,0x2802100,0x962460,0x60001b27,0x4000000,0xc00000,0x60001b27,0x7c00100,0x230400,0x60001f0b,0x2802400, -0x962460,0x60002919,0x7c00100,0x22040e,0x60002a00,0x4000000,0x1600000,0x60003000,0x24000000,0x200000,0x60003000,0x24000000,0xe00000,0x60003700,0x24000000,0x200000, -0x60003800,0x24000000,0x1710000,0x60005102,0x4000000,0x200000,0x60006108,0x7c00100,0x220400,0x60006108,0x7c00100,0x250400,0x60006600,0x24000020,0x200000,0x60008301, -0x2802400,0xc62460,0x6000903c,0x2806000,0x962460,0x6000903c,0x4000000,0x400000,0x60009519,0x7c00100,0x220400,0x60009519,0x7c00100,0x250400,0x6000a008,0x7c00100, -0x220400,0x6000a008,0x7c00100,0x250400,0x6000c300,0x4000000,0x2703580,0x6000c654,0x2802000,0x962460,0x6000c654,0x4000010,0x200000,0x6000c654,0x7c00100,0x230400, -0x6000c73f,0x2802000,0x962460,0x6000c73f,0x2802100,0x962460,0x6000c73f,0x4000000,0x200000,0x6000c73f,0x6800100,0x962540,0x6000c73f,0x6804000,0x962540,0x6000c73f, -0x7c00100,0x230400,0x6000c80b,0x7c00100,0x230400,0x6000c941,0x2802100,0x962460,0x6000c941,0x2806400,0x962460,0x6000c941,0x4000000,0x200000,0x6000c941,0x4000010, -0x200000,0x6000c941,0x6800000,0x1329800,0x6000c941,0x6800100,0x962540,0x6000c941,0x7c00100,0x230400,0x6000c941,0xc000010,0x448000,0x6000ca82,0x7c00100,0x230400, -0x6000cc00,0x4000000,0xe00000,0x6000d000,0x4000000,0x200000,0x6002c300,0x4000000,0x100000,0x6002c300,0x4000000,0x10000d,0x6002c300,0x4000100,0x150400,0x6002c300, -0x4000100,0x15040d,0x600a3000,0x24000000,0x200000,0x600a3000,0x24000000,0xe00000,0x600a3700,0x24000000,0x200000,0x600a3800,0x24000000,0x200000,0x600a3800,0x24000000, -0x2800000,0x600a4305,0x7c00100,0xe30400,0x600ac300,0x4000000,0x100000,0x600ac400,0x4000000,0xe0000d,0x600acb14,0x7c00100,0xe30000,0x600acb16,0x7c00100,0xe30c00, -0x600acc00,0x4000000,0xe00000,0x600acd00,0x4000000,0x200000,0x600acd00,0x4000000,0xe00000,0x600acd00,0x4000000,0x2800000,0x600ace00,0x4000000,0xe00000,0x600ace00, -0x4000000,0x2800000,0x600acf00,0x4000000,0xe00000,0x600acf00,0x4000000,0x2800000,0x600ad111,0x7c40300,0xe30000,0x604ac4ca,0x4000000,0xe00003,0x61000a03,0x4000000, -0x1600000,0x61000c02,0x80000000,0x218960,0x6100120f,0x4000000,0x200000,0x61001a18,0x7c00100,0x1830000,0x61001d0c,0x7c00100,0x230400,0x61001d0c,0x7c00100,0x250400, -0x61006600,0x24000020,0x200000,0x61008407,0x7c00100,0x220400,0x61008407,0x7c00100,0x250400,0x6100870c,0x7c00100,0x220400,0x61008e00,0x24000000,0x200000,0x61008e00, -0x24000000,0x400000,0x61008e00,0x24000002,0x300000,0x6100903c,0x7c00100,0x230400,0x61009519,0x7c00100,0x220400,0x61009519,0x7c00100,0x250400,0x61009519,0x7c00500, -0x22040f,0x61009b71,0x2802100,0x962460,0x61009b71,0x2806400,0x962460,0x61009b71,0x7c00100,0x230400,0x6100a008,0x2802100,0x962460,0x6100c300,0x4000000,0x20000f, -0x6100cd00,0x4000000,0x200000,0x6100d202,0x2802400,0x962460,0x6100d202,0x2802500,0x962460,0x6100d202,0x7c00100,0x230400,0x6100d302,0x4000020,0x200000,0x6100d302, -0x7c00120,0x230405,0x6100d476,0x2802100,0x962460,0x6100d476,0x2802100,0x962461,0x6100d476,0x2806400,0x962460,0x6100d476,0x4000000,0x400000,0x6100d476,0x6800000, -0x1329800,0x6100d476,0x6800100,0x962540,0x6100d476,0x7c00100,0x230400,0x6100d476,0xc000010,0x448000,0x6100d573,0x2802100,0x962460,0x6100d573,0x2806400,0x962460, -0x6100d573,0x6800100,0x962540,0x6100d573,0x7c00100,0x230400,0x6100d573,0x7c00900,0x230400,0x6100d573,0xc000010,0x448000,0x6100d68d,0x7c00100,0x230400,0x6100d756, -0x7c00100,0x230400,0x6100d85c,0x2802500,0x962460,0x6100d85c,0x6800100,0x962540,0x6100d85c,0x7c00100,0x230400,0x6100d85c,0x7c00500,0x230400,0x6100d997,0x2802100, -0x962460,0x6100d997,0x4000000,0x200000,0x6100d997,0x4000000,0x400000,0x6100d997,0x6800000,0x1329800,0x6100d997,0x6800100,0x962540,0x6100d997,0x6804400,0x962540, -0x6100d997,0x7c00100,0x230400,0x6100d997,0x7c00100,0x230560,0x6100d997,0xc000010,0x448000,0x6100da98,0x6800000,0x1329800,0x6100da98,0x7c00100,0x230400,0x6100db71, -0x4000000,0x200000,0x6100dc99,0x2802100,0x962460,0x6100dc99,0x2802400,0x962460,0x6100dc99,0x6800000,0x1329800,0x6100dc99,0x6800100,0x962540,0x6100dc99,0x6804400, -0x962540,0x6100dc99,0x7c00100,0x230400,0x610a4711,0x7c40300,0xe30000,0x610a4f11,0x7c00300,0xe30001,0x610ace00,0x4000000,0xe00000,0x6140afa1,0x7c00100,0x230400, -0x6140afa3,0x7c00100,0x230400,0x6180af9e,0x2802400,0x962460,0x62002a00,0x4000000,0x1600000,0x63002800,0x80000,0x918820,0x63c00c15,0x80000,0x918820,0x7000080e, -0x7c00100,0x250400,0x70000a03,0x4000000,0x200000,0x70000c00,0x80000000,0x218960,0x70000f0a,0x7c00100,0x230400,0x70001004,0x7c00100,0x230400,0x70001524,0x2802100, -0x962460,0x70001524,0x7c00100,0x230400,0x70001615,0x2802100,0x962460,0x7000171a,0x2802100,0x962460,0x70001821,0x6800000,0x1329800,0x70002320,0x7c00100,0x230400, -0x70002a00,0x4000000,0x1500000,0x70002a00,0x4000000,0x1600000,0x70003000,0x24000000,0x200000,0x70003800,0x24000000,0xe00000,0x70005201,0x2802400,0x962460,0x7000581e, -0x7c00100,0x230400,0x70006108,0x7c00100,0x220400,0x70006108,0x7c00100,0x250400,0x70006f30,0x7c00100,0x230400,0x70007300,0x24000000,0x200000,0x70007f0e,0x4000000, -0x200000,0x70008301,0x2802100,0x962460,0x70008301,0x2802400,0x962460,0x70008e00,0x24000000,0x200000,0x70008e00,0x24000000,0x400000,0x70008e00,0x24000002,0x400000, -0x70008e00,0x24000008,0x1410000,0x70008e00,0x24000010,0x400000,0x70008e00,0x2c000010,0x448000,0x70009519,0x7c00100,0x220400,0x70009519,0x7c00100,0x230400,0x70009519, -0x7c00100,0x250400,0x70009865,0x7c00100,0x230400,0x70009965,0x4000010,0x400000,0x70009965,0x7c00100,0x230400,0x7000a008,0x7c00100,0x220400,0x7000a008,0x7c00100, -0x250400,0x7000a008,0x7c00500,0x22040f,0x7000a50e,0x4000000,0x200000,0x7000b61c,0x2802500,0x1862460,0x7000b61c,0x6800500,0x1862400,0x7000b61c,0x7c00100,0x1830000, -0x7000c300,0x4000000,0x100000,0x7000c941,0x2806000,0x962460,0x7000cc00,0x4000000,0xe00000,0x7000cd00,0x4000000,0x200000,0x7000cd00,0x4000000,0xe00000,0x7000cd00, -0x4000000,0x2800000,0x7000cf00,0x4000000,0xe00000,0x7000d202,0x2802100,0x962460,0x7000d202,0x7c00100,0x230400,0x7000d997,0x7c00100,0x230400,0x7000d997,0xc000010, -0x248000,0x7000dd86,0x2802400,0x962460,0x7000dd86,0x7c00100,0x230400,0x7000dd86,0xc000010,0x448000,0x7000de9f,0x4000000,0x200000,0x7000de9f,0x7c00100,0x230400, -0x7000e001,0x2400,0x962460,0x7000e001,0x2802400,0x962460,0x7000e187,0x2802000,0x962460,0x7000e187,0x2802100,0x962460,0x7000e187,0x4000000,0x200000,0x7000e187, -0x7c00100,0x230400,0x7000e187,0xc000010,0x448000,0x7000e288,0x7c00100,0x230400,0x7000e300,0x4000000,0x200000,0x7000e489,0x2802100,0x962460,0x7000e489,0x2802400, -0x962460,0x7000e489,0x6800100,0x962540,0x7000e489,0x6800100,0x962541,0x7000e489,0x6804400,0x962540,0x7000e489,0x7c00100,0x230400,0x7000e489,0x7c00900,0x230400, -0x7000e59d,0x2802100,0x962460,0x7000e59d,0x2802400,0x962460,0x7000e59d,0x4000000,0x200000,0x7000e59d,0x4000010,0x200000,0x7000e59d,0x6800100,0x962540,0x7000e59d, -0x6804400,0x962540,0x7000e59d,0x7c00100,0x230400,0x7000e59d,0xc000010,0x448000,0x7000e691,0x2802100,0x962460,0x7000e691,0x2802400,0x962460,0x7000e691,0x2806400, -0x962460,0x7000e691,0x6800000,0x1329800,0x7000e691,0x6800100,0x962540,0x7000e691,0x7c00100,0x230400,0x7000e700,0x4000400,0x200400,0x7000e70e,0x7c00100,0x220400, -0x7000e719,0x7c00100,0x220400,0x7000e719,0x7c00500,0x22040f,0x7000e853,0x7c00100,0x230400,0x7000e9a0,0x2802400,0x962460,0x7000e9a0,0x4000000,0x200000,0x7000e9a0, -0x4000000,0x500000,0x7000e9a0,0x7c00100,0x230400,0x7000ea79,0x2802400,0x962460,0x7000ea79,0x4000000,0x200000,0x7000ea79,0x4000000,0xf00000,0x7000ea79,0x4000010, -0x400000,0x7000ea79,0x7c00100,0x230400,0x7000eb8c,0x2802400,0x962460,0x7000eb8c,0x4000000,0x200000,0x7000eb8c,0x7c00100,0x230400,0x7000eca3,0x2802100,0x962460, -0x7000eca3,0x2806400,0x962460,0x7000eca3,0x4000000,0x200000,0x7000eca3,0x6800000,0x1329800,0x7000eca3,0x6800100,0x962540,0x7000eca3,0x7c00100,0x230400,0x7000eca3, -0xc000010,0x448000,0x7000ed95,0x6800000,0x1329800,0x7000ed95,0x7c00100,0x230400,0x7000ed95,0xc000010,0x448000,0x7000ee1c,0x2802500,0x1862460,0x7000ee1c,0x6800000, -0x1329800,0x7000ee1c,0x7c00100,0x1830000,0x7000ee1c,0x7c00900,0x1830000,0x7000ef8f,0x4000000,0x200000,0x7000ef8f,0x7c00100,0x230400,0x7000f08e,0x4000000,0x200000, -0x7000f08e,0x7c00100,0x230400,0x7000f159,0x2802100,0x962460,0x7000f159,0x7c00100,0x230400,0x7000f200,0x4000000,0x200000,0x7000f200,0x4000000,0x1200000,0x7000f200, -0x4000000,0x1710000,0x7000f34b,0x2802400,0x962460,0x7000f34b,0x4000000,0x200000,0x7000f34b,0x4000010,0x400000,0x7000f34b,0x6800000,0x1329800,0x7000f34b,0x7c00100, -0x230400,0x7000f34b,0x7c00900,0x230400,0x7000f34b,0xc000010,0x448000,0x7000f490,0x4000000,0x200000,0x7000f490,0x7c00100,0x230400,0x7000f5a5,0x7c00100,0x230400, -0x7000f67b,0x4000000,0x200000,0x7000f67b,0x4000010,0x200000,0x7000f67b,0x7c00100,0x230400,0x7000f8a6,0x2802100,0x962460,0x7000f8a6,0x2802400,0x962460,0x7000f8a6, -0x2806400,0x962460,0x7000f8a6,0x4000000,0x500000,0x7000f8a6,0x4000010,0xb00000,0x7000f8a6,0x4000800,0x200000,0x7000f8a6,0x6800100,0x962540,0x7000f8a6,0x6800100, -0x962541,0x7000f8a6,0x7c00100,0x230400,0x7000f8a6,0xc000010,0x448000,0x7000f921,0x4000000,0x200000,0x7000fa00,0x4000000,0x200000,0x7000fb9e,0x2802100,0x962460, -0x7000fb9e,0x2802400,0x962460,0x7000fb9e,0x2806400,0x962460,0x7000fb9e,0x4000000,0x200000,0x7000fb9e,0x6800000,0x1329800,0x7000fb9e,0x6800100,0x962540,0x7000fb9e, -0x6800100,0x962541,0x7000fb9e,0x7c00100,0x230400,0x7000fc92,0x4000000,0x200000,0x7000fc92,0x6800000,0x1329800,0x7000fc92,0x7c00100,0x220400,0x7000fc92,0x7c00100, -0x230400,0x7000fc92,0x7c00100,0x250400,0x700acd00,0x4000000,0xe00000,0x700acd00,0x4000000,0x2800000,0x700ace00,0x4000000,0xe00000,0x700acf00,0x4000000,0xe00000, -0x700acf00,0x4000000,0x2800000,0x7050df11,0x4000000,0x200000,0x7050f719,0x80000,0x918820,0x7080afa1,0x2802400,0x962460,0x7090df11,0x2802400,0x962460,0x70d0e417, -0x2802100,0x962460,0x70d0e417,0x2802400,0x962460,0x70d0e417,0x6800100,0x962540,0x70d0ea15,0x4000010,0x400000,0x8000120f,0x7c00100,0x230400,0x80001524,0x7c00100, -0x230400,0x8000171a,0x7c00100,0x230400,0x80002006,0x7c00100,0x220400,0x80002006,0x7c00100,0x250400,0x80002a00,0x4000000,0x1500000,0x80002d00,0x4000000,0x200000, -0x80005208,0x2802400,0x962460,0x80005c00,0x4000000,0x200000,0x80007300,0x24000000,0x200000,0x80009519,0x7c00100,0x220400,0x80009519,0x7c00100,0x230400,0x80009519, -0x7c00100,0x250400,0x80009865,0x7c00100,0x230400,0x8000a008,0x2802100,0x962460,0x8000b30a,0x4000000,0x500000,0x8000b30a,0x7c00100,0x230400,0x8000cd00,0x4000000, -0xe00000,0x8000d202,0x2802500,0x962460,0x8000d202,0x7c00100,0x230400,0x8000d68d,0x4000000,0x200000,0x8000d997,0x2802000,0x962460,0x8000d997,0x2802400,0x962460, -0x8000d997,0x4000000,0x400000,0x8000d997,0x4000000,0x500000,0x8000d997,0x7c00100,0x230400,0x8000d997,0xc000010,0x448000,0x8000e489,0x2802100,0x962460,0x8000e489, -0x7c00100,0x230400,0x8000e719,0x7c00100,0x220400,0x8000f8a6,0x2802100,0x962460,0x8000f8a6,0x7c00100,0x230400,0x8000f8a6,0xc000010,0x448000,0x8000fda1,0x2802100, -0x1862460,0x8000fda1,0x2806400,0x1862460,0x8000fda1,0x4000000,0x1800000,0x8000fda1,0x6800000,0x1329800,0x8000fda1,0x6800100,0x1862400,0x8000fda1,0x6800100,0x1862540, -0x8000fda1,0x7c00100,0x1830000,0x8000fda1,0xc000010,0x448000,0x8000fe9c,0x7c00100,0x230400,0x8000fe9c,0x7c00100,0x830400,0x8000fe9c,0x7c00100,0x1430400,0x8000ff06, -0x7c00100,0x220400,0x80010165,0x7c00100,0x230400,0x800102a2,0x4000000,0x200000,0x800102a2,0x7c00100,0x230400,0x800103a4,0x7c00100,0x230400,0x800103a4,0xc000010, -0x448000,0x8001044c,0x4000000,0x200000,0x8001044c,0x7c00100,0x220400,0x8001044c,0x7c00100,0x250400,0x80010670,0x2802000,0x962460,0x80010670,0x4000000,0x200000, -0x80010670,0x4000010,0x400000,0x80010670,0xc000010,0x448000,0x800a4711,0x7c40300,0xe30000,0x800acd00,0x4000000,0xe00000,0x800acd00,0x4000000,0x2902460,0x800ace00, -0x4000000,0xe00000,0x800acf00,0x4000000,0xe00000,0x800b0011,0x7c40300,0xe30000,0x800b0500,0x4000000,0xe00000,0x800b0500,0x4000000,0x2800000,0x90001615,0x7c00100, -0x230400,0x9000171a,0x4000000,0x200000,0x9000171a,0x7c00100,0x230400,0x90003000,0x24000000,0x200000,0x90007f0e,0x4000000,0x200000,0x90008301,0x2802400,0x962460, -0x90008e00,0x24000000,0x400000,0x90009519,0x7c00100,0x250400,0x9000a16f,0x2802100,0x962460,0x9000d200,0x80000000,0x218960,0x9000d202,0x2802000,0x962460,0x9000d202, -0x2802100,0x962460,0x9000d202,0x7c00100,0x230400,0x9000e59d,0x2802100,0x962460,0x90010500,0x4000000,0xe00000,0x900107a7,0x2802100,0x962460,0x900107a7,0x2802400, -0x962460,0x900107a7,0x2802c00,0x962460,0x900107a7,0x4000000,0x1400000,0x900107a7,0x6800000,0x1329800,0x900107a7,0x7c00100,0x220400,0x900107a7,0x7c00100,0x250400, -0x900108a8,0x2802100,0x962460,0x900108a8,0x2806400,0x962460,0x900108a8,0x4000000,0x200000,0x900108a8,0x4000000,0x400000,0x900108a8,0x4000010,0x400000,0x900108a8, -0x6800000,0x1329800,0x900108a8,0x6800100,0x962540,0x900108a8,0x7c00100,0x230400,0x900108a8,0xc000010,0x448000,0x90010908,0x7c00100,0x220400,0x90010a38,0x2802100, -0x962460,0x90010ca9,0x2802100,0x962460,0x90010ca9,0x4000000,0x500000,0x90010ca9,0x4000010,0xb00000,0x90010ca9,0x6800100,0x962540,0x90010ca9,0x7c00100,0x230400, -0x90010d1b,0x4000000,0x500000,0x90010eaa,0x2802100,0x962460,0x90010eaa,0x2802400,0x962460,0x90010eaa,0x2806400,0x962460,0x90010eaa,0x4000000,0x200000,0x90010eaa, -0x4000000,0x400000,0x90010eaa,0x4000010,0x400000,0x90010eaa,0x6800000,0x1329800,0x90010eaa,0x6800100,0x962540,0x90010eaa,0x7c00100,0x230400,0x90010eaa,0xc000010, -0x448000,0x90010fab,0x7c00100,0x220400,0x90010fab,0x7c00100,0x250400,0x9002c300,0x4000000,0x100000,0x900ac400,0x4000000,0xe0000d,0x900acd00,0x4000000,0xe00000, -0x900acd00,0x4000000,0x2800000,0x900acf00,0x4000000,0xe00000,0x900b0500,0x4000000,0xe00000,0x900b0500,0x4000000,0x2800000,0x900b0b9a,0x7c00900,0x1230400,0x900b109a, -0x7c00300,0xe30000,0x900b119a,0x7c00300,0xe30000,0x90408e06,0x24000000,0x400000,0xa0001004,0x4000000,0x200000,0xa0001004,0x7c00100,0x230400,0xa000120f,0x2802100, -0x962460,0xa000120f,0x2802400,0x962460,0xa000171a,0x2802100,0x962460,0xa000171a,0x2806400,0x962460,0xa0002a00,0x4000000,0x1600000,0xa0003000,0x24000000,0x200000, -0xa000581e,0x7c00100,0x230400,0xa0007300,0x24000000,0x200000,0xa0008301,0x2802400,0x962460,0xa0008e00,0x24000000,0x400000,0xa000cf00,0x4000000,0xe00000,0xa0010500, -0x4000000,0x200000,0xa00114af,0x2802100,0x962460,0xa00114af,0x2802400,0x962460,0xa00114af,0x2806400,0x962460,0xa00114af,0x6800000,0x1329800,0xa00114af,0x7c00100, -0x230400,0xa00114af,0x7c00100,0x230560,0xa00116b0,0x2802100,0x962460,0xa00116b0,0x2802800,0x962460,0xa00116b0,0x2806400,0x962460,0xa00116b0,0x4000000,0x400000, -0xa00116b0,0x4000000,0x500000,0xa00116b0,0x4000010,0x400000,0xa00116b0,0x6800100,0x962540,0xa00116b0,0x7c00100,0x230400,0xa00116b0,0x7c00100,0x230560,0xa00116b0, -0xc000010,0x448000,0xa0011722,0x7c00100,0x230400,0xa00118b1,0x2802000,0x962460,0xa00118b1,0x2802100,0x962460,0xa00118b1,0x2806400,0x962460,0xa00118b1,0x4000000, -0x200000,0xa00118b1,0x4000000,0x400000,0xa00118b1,0x4000000,0x500000,0xa00118b1,0x6800100,0x962540,0xa00118b1,0x7c00100,0x230400,0xa00118b1,0x7c00100,0x230560, -0xa00118b1,0xc000010,0x448000,0xa00a4005,0x7c00100,0xe30400,0xa00a4711,0x7c40300,0xe30000,0xa00ac400,0x4000000,0xe00000,0xa00acb14,0x7c00100,0xe30000,0xa00acf00, -0x4000000,0xe00000,0xa00b0500,0x4000000,0xe00000,0xa00b0500,0x4000000,0x2800000,0xa00b0b96,0x7c00900,0x1230400,0xa00b1211,0x7c40300,0xe30000,0xa00b1314,0x7c00100, -0xe30000,0xa00b1596,0x7c00300,0xe30000,0xa040afb7,0x6800400,0x962540,0xa08083b8,0x2802400,0x962460,0xb0000a03,0x7c00100,0x220400,0xb0000b13,0x7c00100,0x2633800, -0xb0001004,0x2802000,0x962460,0xb0001110,0x4000000,0x200000,0xb0001524,0x2802100,0x962460,0xb0001615,0x4000000,0x500000,0xb000251b,0x7c00100,0x230400,0xb0007300, -0x24000000,0x200000,0xb0008939,0x4000000,0x200000,0xb0008939,0x7c00100,0x230400,0xb0008e00,0x24000000,0x200000,0xb0008e00,0x24000000,0x400000,0xb0008e00,0x24000010, -0x400000,0xb0009257,0x2802000,0x962460,0xb0009257,0x4000000,0x1600000,0xb0009519,0x7c00100,0x220400,0xb0009519,0x7c00100,0x250400,0xb0009a00,0x4000000,0x200000, -0xb000b30a,0x2802100,0x962460,0xb000b30a,0x7c00100,0x230400,0xb000c178,0x80000000,0x218960,0xb000c300,0x4000000,0x200000,0xb000d202,0x2802000,0x962460,0xb000d476, -0x6800100,0x962540,0xb000d476,0x7c00100,0x230400,0xb000e300,0x4000000,0xe00000,0xb000fda1,0x7c00100,0x1830000,0xb0010eaa,0x2802000,0x962460,0xb00116b0,0x7c00100, -0x230400,0xb0011900,0x4000000,0xe00000,0xb0011ab2,0x2802100,0x962460,0xb0011ab2,0x2802400,0x962460,0xb0011ab2,0x2806400,0x962460,0xb0011ab2,0x4000000,0x200000, -0xb0011ab2,0x6800100,0x962540,0xb0011ab2,0x7c00100,0x230400,0xb0011b0c,0x7c00100,0x230400,0xb0011cb3,0x2802100,0x962460,0xb0011cb3,0x2806400,0x962460,0xb0011cb3, -0x6800000,0x1329800,0xb0011cb3,0x6800100,0x962540,0xb0011cb3,0x7c00100,0x230400,0xb0011db6,0x2802500,0x962460,0xb0011db6,0x6800000,0x1329800,0xb0011db6,0x7c00100, -0x230400,0xb0011db6,0x7c00500,0x230400,0xb0011e00,0x4000000,0x200000,0xb0011e00,0x4000000,0x1500000,0xb0011fb4,0x2802100,0x962460,0xb0011fb4,0x6800100,0x962540, -0xb0011fb4,0x7c00100,0x230400,0xb0011fb4,0xc000010,0x248000,0xb0012000,0x4000000,0x200000,0xb00121b5,0x4000000,0x200000,0xb00121b5,0x4000010,0x400000,0xb00121b5, -0x7c00100,0x220400,0xb00121b5,0x7c00100,0x250400,0xb00121b5,0xc000010,0x448000,0xb00122b8,0x4000000,0x200000,0xb00122b8,0x7c00100,0x230400,0xb00123b7,0x2802400, -0x962460,0xb00123b7,0x4000000,0x200000,0xb00123b7,0x7c00100,0x230400,0xb00123b7,0xc000010,0x248000,0xb00a4005,0x7c00100,0xe30400,0xb00a4711,0x7c40300,0xe30000, -0xb00acf00,0x4000000,0xe00000,0xb00b0500,0x4000000,0xe00000,0xb00b0500,0x4000000,0x2800000,0xb00b109a,0x7c00300,0xe30000,0xb080e487,0x2802000,0x962460,0xc0001524, -0x4000000,0x500000,0xc0001a18,0x2806400,0x1862460,0xc0001a18,0x7c00100,0x1830000,0xc0007300,0x24000000,0x200000,0xc0008e00,0x24000010,0x400000,0xc0009519,0x7c00100, -0x220400,0xc0009519,0x7c00100,0x250400,0xc000c300,0x4000000,0x20000f,0xc000d85c,0x2802100,0x962460,0xc000d85c,0x6800100,0x962540,0xc000d85c,0x7c00100,0x230400, -0xc000dc99,0x7c00100,0x230400,0xc000e719,0x7c00100,0x220400,0xc00107a7,0x7c00100,0x230400,0xc0010eaa,0x7c00100,0x230400,0xc00116b0,0x7c00100,0x230560,0xc0011900, -0x4000000,0x200000,0xc0012447,0,0x818820,0xc0012447,0,0xc18820,0xc0012447,0,0x1418820,0xc00125b9,0x7c00100,0x230400,0xc00126bb,0x2802100, -0x962460,0xc00126bb,0x2806400,0x962460,0xc00126bb,0x4000000,0x500000,0xc00126bb,0x6800100,0x962540,0xc00126bb,0x7c00100,0x230400,0xc00127ba,0x2802400,0x962460, -0xc00127ba,0x4000000,0x200000,0xc00127ba,0x6800000,0x1329800,0xc00127ba,0x7c00100,0x230400,0xc00127ba,0x7c00900,0x230400,0xc0012800,0x4000000,0x200000,0xc0012b23, -0x4000000,0x200000,0xc0012b23,0x4000000,0x400000,0xc0012b23,0x4000000,0x1500000,0xc0012cbc,0x2802400,0x962460,0xc0012cbc,0x4000000,0x1600000,0xc0012cbc,0x6800000, -0x1329800,0xc0012cbc,0x7c00100,0x230400,0xc00acf00,0x4000000,0xe00000,0xc00ae300,0x4000000,0xe00000,0xc00b0500,0x4000000,0xe00000,0xc00b0500,0x4000000,0x2800000, -0xc00b0b11,0x4000000,0x1200000,0xc00b0b11,0x7c00900,0x1230400,0xc00b109a,0x7c00300,0xe30000,0xc00b2914,0x7c00100,0x2530000,0xc00b2916,0x7c00100,0x2530c00,0xc00b2a00, -0x4000000,0xe00000,0xc040af5e,0x7c00100,0x230400,0xc0c12b89,0x4000000,0x200000,0xc14a44ca,0x4000000,0xe0000d,0xd000131f,0x2802c00,0x962460,0xd000171a,0x7c00100, -0x230400,0xd0001821,0x2802100,0x962460,0xd0007300,0x24000000,0x200000,0xd0008e00,0x24000000,0x200000,0xd0008f3a,0x2806000,0x962460,0xd0009519,0x7c00100,0x220400, -0xd0009519,0x7c00100,0x250400,0xd000a500,0x4000000,0x200000,0xd000c300,0x4000000,0xe00000,0xd000d202,0x7c00100,0x230400,0xd000d476,0x7c00100,0x230400,0xd000d997, -0x2802100,0x962460,0xd000d997,0x6800100,0x962540,0xd000e001,0x2802100,0x962460,0xd000e700,0x4000400,0x200000,0xd000e719,0x7c00100,0x220400,0xd000e719,0x7c00500, -0x22040f,0xd000fa00,0x4000000,0xe00000,0xd0010eaa,0x4000010,0x400000,0xd0010eaa,0x7c00100,0x230400,0xd0012dbd,0x4000000,0x200000,0xd0012dbd,0x7c00100,0x230400, -0xd0012fbe,0x2802100,0x962460,0xd0012fbe,0x2802400,0x962460,0xd0012fbe,0x2806400,0x962460,0xd0012fbe,0x4000000,0x400000,0xd0012fbe,0x6800000,0x1329800,0xd0012fbe, -0x6800100,0x962540,0xd0012fbe,0x6800100,0x962541,0xd0012fbe,0x6804400,0x962540,0xd0012fbe,0x7c00100,0x230400,0xd0012fbe,0x7c00100,0x230560,0xd0012fbe,0xc000010, -0x448000,0xd0013183,0x7c00100,0x230400,0xd0013200,0x4000000,0x200000,0xd0013200,0x6800000,0x1329805,0xd00134c0,0x2802100,0x962460,0xd00134c0,0x4000002,0x400000, -0xd00134c0,0x7c00100,0x230400,0xd00a4305,0x7c00100,0xe30400,0xd00a4611,0x7c40300,0xe30000,0xd00a4711,0x7c40300,0xe30000,0xd00a5e11,0x7c40300,0xe30000,0xd00acf00, -0x4000000,0xe00000,0xd00b0500,0x4000000,0xe00000,0xd00b0500,0x4000000,0x2800000,0xd00b0b11,0x6800500,0x962540,0xd00b0bbf,0x2802200,0xc62460,0xd00b119a,0x7c00300, -0xe30000,0xd00b2a00,0x4000000,0xe00000,0xd00b2e11,0x7c40300,0xe30000,0xd00b30bf,0x7c00300,0x230000,0xd00b339a,0x7c00300,0xe30000,0xe0000c02,0xc000010,0xb48000, -0xe0001524,0x2802400,0x962460,0xe0001524,0x7c00100,0x230400,0xe0001615,0x7c00100,0x230400,0xe000251b,0x12882000,0x962460,0xe0002a00,0x4000000,0x1500000,0xe0005102, -0x4000000,0x200000,0xe0005c00,0x4000000,0x200000,0xe000622a,0x6804400,0x962540,0xe000622a,0x7c00100,0x230400,0xe0008838,0x7c00100,0x220400,0xe0008838,0x7c00100, -0x250400,0xe0008e00,0x24000000,0x810000,0xe0008e00,0x24000000,0x1410000,0xe0008e00,0x24000002,0x400000,0xe0008e00,0x2c000010,0xb48000,0xe000933e,0x7c00100,0x230400, -0xe000933e,0xc000010,0x448000,0xe0009519,0x7c00100,0x220400,0xe0009519,0x7c00100,0x22040f,0xe0009519,0x7c00100,0x250400,0xe000c178,0x2802100,0x962460,0xe000c941, -0x2802100,0x962460,0xe000c941,0x2806400,0x962460,0xe000c941,0x7c00100,0x230400,0xe000d202,0x2802400,0x962460,0xe000d202,0x7c00100,0x230400,0xe000d202,0x7c00500, -0x230400,0xe000dc99,0x4000000,0x200000,0xe000e001,0x2802100,0x962460,0xe000e001,0x2802400,0x962460,0xe000fda1,0x7c00100,0x1830000,0xe0013502,0x2802400,0x962460, -0xe0013502,0x4000000,0x200000,0xe0013502,0x7c00100,0x230400,0xe0013502,0x80000000,0x218960,0xe00136c1,0x4000000,0x200000,0xe00136c1,0x7c00100,0x230400,0xe001370b, -0x7c00100,0x230400,0xe0013919,0x7c00500,0x220400,0xe0013919,0x7c00500,0x22040f,0xe0013919,0x7c00d00,0x23040f,0xe0013a19,0x7c00100,0x220400,0xe0013a19,0x7c00100, -0x230400,0xe0013bc2,0x2802400,0x962460,0xe0013bc2,0x7c00100,0x230400,0xe0013bc2,0xc000010,0x248000,0xe0013cc3,0x6800000,0x1329800,0xe0013cc3,0x7c00100,0x230400, -0xe0013dc4,0x2802400,0x962460,0xe0013dc4,0x7c00100,0x230400,0xe0013e28,0x7c00100,0x230400,0xe0013fc5,0x7c00100,0x220400,0xe0013fc5,0x7c00100,0x250400,0xe0014000, -0x4000000,0x200000,0xe0014001,0x2802400,0x962460,0xe00a4711,0x7c40300,0xe30000,0xe00a5e11,0x7c40300,0xe30000,0xe00ac511,0x7c40300,0xe30000,0xe00acf00,0x4000000, -0xe00000,0xe00ae300,0x4000000,0xe00000,0xe00b0500,0x4000000,0xe00000,0xe00b1314,0x7c00100,0xe30000,0xe00b1316,0x7c00100,0xe30c00,0xe00b2a00,0x4000000,0xe00000, -0xe00b2a00,0x4000000,0x2800000,0xe00b3816,0x7c00500,0x230c00,0xe0808328,0x2802400,0x962460,0xf0001615,0x6800100,0x962540,0xf0001a18,0x2802000,0x1862460,0xf000c247, -0x7c00100,0x230400,0xf000d000,0x4000000,0xe00000,0xf000e300,0x4000000,0xe00000,0xf000e59d,0x2802100,0x962460,0xf000e59d,0x7c00100,0x230400,0xf0012447,0, -0x818820,0xf0012447,0,0xc18820,0xf0012447,0,0x1418820,0xf0012447,0x2802000,0x962460,0xf0012447,0x2802400,0x962460,0xf0012447,0x7c00100,0x230400, -0xf0013a19,0x7c00100,0x220400,0xf0014102,0x2802400,0x962460,0xf0014308,0x2802100,0x962460,0xf0014308,0x7c00500,0x22040e,0xf0014308,0x7c00500,0x22040f,0xf001440a, -0x4000000,0x500000,0xf0014500,0x4000000,0x200000,0xf00146c6,0x2802100,0x962460,0xf00146c6,0x2806000,0x962460,0xf00146c6,0x4000000,0xe00000,0xf00146c6,0x6800000, -0x1329800,0xf00146c6,0x6800100,0x962540,0xf00146c6,0x6804000,0x962540,0xf00146c6,0x7c00100,0x230400,0xf00146c6,0x7c00100,0x230560,0xf00146c6,0xc000010,0x448000, -0xf00147c7,0x2802000,0x962460,0xf00147c7,0x6800000,0x1329800,0xf00147c7,0x7c00100,0x230400,0xf00ac511,0x7c40300,0xe30000,0xf00acf00,0x4000000,0xe00000,0xf00b2914, -0x7c00100,0x2530000,0xf00b2916,0x7c00100,0x2530c00,0xf00b2a00,0x4000000,0xe00000,0xf00b2a00,0x4000000,0x2800000,0xf00b4211,0x7c40300,0xe30000}; +0x1200000,0x30002417,0x6800000,0x1329800,0x30002417,0x6800100,0x1862540,0x30002417,0x7c00100,0x1830000,0x30002417,0x7d00100,0x1830000,0x30002417,0xc000010,0x448000, +0x3000251b,0x80000,0xc18820,0x3000251b,0x2802100,0x962460,0x3000251b,0x3c02100,0x962460,0x3000251b,0x4000000,0x200000,0x3000251b,0x4000006,0x500000,0x3000251b, +0x4000010,0x400000,0x3000251b,0x4000010,0xb70000,0x3000251b,0x4000800,0x200000,0x3000251b,0x6800000,0x1329800,0x3000251b,0x7c00100,0x230400,0x3000251b,0x7c00900, +0x230400,0x3000251b,0xc000010,0xb48000,0x3000251b,0x12882000,0x962460,0x30002800,0x24000000,0x200000,0x30002800,0x2c000010,0x1248002,0x30002a00,0x4000000,0x1600000, +0x30002b01,0x2000,0x962460,0x30002c00,0x4000000,0x200000,0x30002c00,0x7c00100,0x220405,0x30002d19,0x7c00100,0x250400,0x30002e00,0x24000000,0x200000,0x30003000, +0x24000000,0x200000,0x30003100,0x24000000,0x200000,0x30003600,0x24000000,0x200000,0x30003700,0x24000000,0x200000,0x3000392e,0x24000000,0x200000,0x30005013,0x7c00100, +0x2633801,0x30005600,0,0x918820,0x30020600,0x4000400,0x500400,0x30020701,0x2802400,0x962460,0x30020701,0x2802400,0xc62460,0x300a3a11,0x4020000,0xe00000, +0x300a3a11,0x4020000,0xe00002,0x300a3b11,0x4020000,0xe00002,0x300a3c00,0x4008000,0xe00000,0x300a3c00,0x4010000,0xe00000,0x300a3d11,0x7c00300,0xe30002,0x300a4305, +0x7c00100,0xe30400,0x300a4611,0x7c40300,0xe30000,0x300a4829,0x7c00100,0xe30400,0x300a4829,0x7c00900,0x1230400,0x300a4929,0x4000000,0xe00000,0x3040259a,0x4000010, +0x400000,0x3040259a,0x4000010,0xb70000,0x3040259a,0xc000010,0xb48000,0x304028bc,0x4000001,0xc41c0b,0x304a3dcc,0x4000000,0xe00000,0x30800c27,0x2802100,0x962460, +0x30c01c92,0x6800000,0x1329800,0x3100080e,0x7c00120,0x220402,0x3100080e,0x7c00120,0x250402,0x31005167,0x1000,0,0x3100581e,0x4000000,0x200000,0x3100581e, +0x7c00100,0x230400,0x3100590d,0x7c00100,0x230400,0x31005a09,0x7c00100,0x220400,0x31005a09,0x7c00100,0x250400,0x31005b00,0x4000000,0x200000,0x31005c00,0x80000, +0x918820,0x31005c00,0x2802000,0x962460,0x31005c00,0x2802400,0x962460,0x31005c00,0x4000000,0x200000,0x31005c00,0x4000000,0x200001,0x31005c00,0x6800000,0x962540, +0x31005c00,0x6800400,0x962540,0x31005c01,0x2802400,0x962460,0x31005d00,0x4000020,0x200005,0x31005d00,0x6800020,0x1329805,0x31005d00,0x7c00120,0x220405,0x31005d00, +0x7c00120,0x250405,0x31006000,0x82000,0x962460,0x31006000,0x180000,0x918820,0x310a5e11,0x7c40300,0xe30000,0x310a5f11,0x7c00300,0xe30001,0x32000419,0x7c00100, +0x250400,0x3200080e,0x4000020,0x200000,0x3200080e,0x7c00100,0x220400,0x3200080e,0x7c00100,0x250400,0x32000908,0x7c00100,0x220400,0x32000908,0x7c00100,0x250400, +0x32000c02,0x7c00100,0x230400,0x32000e25,0x7c00100,0x230400,0x32001d0c,0x7c00100,0x230400,0x32002800,0x80000,0x1e18820,0x32002800,0x80020,0x218820,0x32002800, +0x4000001,0x445802,0x32002800,0x24000000,0x200000,0x32002800,0x24000000,0x1500002,0x32002800,0x24000020,0x200000,0x32002800,0x2c000010,0x1248002,0x32002919,0x7c00100, +0x22040f,0x32002a00,0x4000000,0x1600000,0x32002b01,0x2000,0x962460,0x32002b01,0x2802000,0x962460,0x32002b01,0x2802020,0x962460,0x32002c00,0x4000000,0x200000, +0x32002c00,0x4000020,0x200000,0x32002c00,0x4000020,0x200005,0x32002c00,0x7c00120,0x220405,0x32002c00,0x7c00120,0x250405,0x32002e00,0x24000020,0x200000,0x32002f00, +0x24000020,0x200000,0x32003000,0x24000000,0x200000,0x32003000,0x24000020,0x200000,0x32003500,0x24000000,0x200000,0x32003600,0x24000020,0x200000,0x32003700,0x24000000, +0x100000,0x32003700,0x24000000,0x200000,0x32003800,0x24000000,0x810000,0x32003800,0x24000000,0x1410000,0x32005102,0x4000000,0x1500008,0x32005502,0x7c00100,0x230400, +0x32006108,0x7c00100,0x220400,0x32006108,0x7c00100,0x250400,0x3200622a,0x2802100,0x962460,0x3200622a,0x2806400,0x962460,0x3200622a,0x7c00100,0x230400,0x3200632b, +0x2802100,0x962460,0x3200632b,0x6804000,0x962540,0x3200632b,0x7c00100,0x230400,0x3200642c,0x2802100,0x962460,0x3200642c,0x7c00100,0x230400,0x3200652d,0x2802100, +0x962460,0x3200652d,0x7c00100,0x230400,0x32006600,0x24000020,0x200000,0x32006700,0x24000020,0x200000,0x32006800,0x24000020,0x200000,0x32006900,0x24000020,0x200000, +0x32006900,0x24000020,0x810000,0x32006900,0x24000020,0x1410000,0x32006a00,0x24000020,0x200000,0x32006a00,0x24000020,0x200001,0x32006a00,0x24000020,0x200002,0x32020701, +0x2882000,0xc62460,0x32023300,0x4000000,0x100000,0x32026c01,0x12882000,0x962460,0x32065700,0x4000000,0x810011,0x32065700,0x4000000,0x1410011,0x32086600,0x24000020, +0x810000,0x32086600,0x24000020,0x1410000,0x32086900,0x24000020,0x810000,0x32086900,0x24000020,0x1410000,0x320a3600,0x24000020,0x200000,0x320a3d11,0x7c00100,0x1230400, +0x320a3e14,0x7c00100,0xe30010,0x320a3e14,0x7c00100,0x2530000,0x320a3f16,0x7c00100,0xe30c10,0x320a4400,0x4000000,0xe00003,0x320a4929,0x4000000,0xe00000,0x320a4f11, +0x7c00300,0xe30001,0x320a6b16,0x7c00100,0x2530c00,0x32406396,0xc000010,0x448000,0x324a3dcf,0x4000000,0xe00000,0x324a3dcf,0x7c00100,0x1230400,0x324a3fca,0x4000002, +0x1200c00,0x324a53c7,0x24000000,0xe00000,0x32820701,0x2802000,0x962460,0x40000419,0x7c00100,0x220400,0x40000519,0x7c00100,0x220400,0x40000600,0x4000400,0x200400, +0x4000080e,0x7c00100,0x220400,0x4000080e,0x7c00100,0x250400,0x4000080e,0x7c00100,0x250402,0x40000c02,0x2802100,0x962460,0x40000c02,0x2802400,0x962460,0x40000c02, +0x2802500,0x962460,0x40000c02,0x4000000,0x200000,0x40000c02,0x4000000,0x1071400,0x40000c02,0x7c00100,0x230400,0x40000c02,0x80000000,0x1329960,0x40000d22,0x7c00100, +0x230400,0x40000f0a,0x7c00100,0x230400,0x40001004,0x7c00100,0x230400,0x40001110,0x2802100,0x962460,0x40001110,0x6800100,0x962540,0x4000120f,0x2802100,0x962460, +0x4000120f,0x4000000,0x1600000,0x4000120f,0x7c00100,0x230400,0x4000131f,0x7c00100,0x230400,0x40001423,0x4000000,0x200000,0x40001423,0x4000000,0x1600000,0x40001615, +0x2802400,0x962460,0x40001615,0x7c00100,0x230400,0x40002417,0x2802400,0x1862460,0x40002417,0x4000000,0x200000,0x40002800,0x6800000,0x201c00,0x40002800,0x24000002, +0x200000,0x40002c00,0x4000000,0x200002,0x40003000,0x24000000,0x200000,0x40003000,0x24000020,0x200000,0x40003700,0x24000000,0x200000,0x40005a09,0x7c00100,0x220400, +0x40005a09,0x7c00100,0x250400,0x40005d00,0x7c00120,0x220405,0x40006f30,0x2802100,0x962460,0x40006f30,0x2802400,0x962460,0x40006f30,0x4000000,0x200000,0x40006f30, +0x6800000,0x1329800,0x40006f30,0x6800100,0x962540,0x40006f30,0x7c00100,0x230400,0x40006f30,0xc000010,0xb48000,0x40007034,0x7c00100,0x1830000,0x40007117,0x4000000, +0x200000,0x40007208,0x7c00100,0x220400,0x4000720e,0x7c00100,0x220400,0x4000720e,0x7c00500,0x22040e,0x4000720e,0x7c00500,0x22040f,0x40007219,0x7c00100,0x220400, +0x40007219,0x7c00500,0x220400,0x40007219,0x7c00500,0x22040e,0x40007219,0x7c00500,0x22040f,0x40007300,0x24000000,0x200000,0x40007400,0x4000000,0x200000,0x40007531, +0x7c00100,0x230400,0x40007631,0x7c00100,0x230400,0x40007835,0x4000010,0x400000,0x40007835,0x7c00100,0x230400,0x40007933,0x7c00100,0x230400,0x40007a32,0x6800000, +0x1329800,0x40007a32,0x7c00100,0x230400,0x40007b2f,0x7c00100,0x230400,0x40007c00,0x4000000,0x200000,0x40020701,0x2802400,0x962460,0x40020701,0x2802400,0xc62460, +0x40023300,0x4000000,0x200000,0x40027d01,0x12882000,0x962460,0x400a3700,0x24000000,0x200000,0x400a3700,0x24000000,0xe00000,0x400a4400,0x4000000,0xe0000d,0x400a4412, +0x4000000,0xe00002,0x400a4412,0x4000000,0xe00003,0x400a4500,0x4000000,0xe0000d,0x400a5300,0x4000000,0x810010,0x400a5300,0x4000000,0x1410010,0x40507719,0x4000000, +0x200000,0x4050771c,0x4000000,0x400000,0x4050771f,0x4000000,0x200000,0x4050771f,0x4000000,0x400000,0x40c01489,0x4000000,0x200000,0x40d05117,0x4000000,0x200000, +0x41000419,0x7c00100,0x220400,0x41000419,0x7c00100,0x250400,0x4100080e,0x7c00100,0x220400,0x4100080e,0x7c00100,0x250400,0x41000908,0x7c00100,0x220400,0x41000908, +0x7c00100,0x250400,0x41000b13,0x2802000,0x962460,0x41000b13,0x2802100,0x962460,0x41000b13,0x4000000,0xb00000,0x41000c02,0x2802100,0x962460,0x41000c02,0x4000000, +0x1500000,0x41000c02,0xc000010,0xb48000,0x41000f0a,0x7c00100,0x230400,0x41001004,0x7c00100,0x230400,0x41001423,0x7c00100,0x230400,0x41001b27,0x4000000,0x500000, +0x41001d0c,0x7c00100,0x22040f,0x41001d0c,0x7c00100,0x230400,0x41001f0b,0x2802400,0x962460,0x41001f0b,0x4000000,0x200000,0x41001f0b,0x7c00100,0x230400,0x41002800, +0x24000000,0x200000,0x41002800,0x24000000,0x400000,0x41002919,0x7c00100,0x22040e,0x41002a00,0x4000000,0x1600000,0x41002b01,0x2802020,0x962460,0x41002c00,0x4000000, +0x200000,0x41002c00,0x7c00120,0x220405,0x41003000,0x24000000,0x200000,0x41003700,0x24000000,0x200000,0x41003700,0x24000000,0xe00000,0x41005d00,0x7c00120,0x220405, +0x41006600,0x24000020,0x200000,0x41006600,0x24000020,0x810000,0x41006600,0x24000020,0x1410000,0x41007208,0x7c00100,0x22040f,0x41007219,0x7c00100,0x220400,0x41007300, +0x24000000,0x200000,0x41007e0e,0x2802000,0x962460,0x41007e0e,0x4000000,0x200000,0x41007f0e,0x4000000,0x200000,0x41007f0e,0x7c00100,0x230400,0x41008002,0x7c00100, +0x230400,0x41008137,0x2802100,0x962460,0x41008137,0x4000000,0x200000,0x41008137,0x6800100,0x962540,0x41008137,0x7c00100,0x230400,0x41008301,0x2802000,0x962460, +0x41008407,0x4000000,0x200000,0x41008407,0x4000000,0x400000,0x41008407,0x4000000,0xb00000,0x41008407,0x7c00100,0x220400,0x41008407,0x7c00100,0x250400,0x4100850b, +0x7c00100,0x230400,0x4100860b,0x4000000,0x200000,0x4100860b,0x7c00100,0x230400,0x4100870c,0x7c00100,0x220400,0x41008838,0x7c00100,0x220400,0x41008838,0x7c00100, +0x250400,0x41008939,0x2802000,0x962460,0x41008939,0x2802100,0x962460,0x41008939,0x2806000,0x962460,0x41008939,0x4000000,0x200000,0x41008939,0x4000000,0x400000, +0x41008939,0x7c00100,0x230400,0x41008939,0xc000010,0x448000,0x41008a00,0x4000400,0x200400,0x41008b3b,0x4000000,0x1800000,0x41008b3b,0x6800000,0x1329800,0x41008b3b, +0x7c00100,0x1830000,0x41008b3b,0x7e00100,0x1830000,0x41008c3d,0x4000010,0x400000,0x41008c3d,0x7c00100,0x230400,0x41008d0e,0x7c00100,0x22040f,0x41008d19,0x7c00100, +0x220400,0x41008d19,0x7c00100,0x22040f,0x41008e00,0x24000000,0x200000,0x41008e00,0x24000000,0x400000,0x41008e00,0x24000000,0x1710000,0x41008e00,0x24000006,0x400000, +0x41008f3a,0x2802100,0x962460,0x41008f3a,0x2806000,0x962460,0x41008f3a,0x4000000,0x200000,0x41008f3a,0x6800100,0x962540,0x41008f3a,0x7c00100,0x230400,0x4100903c, +0x7c00100,0x230400,0x4100903c,0x7c00100,0x23040f,0x41020701,0x2802000,0x962460,0x41020701,0x2802000,0xc62460,0x410a3700,0x24000000,0x200000,0x410a3700,0x24000000, +0xe00000,0x410a4412,0x4000000,0xe00003,0x410a4711,0x7c40300,0xe30000,0x410a4f11,0x7c00300,0xe30001,0x410a9100,0x4000000,0x800010,0x410a9100,0x4000000,0x810010, +0x410a9100,0x4000000,0x870010,0x410a9100,0x4000000,0xb00010,0x410a9100,0x4000000,0xf00010,0x410a9100,0x4000000,0x1001410,0x410a9100,0x4000000,0x1071010,0x410a9100, +0x4000000,0x1071410,0x410a9100,0x4000000,0x1410010,0x41408ad2,0x4000400,0x200000,0x414a82cc,0x4000000,0xe00000,0x41808300,0x2802000,0x962460,0x41c01489,0x6800000, +0x1329800,0x50000419,0x7c00100,0x220400,0x50000419,0x7c00100,0x250400,0x5000080e,0x7c00100,0x220400,0x50000908,0x7c00100,0x220400,0x50000908,0x7c00100,0x250400, +0x50000b13,0x2802500,0x962460,0x50000f0a,0x7c00100,0x230400,0x50001615,0x2802100,0x962460,0x50001615,0x7c00100,0x230400,0x50002b01,0x2802020,0x962460,0x50002c00, +0x4000000,0x200000,0x50002c19,0x7c00100,0x220400,0x50002d19,0x7c00100,0x220400,0x50003000,0x24000000,0x200000,0x50003000,0x24000020,0x200000,0x50003700,0x24000000, +0x200000,0x50005d00,0x7c00120,0x220405,0x50005d00,0x7c00120,0x250405,0x50006108,0x7c00100,0x220400,0x50006108,0x7c00100,0x250400,0x50006600,0x24000020,0x200000, +0x50007300,0x24000000,0x200000,0x50008301,0x2802400,0x962460,0x50008a00,0x7c00500,0x230400,0x50009257,0x2802400,0x962460,0x50009257,0x4000000,0x200000,0x50009257, +0x4000010,0x1071400,0x50009257,0x6800000,0x1329800,0x50009257,0x7c00100,0x230400,0x50009257,0x7c00500,0x230400,0x50009257,0x7c00900,0x230400,0x50009257,0xc000010, +0xb48000,0x5000933e,0x2802100,0x962460,0x5000933e,0x2802400,0x962460,0x5000933e,0x4000000,0x400000,0x5000933e,0x4000000,0xe00000,0x5000933e,0x4000010,0x400000, +0x5000933e,0x6800000,0xe29800,0x5000933e,0x6800100,0x962540,0x5000933e,0x6800100,0x962541,0x5000933e,0x6804400,0x2f62540,0x5000933e,0x7c00100,0x2b30400,0x5000933e, +0x7c00100,0x2b30401,0x5000933e,0xc000010,0x448000,0x50009419,0x7c00100,0x220400,0x50009419,0x7c00100,0x250400,0x50009500,0x4000400,0x200400,0x5000965a,0x4000000, +0x500000,0x5000965a,0x7c00100,0x230400,0x5000965a,0xc000010,0xb48000,0x5000975b,0x4000000,0x200000,0x5000975b,0x4000010,0x400000,0x5000975b,0x7c00100,0x230400, +0x50009865,0x7c00100,0x230400,0x50009965,0x4000010,0x400000,0x50009965,0x7c00100,0x230400,0x50409acc,0x4000000,0x200000,0x5100080e,0x7c00100,0x220400,0x5100080e, +0x7c00100,0x250400,0x51000c02,0x2802100,0x962460,0x51000c02,0x4000000,0x1500000,0x51000c02,0x4000020,0x200000,0x51000c02,0x7c00100,0x230400,0x51000f0a,0x7c00100, +0x230400,0x51000f0a,0x7c00500,0x230400,0x51001110,0x2802100,0x962460,0x5100131f,0x2802100,0x962460,0x51001423,0x7c00100,0x230400,0x51001524,0x2802100,0x962460, +0x51001524,0x4000000,0x200000,0x51001524,0x7c00100,0x230400,0x5100171a,0x2802100,0x962460,0x5100171a,0x4000000,0x200000,0x5100171a,0x4000000,0x1500000,0x5100171a, +0x7c00100,0x230400,0x51001b27,0x4000000,0x200000,0x51001b27,0x4000000,0x400000,0x51001b27,0x4000000,0x500000,0x51001b27,0x7c00100,0x230400,0x51001c1c,0x2802100, +0x1862460,0x51001c1c,0x2802500,0x1862460,0x51001c1c,0x2806400,0x1862460,0x51001c1c,0x4000000,0x1800000,0x51001c1c,0x6800000,0x1329800,0x51001c1c,0x6800100,0x1862400, +0x51001c1c,0x6800100,0x1862540,0x51001c1c,0x6800500,0x1862400,0x51001c1c,0x7c00100,0x1830000,0x5100251b,0x7c00100,0x230400,0x51002619,0x7c00100,0x220400,0x51002619, +0x7c00100,0x250400,0x51002800,0x80020,0x218820,0x51002c00,0x4000000,0x200000,0x51002d19,0x7c00100,0x230400,0x51003700,0x24000000,0x200000,0x51003700,0x24000000, +0xe00000,0x51005201,0x2802400,0x962460,0x51005c00,0x4000000,0x200000,0x51006108,0x7c00100,0x220400,0x51006108,0x7c00100,0x250400,0x51006600,0x24000020,0x200000, +0x51006600,0x24000020,0x810000,0x51006600,0x24000020,0x1410000,0x51007300,0x24000000,0x200000,0x51007300,0x24000020,0x200000,0x51008002,0x7c00100,0x230400,0x51008301, +0x2802000,0x962460,0x51008301,0x2802400,0x962460,0x51008301,0x2802400,0xc62460,0x51008a00,0x7c00500,0x230400,0x51008e00,0x24000000,0x200000,0x51008e00,0x24000000, +0x400000,0x51008e00,0x24000000,0x810000,0x51008e00,0x24000000,0x1400000,0x51008e00,0x24000000,0x1410000,0x51008e00,0x24000000,0x1710000,0x51008e00,0x24000002,0x200000, +0x51008e00,0x24000500,0x230400,0x51008e00,0x2c000010,0xb48000,0x51009419,0x7c00100,0x220400,0x51009419,0x7c00100,0x22040e,0x51009419,0x7c00100,0x22040f,0x51009419, +0x7c00100,0x250400,0x51009500,0x4000400,0x200400,0x51009500,0x7c00500,0x230400,0x51009519,0x7c00100,0x220400,0x51009519,0x7c00100,0x22040f,0x51009519,0x7c00100, +0x230400,0x51009519,0x7c00100,0x250400,0x51009b71,0x2802100,0x962460,0x51009b71,0x6800000,0x1329800,0x51009b71,0x6800100,0x962540,0x51009b71,0x6804400,0x962540, +0x51009b71,0x7c00100,0x230400,0x51009c52,0x2802100,0x962460,0x51009c52,0x2802400,0x962460,0x51009c52,0x2802d00,0x962460,0x51009c52,0x4000010,0x400000,0x51009c52, +0x6800000,0x1329800,0x51009c52,0x6800100,0x962540,0x51009c52,0x7c00100,0x230400,0x51009c52,0xc000010,0x448000,0x51009d6d,0x6800000,0x1329800,0x51009d6d,0x7c00100, +0x230400,0x51009d6d,0x7c00500,0x230400,0x51009d6d,0x7c00d00,0x230400,0x51009d6d,0xc000010,0x448000,0x51009e08,0x2802100,0x962460,0x51009f63,0x4000010,0x400000, +0x51009f63,0x6800000,0x1329800,0x51009f63,0x7c00100,0x230400,0x51009f63,0x7c00900,0x230400,0x51009f63,0xc000010,0x448000,0x51009f63,0xc000010,0xb48000,0x5100a008, +0x2000,0x962460,0x5100a008,0x2802400,0x962460,0x5100a008,0x4000000,0x200000,0x5100a008,0x7c00100,0x220400,0x5100a008,0x7c00100,0x230400,0x5100a008,0x7c00100, +0x250400,0x5100a008,0x7c00500,0x230400,0x5100a16f,0x2806400,0x962460,0x5100a16f,0x6800000,0x1329800,0x5100a16f,0x6800100,0x962540,0x5100a16f,0x7c00100,0x230400, +0x5100a16f,0xc000010,0x448000,0x5100a24f,0x2802100,0x962460,0x5100a24f,0x2802400,0x962460,0x5100a24f,0x6800000,0x1329800,0x5100a24f,0x7c00100,0x230400,0x5100a24f, +0xc000010,0x448000,0x5100a36e,0x2802100,0x962460,0x5100a36e,0x4000000,0x200000,0x5100a36e,0x6800100,0x962540,0x5100a36e,0x6804400,0x962540,0x5100a36e,0x7c00100, +0x230400,0x5100a442,0x2802100,0x962460,0x5100a442,0x4000000,0xe00000,0x5100a442,0x6800000,0xe29800,0x5100a442,0x6800100,0x962540,0x5100a442,0x7c00100,0x430400, +0x5100a442,0x7c00100,0x2d30400,0x5100a442,0xc000010,0x448000,0x5100a500,0x4000000,0x200000,0x5100a600,0x4000000,0x200000,0x5100a601,0x2802000,0x962460,0x5100a76b, +0x7c00100,0x230400,0x5100a868,0x7c00100,0x230400,0x5100a96c,0x4000000,0x200000,0x5100a96c,0x7c00100,0x230400,0x5100aa00,0x4000000,0xe00000,0x5100ab00,0x4000000, +0xe00000,0x51086600,0x24000020,0x810000,0x51086600,0x24000020,0x1410000,0x510a4005,0x7c00100,0xe30400,0x510a4711,0x7c40300,0xe30000,0x510a7300,0x24000000,0x200000, +0x510aaa00,0x4000000,0xe00000,0x514a82cc,0x4000000,0xe00000,0x5150a20e,0x4000400,0x400000,0x51802bbe,0x2802000,0x962460,0x51c00908,0x2802400,0x962460,0x51c0a008, +0x2802400,0x962460,0x52000f0a,0x2802100,0x962460,0x52000f0a,0x6800100,0x962540,0x52000f0a,0x7c00100,0x230400,0x52001004,0x4000000,0x1600000,0x52001b00,0x4000000, +0x200000,0x52001c1c,0x2802100,0x1862460,0x52001c1c,0x6800100,0x1862400,0x52001c1c,0x6800500,0x1862400,0x52001e12,0x7c00100,0x2230500,0x52001e12,0x7c00100,0x2330520, +0x52002128,0x4000002,0x400000,0x52002128,0x7c00100,0x230400,0x52002a00,0x4000000,0x1500000,0x52002a00,0x4000000,0x1600000,0x52002d00,0x4000000,0x200006,0x52003000, +0x24000000,0x200000,0x52006108,0x7c00100,0x220400,0x52006108,0x7c00100,0x250400,0x52008301,0x2802400,0x962460,0x52008407,0x2802400,0x962460,0x52008407,0x7c00100, +0x220400,0x52008407,0x7c00100,0x250400,0x52008b3b,0x6800000,0x1800000,0x52008b3b,0x7c00100,0x1830000,0x52008e00,0x24000000,0x400000,0x52009419,0x7c00100,0x250400, +0x5200975b,0x4000000,0x200000,0x5200ac7e,0x2802000,0x962460,0x5200ac7e,0x2802100,0x962460,0x5200ac7e,0x2802400,0x962460,0x5200ac7e,0x4000010,0x200000,0x5200ac7e, +0x7c00100,0x230400,0x5200ac7e,0xc000010,0x248000,0x5200ad28,0x7c00100,0x230400,0x5200ae6a,0x2802100,0x1862460,0x5200ae6a,0x2802400,0x962460,0x5200ae6a,0x2802400, +0x1862460,0x5200ae6a,0x2806000,0x1862460,0x5200ae6a,0x4000000,0x1800000,0x5200ae6a,0x6800000,0x1329800,0x5200ae6a,0x6800100,0x1862400,0x5200ae6a,0x6800100,0x1862540, +0x5200ae6a,0x7c00100,0x1830000,0x5200ae6a,0x7c00900,0x1830000,0x5200ae6a,0xc000010,0x1848000,0x5200b083,0x4000010,0x400000,0x5200b083,0x7c00100,0x230400,0x5200b083, +0xc000010,0x448000,0x5200b182,0x2802400,0x962460,0x5200b182,0x4000000,0x200000,0x5200b182,0x4000010,0x400000,0x5200b182,0x7c00100,0x230400,0x5200b182,0xc000010, +0x448000,0x5200b30a,0x2802400,0x962460,0x5200b30a,0x4000000,0x200000,0x5200b30a,0x7c00100,0x230400,0x5200b54e,0x2802100,0x962460,0x5200b54e,0x2802400,0x962460, +0x5200b54e,0x4000000,0xe00000,0x5200b54e,0x4000010,0x400000,0x5200b54e,0x6800000,0xe29800,0x5200b54e,0x6800100,0x962540,0x5200b54e,0x6804400,0x2f62540,0x5200b54e, +0x7c00100,0x2b30400,0x5200b54e,0xc000010,0x448000,0x5200b61c,0x4000000,0x1800000,0x5200b61c,0x6800500,0x1862400,0x5200b61c,0x7c00100,0x1830000,0x5200b61c,0x7c00900, +0x1830000,0x5200b77f,0x2802100,0x1862460,0x5200b77f,0x2802400,0x1862460,0x5200b77f,0x4000000,0x1800000,0x5200b77f,0x4000010,0x1800000,0x5200b77f,0x7c00100,0x1830000, +0x5200b77f,0x7c00500,0x1830000,0x5200b77f,0x7c00900,0x1830000,0x5200b77f,0x7e00100,0x1830000,0x5200b873,0x2802100,0x962460,0x5200b873,0x2806400,0x962460,0x5200b873, +0x6800000,0x1329800,0x5200b873,0x6800100,0x962540,0x5200b873,0x6800400,0x962540,0x5200b873,0x7c00100,0x230400,0x5200b873,0xc000010,0x448000,0x5200b912,0x7c00100, +0x2230500,0x5200b912,0x7c00100,0x2330520,0x5200ba74,0x4000000,0x200000,0x5200ba74,0x4000010,0x400000,0x5200ba74,0x7c00100,0x230400,0x5200bb85,0x4000000,0x200000, +0x5200bb85,0x7c00100,0x230400,0x5200bc75,0x4000000,0x400000,0x5200bc75,0x4000010,0x400000,0x5200bc75,0x7c00100,0x230400,0x5200bd7d,0x4000000,0x200000,0x5200bd7d, +0x7c00100,0x230400,0x5200be7a,0x4000000,0x200000,0x5200be7a,0x7c00100,0x230400,0x5200bf58,0x7c00100,0x230400,0x5200c002,0x4000000,0x200000,0x5200c178,0x2802100, +0x962460,0x5200c178,0x2802400,0x962460,0x5200c178,0x2806400,0x962460,0x5200c178,0x4000000,0x200000,0x5200c178,0x6800100,0x962540,0x5200c178,0x7c00100,0x230400, +0x5200c178,0x7c00100,0x230401,0x5200c178,0xc000010,0x448000,0x5200c178,0x80000000,0x1329960,0x5200c247,0x7c00100,0x230400,0x5200c247,0x7c00100,0x830400,0x5200c247, +0x7c00100,0x1430400,0x5200c300,0x4000000,0x200003,0x52022d00,0x4000000,0x100006,0x52023700,0x24000000,0x100000,0x52023700,0x24000000,0xe00000,0x52023700,0x24000000, +0x2800000,0x52024400,0x4000000,0x100000,0x52027300,0x24000000,0x100000,0x5202c300,0x4000000,0x100000,0x5202c300,0x4000000,0x100002,0x5202c300,0x4000000,0x100003, +0x5202c300,0x4000000,0x10000d,0x5202c300,0x4000100,0x150400,0x5202c300,0x4000100,0x15040d,0x520a1e12,0x7c00100,0x2130480,0x520a3700,0x24000000,0xe00000,0x520a3800, +0x24000000,0x100000,0x520a4711,0x7c40300,0xe30000,0x520a4f11,0x7c00300,0xe30001,0x520a7300,0x24000000,0x100000,0x520ab412,0x7c00100,0x2130480,0x520ac400,0x4000000, +0xe00002,0x520ac400,0x4000000,0xe0000d,0x520ac414,0x4000000,0xe0000d,0x520ac511,0x7c40300,0xe30000,0x5240af9c,0x7c00100,0x230400,0x5240afa1,0x4000400,0x200000, +0x5240afa3,0x6800400,0x962540,0x5240afa3,0x7c00100,0x230400,0x5240afad,0x7c00100,0x230400,0x5240afaf,0x7c00100,0x230400,0x5240b2d4,0x4000000,0x200000,0x5240b2e3, +0x4000000,0x200000,0x5240b2f1,0x4000000,0x200000,0x5240b2fc,0x4000000,0x1500000,0x524a44cc,0x4000000,0xe00003,0x5250b511,0x7c00900,0x430400,0x5280af9c,0x2802400, +0x962460,0x5280af9d,0x2802400,0x962460,0x5280afa3,0x2802400,0x962460,0x5280afa5,0x2802400,0x962460,0x5280afa7,0x2802400,0x962460,0x52d0b308,0x2802400,0x962460, +0x52d0b30c,0x7c00100,0x230400,0x60000c02,0x2802100,0x962460,0x60000c02,0x7c00100,0x230400,0x60000f0a,0x2802100,0x962460,0x60000f0a,0x6800100,0x962540,0x60000f0a, +0x7c00100,0x230400,0x6000131f,0x4000000,0x200000,0x6000171a,0x7c00100,0x230400,0x6000171a,0x7c00100,0x230560,0x60001b27,0x2802100,0x962460,0x60001b27,0x4000000, +0xc00000,0x60001b27,0x7c00100,0x230400,0x60001f0b,0x2802400,0x962460,0x60002919,0x7c00100,0x22040e,0x60002a00,0x4000000,0x1600000,0x60003000,0x24000000,0x200000, +0x60003000,0x24000000,0xe00000,0x60003700,0x24000000,0x200000,0x60003800,0x24000000,0x1710000,0x60005102,0x4000000,0x200000,0x60006108,0x7c00100,0x220400,0x60006108, +0x7c00100,0x250400,0x60006600,0x24000020,0x200000,0x60008301,0x2802400,0xc62460,0x6000903c,0x2806000,0x962460,0x6000903c,0x4000000,0x400000,0x60009519,0x7c00100, +0x220400,0x60009519,0x7c00100,0x250400,0x6000a008,0x7c00100,0x220400,0x6000a008,0x7c00100,0x250400,0x6000c300,0x4000000,0x2703580,0x6000c654,0x2802000,0x962460, +0x6000c654,0x4000010,0x200000,0x6000c654,0x7c00100,0x230400,0x6000c73f,0x2802000,0x962460,0x6000c73f,0x2802100,0x962460,0x6000c73f,0x4000000,0x200000,0x6000c73f, +0x6800100,0x962540,0x6000c73f,0x6804000,0x2e62540,0x6000c73f,0x7c00100,0x2d30400,0x6000c80b,0x7c00100,0x230400,0x6000c941,0x2802100,0x962460,0x6000c941,0x2806400, +0x2f62460,0x6000c941,0x4000000,0xe00000,0x6000c941,0x4000010,0xe00000,0x6000c941,0x6800000,0x2d29800,0x6000c941,0x6800100,0x962540,0x6000c941,0x7c00100,0x2b30400, +0x6000c941,0x7c00100,0x2c30400,0x6000c941,0xc000010,0x448000,0x6000ca82,0x7c00100,0x230400,0x6000cc00,0x4000000,0xe00000,0x6000d000,0x4000000,0x200000,0x6002c300, +0x4000000,0x100000,0x6002c300,0x4000000,0x10000d,0x6002c300,0x4000100,0x150400,0x6002c300,0x4000100,0x15040d,0x600a3000,0x24000000,0x200000,0x600a3000,0x24000000, +0xe00000,0x600a3700,0x24000000,0x200000,0x600a3800,0x24000000,0x200000,0x600a3800,0x24000000,0x2800000,0x600a4305,0x7c00100,0xe30400,0x600ac300,0x4000000,0x100000, +0x600ac400,0x4000000,0xe0000d,0x600acb14,0x7c00100,0xe30000,0x600acb16,0x7c00100,0xe30c00,0x600acc00,0x4000000,0xe00000,0x600acd00,0x4000000,0x200000,0x600acd00, +0x4000000,0xe00000,0x600acd00,0x4000000,0x2800000,0x600ace00,0x4000000,0xe00000,0x600ace00,0x4000000,0x2800000,0x600acf00,0x4000000,0xe00000,0x600acf00,0x4000000, +0x2800000,0x600ad111,0x7c40300,0xe30000,0x604ac4cc,0x4000000,0xe00003,0x61000a03,0x4000000,0x1600000,0x61000c02,0x80000000,0x1329960,0x6100120f,0x4000000,0x200000, +0x61001a18,0x7c00100,0x1830000,0x61001d0c,0x7c00100,0x230400,0x61001d0c,0x7c00100,0x250400,0x61006600,0x24000020,0x200000,0x61008407,0x7c00100,0x220400,0x61008407, +0x7c00100,0x250400,0x6100870c,0x7c00100,0x220400,0x61008e00,0x24000000,0x200000,0x61008e00,0x24000000,0x400000,0x61008e00,0x24000002,0x300000,0x6100903c,0x7c00100, +0x230400,0x61009519,0x7c00100,0x220400,0x61009519,0x7c00100,0x250400,0x61009519,0x7c00500,0x22040f,0x61009b71,0x2802100,0x962460,0x61009b71,0x2806400,0x962460, +0x61009b71,0x7c00100,0x230400,0x6100a008,0x2802100,0x962460,0x6100c300,0x4000000,0x20000f,0x6100cd00,0x4000000,0x200000,0x6100d202,0x2802400,0x962460,0x6100d202, +0x2802500,0x962460,0x6100d202,0x7c00100,0x230400,0x6100d302,0x4000020,0x200000,0x6100d302,0x7c00120,0x230405,0x6100d476,0x2802100,0x962460,0x6100d476,0x2802100, +0x962461,0x6100d476,0x2806400,0x962460,0x6100d476,0x4000000,0x400000,0x6100d476,0x6800000,0x1329800,0x6100d476,0x6800100,0x962540,0x6100d476,0x7c00100,0x230400, +0x6100d476,0xc000010,0x448000,0x6100d573,0x2802100,0x962460,0x6100d573,0x2806400,0x962460,0x6100d573,0x6800100,0x962540,0x6100d573,0x7c00100,0x230400,0x6100d573, +0x7c00900,0x230400,0x6100d573,0xc000010,0x448000,0x6100d68d,0x7c00100,0x230400,0x6100d756,0x7c00100,0x230400,0x6100d85c,0x2802500,0x962460,0x6100d85c,0x6800100, +0x962540,0x6100d85c,0x7c00100,0x230400,0x6100d85c,0x7c00500,0x230400,0x6100d997,0x2802100,0x962460,0x6100d997,0x4000000,0x200000,0x6100d997,0x4000000,0x400000, +0x6100d997,0x6800000,0x1329800,0x6100d997,0x6800100,0x962540,0x6100d997,0x6804400,0x962540,0x6100d997,0x7c00100,0x230400,0x6100d997,0x7c00100,0x230560,0x6100d997, +0xc000010,0x448000,0x6100da98,0x6800000,0x1329800,0x6100da98,0x7c00100,0x230400,0x6100db71,0x4000000,0x200000,0x6100dc99,0x2802100,0x962460,0x6100dc99,0x2802400, +0x962460,0x6100dc99,0x6800000,0x1329800,0x6100dc99,0x6800100,0x962540,0x6100dc99,0x6804400,0x962540,0x6100dc99,0x7c00100,0x230400,0x610a4711,0x7c40300,0xe30000, +0x610a4f11,0x7c00300,0xe30001,0x610ace00,0x4000000,0xe00000,0x6140afa1,0x7c00100,0x230400,0x6140afa3,0x7c00100,0x230400,0x6180af9e,0x2802400,0x962460,0x62002a00, +0x4000000,0x1600000,0x63002800,0x80000,0x918820,0x63c00c15,0x80000,0x918820,0x7000080e,0x7c00100,0x250400,0x70000a03,0x4000000,0x200000,0x70000c00,0x80000000, +0x1329960,0x70000f0a,0x7c00100,0x230400,0x70001004,0x7c00100,0x230400,0x70001524,0x2802100,0x962460,0x70001524,0x7c00100,0x230400,0x70001615,0x2802100,0x962460, +0x7000171a,0x2802100,0x962460,0x70001821,0x6800000,0x1329800,0x70002320,0x7c00100,0x230400,0x70002a00,0x4000000,0x1500000,0x70002a00,0x4000000,0x1600000,0x70003000, +0x24000000,0x200000,0x70003800,0x24000000,0xe00000,0x70005201,0x2802400,0x962460,0x7000581e,0x7c00100,0x230400,0x70006108,0x7c00100,0x220400,0x70006108,0x7c00100, +0x250400,0x70006f30,0x7c00100,0x230400,0x70007300,0x24000000,0x200000,0x70007f0e,0x4000000,0x200000,0x70008301,0x2802100,0x962460,0x70008301,0x2802400,0x962460, +0x70008e00,0x24000000,0x200000,0x70008e00,0x24000000,0x400000,0x70008e00,0x24000002,0x400000,0x70008e00,0x24000008,0x1410000,0x70008e00,0x24000010,0x400000,0x70008e00, +0x2c000010,0x448000,0x70009519,0x7c00100,0x220400,0x70009519,0x7c00100,0x230400,0x70009519,0x7c00100,0x250400,0x70009865,0x7c00100,0x230400,0x70009965,0x4000010, +0x400000,0x70009965,0x7c00100,0x230400,0x7000a008,0x7c00100,0x220400,0x7000a008,0x7c00100,0x250400,0x7000a008,0x7c00500,0x22040f,0x7000a50e,0x4000000,0x200000, +0x7000b61c,0x2802500,0x1862460,0x7000b61c,0x6800500,0x1862400,0x7000b61c,0x7c00100,0x1830000,0x7000c300,0x4000000,0x100000,0x7000c941,0x2806000,0xc62460,0x7000cc00, +0x4000000,0xe00000,0x7000cd00,0x4000000,0x200000,0x7000cd00,0x4000000,0xe00000,0x7000cd00,0x4000000,0x2800000,0x7000cf00,0x4000000,0xe00000,0x7000d202,0x2802100, +0x962460,0x7000d202,0x7c00100,0x230400,0x7000d997,0x7c00100,0x230400,0x7000d997,0xc000010,0x248000,0x7000dd86,0x2802400,0x962460,0x7000dd86,0x7c00100,0x230400, +0x7000dd86,0xc000010,0x448000,0x7000de9f,0x4000000,0x200000,0x7000de9f,0x7c00100,0x230400,0x7000e001,0x2400,0x962460,0x7000e001,0x2802400,0x962460,0x7000e187, +0x2802000,0x962460,0x7000e187,0x2802100,0x962460,0x7000e187,0x4000000,0x200000,0x7000e187,0x7c00100,0x230400,0x7000e187,0xc000010,0x448000,0x7000e288,0x7c00100, +0x230400,0x7000e300,0x4000000,0x200000,0x7000e489,0x2802100,0x962460,0x7000e489,0x2802400,0x962460,0x7000e489,0x6800100,0x962540,0x7000e489,0x6800100,0x962541, +0x7000e489,0x6804400,0x2f62540,0x7000e489,0x7c00100,0x430400,0x7000e489,0x7c00100,0x2b30400,0x7000e489,0x7c00100,0x2d30400,0x7000e489,0x7c00900,0x430400,0x7000e59d, +0x2802100,0x962460,0x7000e59d,0x2802400,0x962460,0x7000e59d,0x4000000,0x200000,0x7000e59d,0x4000010,0x200000,0x7000e59d,0x6800100,0x962540,0x7000e59d,0x6804400, +0x962540,0x7000e59d,0x7c00100,0x230400,0x7000e59d,0xc000010,0x448000,0x7000e691,0x2802100,0x962460,0x7000e691,0x2802400,0x962460,0x7000e691,0x2806400,0x962460, +0x7000e691,0x6800000,0x1329800,0x7000e691,0x6800100,0x962540,0x7000e691,0x7c00100,0x230400,0x7000e700,0x4000400,0x200400,0x7000e70e,0x7c00100,0x220400,0x7000e719, +0x7c00100,0x220400,0x7000e719,0x7c00500,0x22040f,0x7000e853,0x7c00100,0x230400,0x7000e9a0,0x2802400,0x962460,0x7000e9a0,0x4000000,0x200000,0x7000e9a0,0x4000000, +0x500000,0x7000e9a0,0x7c00100,0x230400,0x7000ea79,0x2802400,0x962460,0x7000ea79,0x4000000,0x200000,0x7000ea79,0x4000000,0xf00000,0x7000ea79,0x4000010,0x400000, +0x7000ea79,0x7c00100,0x230400,0x7000eb8c,0x2802400,0x962460,0x7000eb8c,0x4000000,0x200000,0x7000eb8c,0x7c00100,0x230400,0x7000eca3,0x2802100,0x962460,0x7000eca3, +0x2806400,0x962460,0x7000eca3,0x4000000,0x200000,0x7000eca3,0x6800000,0x1329800,0x7000eca3,0x6800100,0x962540,0x7000eca3,0x7c00100,0x230400,0x7000eca3,0xc000010, +0x448000,0x7000ed95,0x6800000,0x1329800,0x7000ed95,0x7c00100,0x230400,0x7000ed95,0xc000010,0x448000,0x7000ee1c,0x2802500,0x1862460,0x7000ee1c,0x6800000,0x1329800, +0x7000ee1c,0x7c00100,0x1830000,0x7000ee1c,0x7c00900,0x1830000,0x7000ef8f,0x4000000,0x200000,0x7000ef8f,0x7c00100,0x230400,0x7000f08e,0x4000000,0x200000,0x7000f08e, +0x7c00100,0x230400,0x7000f159,0x2802100,0x962460,0x7000f159,0x7c00100,0x230400,0x7000f200,0x4000000,0x200000,0x7000f200,0x4000000,0x1200000,0x7000f200,0x4000000, +0x1710000,0x7000f34b,0x2802400,0x962460,0x7000f34b,0x4000000,0x200000,0x7000f34b,0x4000010,0x400000,0x7000f34b,0x6800000,0x1329800,0x7000f34b,0x7c00100,0x230400, +0x7000f34b,0x7c00900,0x230400,0x7000f34b,0xc000010,0x448000,0x7000f490,0x4000000,0x200000,0x7000f490,0x7c00100,0x230400,0x7000f5a5,0x7c00100,0x230400,0x7000f67b, +0x4000000,0x200000,0x7000f67b,0x4000010,0x200000,0x7000f67b,0x7c00100,0x230400,0x7000f8a6,0x2802100,0x962460,0x7000f8a6,0x2802400,0x962460,0x7000f8a6,0x2806400, +0x962460,0x7000f8a6,0x4000000,0x500000,0x7000f8a6,0x4000010,0xb00000,0x7000f8a6,0x4000800,0x200000,0x7000f8a6,0x6800100,0x962540,0x7000f8a6,0x6800100,0x962541, +0x7000f8a6,0x7c00100,0x230400,0x7000f8a6,0xc000010,0x448000,0x7000f921,0x4000000,0x200000,0x7000fa00,0x4000000,0x200000,0x7000fb9e,0x2802100,0x962460,0x7000fb9e, +0x2802400,0x962460,0x7000fb9e,0x2806400,0x962460,0x7000fb9e,0x4000000,0x200000,0x7000fb9e,0x6800000,0x1329800,0x7000fb9e,0x6800100,0x962540,0x7000fb9e,0x6800100, +0x962541,0x7000fb9e,0x7c00100,0x230400,0x7000fc92,0x4000000,0x200000,0x7000fc92,0x6800000,0x1329800,0x7000fc92,0x7c00100,0x220400,0x7000fc92,0x7c00100,0x230400, +0x7000fc92,0x7c00100,0x250400,0x700acd00,0x4000000,0xe00000,0x700acd00,0x4000000,0x2800000,0x700ace00,0x4000000,0xe00000,0x700acf00,0x4000000,0xe00000,0x700acf00, +0x4000000,0x2800000,0x7050df21,0x4000000,0x200000,0x7050f729,0x80000,0x918820,0x7080afa1,0x2802400,0x962460,0x7090df21,0x2802400,0x962460,0x70d0e427,0x2802100, +0x962460,0x70d0e427,0x2802400,0x962460,0x70d0e427,0x6800100,0x962540,0x70d0ea25,0x4000010,0x400000,0x8000120f,0x7c00100,0x230400,0x80001524,0x7c00100,0x230400, +0x8000171a,0x7c00100,0x230400,0x80002006,0x7c00100,0x220400,0x80002006,0x7c00100,0x250400,0x80002a00,0x4000000,0x1500000,0x80002d00,0x4000000,0x200000,0x80005208, +0x2802400,0x962460,0x80005c00,0x4000000,0x200000,0x80007300,0x24000000,0x200000,0x80009519,0x7c00100,0x220400,0x80009519,0x7c00100,0x230400,0x80009519,0x7c00100, +0x250400,0x80009865,0x7c00100,0x230400,0x8000a008,0x2802100,0x962460,0x8000b30a,0x4000000,0x500000,0x8000b30a,0x7c00100,0x230400,0x8000cd00,0x4000000,0xe00000, +0x8000d202,0x2802500,0x962460,0x8000d202,0x7c00100,0x230400,0x8000d68d,0x4000000,0x200000,0x8000d997,0x2802000,0x962460,0x8000d997,0x2802400,0x962460,0x8000d997, +0x4000000,0x400000,0x8000d997,0x4000000,0x500000,0x8000d997,0x7c00100,0x230400,0x8000d997,0xc000010,0x448000,0x8000e489,0x2802100,0x962460,0x8000e489,0x7c00100, +0x2d30400,0x8000e719,0x7c00100,0x220400,0x8000f8a6,0x2802100,0x962460,0x8000f8a6,0x7c00100,0x230400,0x8000f8a6,0xc000010,0x448000,0x8000fda1,0x2802100,0x1862460, +0x8000fda1,0x2806400,0x1862460,0x8000fda1,0x4000000,0x1800000,0x8000fda1,0x6800000,0x1329800,0x8000fda1,0x6800100,0x1862400,0x8000fda1,0x6800100,0x1862540,0x8000fda1, +0x7c00100,0x1830000,0x8000fda1,0xc000010,0x448000,0x8000fe9c,0x7c00100,0x230400,0x8000fe9c,0x7c00100,0x830400,0x8000fe9c,0x7c00100,0x1430400,0x8000ff06,0x7c00100, +0x220400,0x80010165,0x7c00100,0x230400,0x800102a2,0x4000000,0x200000,0x800102a2,0x7c00100,0x230400,0x800103a4,0x7c00100,0x230400,0x800103a4,0xc000010,0x448000, +0x8001044c,0x4000000,0x200000,0x8001044c,0x7c00100,0x220400,0x8001044c,0x7c00100,0x250400,0x80010670,0x2802000,0x962460,0x80010670,0x4000000,0x200000,0x80010670, +0x4000010,0x400000,0x80010670,0xc000010,0x448000,0x800a4711,0x7c40300,0xe30000,0x800acd00,0x4000000,0xe00000,0x800acd00,0x4000000,0x2902460,0x800ace00,0x4000000, +0xe00000,0x800acf00,0x4000000,0xe00000,0x800b0011,0x7c40300,0xe30000,0x800b0500,0x4000000,0xe00000,0x800b0500,0x4000000,0x2800000,0x90001615,0x7c00100,0x230400, +0x9000171a,0x4000000,0x200000,0x9000171a,0x7c00100,0x230400,0x90003000,0x24000000,0x200000,0x90007f0e,0x4000000,0x200000,0x90008301,0x2802400,0x962460,0x90008e00, +0x24000000,0x400000,0x90009519,0x7c00100,0x250400,0x9000a16f,0x2802100,0x962460,0x9000d200,0x80000000,0x1329960,0x9000d202,0x2802000,0x962460,0x9000d202,0x2802100, +0x962460,0x9000d202,0x7c00100,0x230400,0x9000e59d,0x2802100,0x962460,0x90010500,0x4000000,0xe00000,0x900107a7,0x2802100,0x962460,0x900107a7,0x2802400,0x962460, +0x900107a7,0x2802c00,0x962460,0x900107a7,0x4000000,0x1400000,0x900107a7,0x6800000,0x1329800,0x900107a7,0x7c00100,0x220400,0x900107a7,0x7c00100,0x250400,0x900108a8, +0x2802100,0x962460,0x900108a8,0x2806400,0x962460,0x900108a8,0x4000000,0x200000,0x900108a8,0x4000000,0x400000,0x900108a8,0x4000010,0x400000,0x900108a8,0x6800000, +0x1329800,0x900108a8,0x6800100,0x962540,0x900108a8,0x7c00100,0x230400,0x900108a8,0xc000010,0x448000,0x90010908,0x7c00100,0x220400,0x90010a38,0x2802100,0x962460, +0x90010ca9,0x2802100,0x962460,0x90010ca9,0x4000000,0x500000,0x90010ca9,0x4000010,0xb00000,0x90010ca9,0x6800100,0x962540,0x90010ca9,0x7c00100,0x230400,0x90010d1b, +0x4000000,0x500000,0x90010eaa,0x2802100,0x962460,0x90010eaa,0x2802400,0x962460,0x90010eaa,0x2806400,0x962460,0x90010eaa,0x4000000,0x200000,0x90010eaa,0x4000000, +0x400000,0x90010eaa,0x4000010,0x400000,0x90010eaa,0x6800000,0x1329800,0x90010eaa,0x6800100,0x962540,0x90010eaa,0x7c00100,0x230400,0x90010eaa,0xc000010,0x448000, +0x90010fab,0x7c00100,0x220400,0x90010fab,0x7c00100,0x250400,0x9002c300,0x4000000,0x100000,0x900ac400,0x4000000,0xe0000d,0x900acd00,0x4000000,0xe00000,0x900acd00, +0x4000000,0x2800000,0x900acf00,0x4000000,0xe00000,0x900b0500,0x4000000,0xe00000,0x900b0500,0x4000000,0x2800000,0x900b0b9a,0x7c00900,0x1230400,0x900b109a,0x7c00300, +0xe30000,0x900b119a,0x7c00300,0xe30000,0x90408e06,0x24000000,0x400000,0xa0001004,0x4000000,0x200000,0xa0001004,0x7c00100,0x230400,0xa000120f,0x2802100,0x962460, +0xa000120f,0x2802400,0x962460,0xa000171a,0x2802100,0x962460,0xa000171a,0x2806400,0x962460,0xa0002a00,0x4000000,0x1600000,0xa0003000,0x24000000,0x200000,0xa000581e, +0x7c00100,0x230400,0xa0007300,0x24000000,0x200000,0xa0008301,0x2802400,0x962460,0xa0008e00,0x24000000,0x400000,0xa000cf00,0x4000000,0xe00000,0xa0010500,0x4000000, +0x200000,0xa00114af,0x2802100,0x962460,0xa00114af,0x2802400,0x962460,0xa00114af,0x2806400,0x962460,0xa00114af,0x6800000,0x1329800,0xa00114af,0x7c00100,0x230400, +0xa00114af,0x7c00100,0x230560,0xa00116b0,0x2802100,0x962460,0xa00116b0,0x2802800,0x962460,0xa00116b0,0x2806400,0x962460,0xa00116b0,0x4000000,0x400000,0xa00116b0, +0x4000000,0x500000,0xa00116b0,0x4000010,0x400000,0xa00116b0,0x6800100,0x962540,0xa00116b0,0x7c00100,0x230400,0xa00116b0,0x7c00100,0x230560,0xa00116b0,0xc000010, +0x448000,0xa0011722,0x7c00100,0x230400,0xa00118b1,0x2802000,0x962460,0xa00118b1,0x2802100,0x962460,0xa00118b1,0x2806400,0x962460,0xa00118b1,0x4000000,0x200000, +0xa00118b1,0x4000000,0x400000,0xa00118b1,0x4000000,0x500000,0xa00118b1,0x6800100,0x962540,0xa00118b1,0x7c00100,0x230400,0xa00118b1,0x7c00100,0x230560,0xa00118b1, +0xc000010,0x448000,0xa00a4005,0x7c00100,0xe30400,0xa00a4711,0x7c40300,0xe30000,0xa00ac400,0x4000000,0xe00000,0xa00acb14,0x7c00100,0xe30000,0xa00acf00,0x4000000, +0xe00000,0xa00b0500,0x4000000,0xe00000,0xa00b0500,0x4000000,0x2800000,0xa00b0b96,0x7c00900,0x1230400,0xa00b1211,0x7c40300,0xe30000,0xa00b1314,0x7c00100,0xe30000, +0xa00b1596,0x7c00300,0xe30000,0xa040afb9,0x6800400,0x962540,0xa08083ba,0x2802400,0x962460,0xb0000a03,0x7c00100,0x220400,0xb0000b13,0x7c00100,0x2633800,0xb0001004, +0x2802000,0x962460,0xb0001110,0x4000000,0x200000,0xb0001524,0x2802100,0x962460,0xb0001615,0x4000000,0x500000,0xb000251b,0x7c00100,0x230400,0xb0007300,0x24000000, +0x200000,0xb0008939,0x4000000,0x200000,0xb0008939,0x7c00100,0x230400,0xb0008e00,0x24000000,0x200000,0xb0008e00,0x24000000,0x400000,0xb0008e00,0x24000010,0x400000, +0xb0009257,0x2802000,0x962460,0xb0009257,0x4000000,0x1600000,0xb0009519,0x7c00100,0x220400,0xb0009519,0x7c00100,0x250400,0xb0009a00,0x4000000,0x200000,0xb000b30a, +0x2802100,0x962460,0xb000b30a,0x7c00100,0x230400,0xb000c178,0x80000000,0x1329960,0xb000c300,0x4000000,0x200000,0xb000d202,0x2802000,0x962460,0xb000d476,0x6800100, +0x962540,0xb000d476,0x7c00100,0x230400,0xb000e300,0x4000000,0xe00000,0xb000fda1,0x7c00100,0x1830000,0xb0010eaa,0x2802000,0x962460,0xb00116b0,0x7c00100,0x230400, +0xb0011900,0x4000000,0xe00000,0xb0011ab2,0x2802100,0x962460,0xb0011ab2,0x2802400,0x962460,0xb0011ab2,0x2806400,0x962460,0xb0011ab2,0x4000000,0x200000,0xb0011ab2, +0x6800100,0x962540,0xb0011ab2,0x7c00100,0x230400,0xb0011b0c,0x7c00100,0x230400,0xb0011cb3,0x2802100,0x962460,0xb0011cb3,0x2806400,0x962460,0xb0011cb3,0x6800000, +0x1329800,0xb0011cb3,0x6800100,0x962540,0xb0011cb3,0x7c00100,0x230400,0xb0011db6,0x2802500,0x962460,0xb0011db6,0x6800000,0x1329800,0xb0011db6,0x7c00100,0x230400, +0xb0011db6,0x7c00500,0x230400,0xb0011e00,0x4000000,0x200000,0xb0011e00,0x4000000,0x1500000,0xb0011fb4,0x2802100,0x962460,0xb0011fb4,0x6800100,0x962540,0xb0011fb4, +0x7c00100,0x430400,0xb0011fb4,0x7c00100,0x2d30400,0xb0011fb4,0xc000010,0x448000,0xb0012000,0x4000000,0x200000,0xb00121b5,0x4000000,0x200000,0xb00121b5,0x4000010, +0x400000,0xb00121b5,0x7c00100,0x220400,0xb00121b5,0x7c00100,0x250400,0xb00121b5,0xc000010,0x448000,0xb00122b8,0x4000000,0x200000,0xb00122b8,0x7c00100,0x230400, +0xb00123b7,0x2802400,0x962460,0xb00123b7,0x4000000,0x200000,0xb00123b7,0x7c00100,0x230400,0xb00123b7,0xc000010,0x248000,0xb00a4005,0x7c00100,0xe30400,0xb00a4711, +0x7c40300,0xe30000,0xb00acf00,0x4000000,0xe00000,0xb00b0500,0x4000000,0xe00000,0xb00b0500,0x4000000,0x2800000,0xb00b109a,0x7c00300,0xe30000,0xb080e487,0x2802000, +0x962460,0xc0001524,0x4000000,0x500000,0xc0001a18,0x2806400,0x1862460,0xc0001a18,0x7c00100,0x1830000,0xc0007300,0x24000000,0x200000,0xc0008e00,0x24000010,0x400000, +0xc0009519,0x7c00100,0x220400,0xc0009519,0x7c00100,0x250400,0xc000c300,0x4000000,0x20000f,0xc000d85c,0x2802100,0x962460,0xc000d85c,0x6800100,0x962540,0xc000d85c, +0x7c00100,0x230400,0xc000dc99,0x7c00100,0x230400,0xc000e719,0x7c00100,0x220400,0xc00107a7,0x7c00100,0x230400,0xc0010eaa,0x7c00100,0x230400,0xc00116b0,0x7c00100, +0x230560,0xc0011900,0x4000000,0x200000,0xc0012447,0,0x818820,0xc0012447,0,0xc18820,0xc0012447,0,0x1418820,0xc00125b9,0x7c00100,0x230400, +0xc00126bb,0x2802100,0x962460,0xc00126bb,0x2806400,0x962460,0xc00126bb,0x4000000,0x500000,0xc00126bb,0x6800100,0x962540,0xc00126bb,0x7c00100,0x230400,0xc00127ba, +0x2802400,0x962460,0xc00127ba,0x4000000,0x200000,0xc00127ba,0x6800000,0x1329800,0xc00127ba,0x7c00100,0x230400,0xc00127ba,0x7c00900,0x230400,0xc0012800,0x4000000, +0x200000,0xc0012b23,0x4000000,0x200000,0xc0012b23,0x4000000,0x400000,0xc0012b23,0x4000000,0x1500000,0xc0012cbc,0x2802400,0x962460,0xc0012cbc,0x4000000,0x1600000, +0xc0012cbc,0x6800000,0x1329800,0xc0012cbc,0x7c00100,0x230400,0xc00acf00,0x4000000,0xe00000,0xc00ae300,0x4000000,0xe00000,0xc00b0500,0x4000000,0xe00000,0xc00b0500, +0x4000000,0x2800000,0xc00b0b11,0x4000000,0x1200000,0xc00b0b11,0x7c00900,0x1230400,0xc00b109a,0x7c00300,0xe30000,0xc00b2914,0x7c00100,0x2530000,0xc00b2916,0x7c00100, +0x2530c00,0xc00b2a00,0x4000000,0xe00000,0xc040af5e,0x7c00100,0x230400,0xc0c12b89,0x4000000,0x200000,0xc14a44cc,0x4000000,0xe0000d,0xd000131f,0x2802c00,0x962460, +0xd000171a,0x7c00100,0x230400,0xd0001821,0x2802100,0x962460,0xd0007300,0x24000000,0x200000,0xd0008e00,0x24000000,0x200000,0xd0008f3a,0x2806000,0x962460,0xd0009519, +0x7c00100,0x220400,0xd0009519,0x7c00100,0x250400,0xd000a500,0x4000000,0x200000,0xd000c300,0x4000000,0xe00000,0xd000d202,0x7c00100,0x230400,0xd000d476,0x7c00100, +0x230400,0xd000d997,0x2802100,0x962460,0xd000d997,0x6800100,0x962540,0xd000e001,0x2802100,0x962460,0xd000e700,0x4000400,0x200000,0xd000e719,0x7c00100,0x220400, +0xd000e719,0x7c00500,0x22040f,0xd000fa00,0x4000000,0xe00000,0xd0010eaa,0x4000010,0x400000,0xd0010eaa,0x7c00100,0x230400,0xd0012dbd,0x4000000,0x200000,0xd0012dbd, +0x7c00100,0x230400,0xd0012fbe,0x2802100,0x962460,0xd0012fbe,0x2802400,0x962460,0xd0012fbe,0x2806400,0x2f62460,0xd0012fbe,0x4000000,0x400000,0xd0012fbe,0x6800000, +0xe29800,0xd0012fbe,0x6800100,0x962540,0xd0012fbe,0x6800100,0x962541,0xd0012fbe,0x6804400,0x962540,0xd0012fbe,0x7c00100,0x2b30400,0xd0012fbe,0x7c00100,0x2c30560, +0xd0012fbe,0xc000010,0x448000,0xd0013183,0x7c00100,0x230400,0xd0013200,0x4000000,0x200000,0xd0013200,0x6800000,0x1329805,0xd00134c0,0x2802100,0x962460,0xd00134c0, +0x4000002,0x400000,0xd00134c0,0x7c00100,0x230400,0xd00a4305,0x7c00100,0xe30400,0xd00a4611,0x7c40300,0xe30000,0xd00a4711,0x7c40300,0xe30000,0xd00a5e11,0x7c40300, +0xe30000,0xd00acf00,0x4000000,0xe00000,0xd00b0500,0x4000000,0xe00000,0xd00b0500,0x4000000,0x2800000,0xd00b0b11,0x6800500,0x962540,0xd00b0bbf,0x2802200,0xc62460, +0xd00b119a,0x7c00300,0xe30000,0xd00b2a00,0x4000000,0xe00000,0xd00b2e11,0x7c40300,0xe30000,0xd00b30bf,0x7c00300,0x230000,0xd00b339a,0x7c00300,0xe30000,0xe0000c02, +0xc000010,0xb48000,0xe0001524,0x2802400,0x962460,0xe0001524,0x7c00100,0x230400,0xe0001615,0x7c00100,0x230400,0xe000251b,0x12882000,0x962460,0xe0002a00,0x4000000, +0x1500000,0xe0005102,0x4000000,0x200000,0xe0005c00,0x4000000,0x200000,0xe000622a,0x6804400,0x962540,0xe000622a,0x7c00100,0x230400,0xe0008838,0x7c00100,0x220400, +0xe0008838,0x7c00100,0x250400,0xe0008e00,0x24000000,0x810000,0xe0008e00,0x24000000,0x1410000,0xe0008e00,0x24000002,0x400000,0xe0008e00,0x2c000010,0xb48000,0xe000933e, +0x7c00100,0x2b30400,0xe000933e,0xc000010,0x448000,0xe0009519,0x7c00100,0x220400,0xe0009519,0x7c00100,0x22040f,0xe0009519,0x7c00100,0x250400,0xe000c178,0x2802100, +0x962460,0xe000c941,0x2802100,0x962460,0xe000c941,0x2806400,0x962460,0xe000c941,0x7c00100,0x2b30400,0xe000d202,0x2802400,0x962460,0xe000d202,0x7c00100,0x230400, +0xe000d202,0x7c00500,0x230400,0xe000dc99,0x4000000,0x200000,0xe000e001,0x2802100,0x962460,0xe000e001,0x2802400,0x962460,0xe000fda1,0x7c00100,0x1830000,0xe0013502, +0x2802400,0x962460,0xe0013502,0x4000000,0x200000,0xe0013502,0x7c00100,0x230400,0xe0013502,0x80000000,0x1329960,0xe00136c1,0x4000000,0x200000,0xe00136c1,0x7c00100, +0x230400,0xe001370b,0x7c00100,0x230400,0xe0013919,0x7c00500,0x220400,0xe0013919,0x7c00500,0x22040f,0xe0013919,0x7c00d00,0x23040f,0xe0013a19,0x7c00100,0x220400, +0xe0013a19,0x7c00100,0x230400,0xe0013bc2,0x2802400,0x962460,0xe0013bc2,0x7c00100,0x230400,0xe0013bc2,0xc000010,0x248000,0xe0013cc3,0x6800000,0x1329800,0xe0013cc3, +0x7c00100,0x230400,0xe0013dc4,0x2802400,0x962460,0xe0013dc4,0x7c00100,0x230400,0xe0013e28,0x7c00100,0x230400,0xe0013fc5,0x7c00100,0x220400,0xe0013fc5,0x7c00100, +0x250400,0xe0014000,0x4000000,0x200000,0xe0014001,0x2802400,0x962460,0xe00a4711,0x7c40300,0xe30000,0xe00a5e11,0x7c40300,0xe30000,0xe00ac511,0x7c40300,0xe30000, +0xe00acf00,0x4000000,0xe00000,0xe00ae300,0x4000000,0xe00000,0xe00b0500,0x4000000,0xe00000,0xe00b1314,0x7c00100,0xe30000,0xe00b1316,0x7c00100,0xe30c00,0xe00b2a00, +0x4000000,0xe00000,0xe00b2a00,0x4000000,0x2800000,0xe00b3816,0x7c00500,0x230c00,0xe0808328,0x2802400,0x962460,0xf0001615,0x6800100,0x962540,0xf0001a18,0x2802000, +0x1862460,0xf000c247,0x7c00100,0x1430400,0xf000d000,0x4000000,0xe00000,0xf000e300,0x4000000,0xe00000,0xf000e59d,0x2802100,0x962460,0xf000e59d,0x7c00100,0x230400, +0xf0012447,0,0x818820,0xf0012447,0,0xc18820,0xf0012447,0,0x1418820,0xf0012447,0x2802000,0x962460,0xf0012447,0x2802400,0x962460,0xf0012447, +0x7c00100,0x230400,0xf0013a19,0x7c00100,0x220400,0xf0014102,0x2802400,0x962460,0xf0014308,0x2802100,0x962460,0xf0014308,0x7c00500,0x22040e,0xf0014308,0x7c00500, +0x22040f,0xf001440a,0x4000000,0x500000,0xf0014500,0x4000000,0x200000,0xf00146c6,0x2802100,0x962460,0xf00146c6,0x2806000,0x2f62460,0xf00146c6,0x4000000,0xe00000, +0xf00146c6,0x6800000,0x2d29800,0xf00146c6,0x6800100,0x962540,0xf00146c6,0x6804000,0x962540,0xf00146c6,0x7c00100,0x2b30400,0xf00146c6,0x7c00100,0x2c30560,0xf00146c6, +0xc000010,0x448000,0xf00147c7,0x2802000,0x962460,0xf00147c7,0x6800000,0x1329800,0xf00147c7,0x7c00100,0x230400,0xf00ac511,0x7c40300,0xe30000,0xf00acf00,0x4000000, +0xe00000,0xf00b2914,0x7c00100,0x2530000,0xf00b2916,0x7c00100,0x2530c00,0xf00b2a00,0x4000000,0xe00000,0xf00b2a00,0x4000000,0x2800000,0xf00b4211,0x7c40300,0xe30000, +0xf10a3c00,0x4000000,0xe00000,0xf10a3c00,0x4008000,0xe00000,0xf10a8200,0x4008000,0xe00000,0xf10b4811,0x7c40300,0xe30000}; -static const int32_t countPropsVectors=7230; +static const int32_t countPropsVectors=7260; static const int32_t propsVectorsColumns=3; -static const uint16_t scriptExtensions[282]={ +static const uint16_t scriptExtensions[298]={ 0x800e,0x8019,8,0x8059,8,2,8,0x8038,8,6,8,0x8019,2,0x22,0x25,0x57, 0xb6,0x80c0,2,0x22,0x8025,2,0x12,2,0x22,0x25,0x57,0xa7,0xb6,0x80c0,2,0x22, 0x54,0x79,0x7b,0xa7,0xb6,0xb7,0x80c2,2,0x8022,2,0x25,0x80c0,2,0x29,2,0x80b6, @@ -3998,14 +4013,15 @@ static const uint16_t scriptExtensions[282]={ 0x80a4,0x10,0x7f,0xf,0x809d,0xf,0x83,0x23,0x8089,0x23,0x87,0x15,0x80bb,0x15,0x8b,0x1c, 0x34,0x8076,0x1c,0x8f,0xc,0x8019,0x2a,0x2b,0x2c,0x802d,0x1b,0x805a,0x800a,4,0xa,0x15, 0x8089,0xa,0x8089,4,0x800a,0xa,0x8097,0xa,0x15,0x1a,0x1f,0x23,0x8024,0xa,0x80bb,4, -0xa,0x15,0x1f,0x24,0x89,0x9e,0x80bb,0x8004,8,0x8022,0x19,0x801b,0xa,0x19,0x8089,5, -0x11,0x12,0x14,0x16,0x8029,5,0x11,0x12,0x14,0x8016,0x8011,5,0x8011,0x11,0x14,0x8016, -0x11,0x8019,0xa,0xf,0x10,0x78,0x91,0x99,0x9d,0x9e,0xa0,0xa3,0x80b2,0xa,0xf,0x10, -0x15,0x1a,0x78,0x91,0x99,0x9d,0x9e,0xa0,0xa3,0xb2,0x80bb,0xa,0xf,0x10,0x15,0x78, -0x91,0x99,0x9d,0x9e,0xa0,0xa3,0xb2,0x80bb,0xa,0xa3,0xa,0x8023,0xa,0xfa,0x19,0x1c, -0x804f,0x37,0x804e,2,0x8057,2,0x8025,2,0x105,0x2f,0x31,0x8053,0x2f,0x31,0x80c1,0x2f, -0x8031,2,0x8007,0x79,0x80c2,0x79,0x113,0x89,0x87,0x8087}; +0xa,0x15,0x1a,0x1f,0x21,0x24,0x89,0x9e,0x80bb,0x8004,8,0x8022,0x19,0x801b,0xa,0x19, +0x8089,5,0x11,0x12,0x14,0x16,0x8029,5,0x11,0x12,0x14,0x8016,0x8011,5,0x8011,0x11, +0x14,0x8016,0x11,0x8019,0xa,0xf,0x10,0x15,0x1a,0x78,0x91,0x97,0x99,0x9d,0x9e,0xa0, +0xa3,0xb2,0x80bb,0xa,0xf,0x10,0x15,0x78,0x91,0x97,0x99,0x9d,0x9e,0xa0,0xa3,0xb2, +0x80bb,0xa,0xf,0x10,0x78,0x91,0x99,0x9d,0x9e,0xa0,0xa3,0x80b2,0xa,0xf,0x10,0x78, +0x91,0x97,0x99,0x9d,0x9e,0xa0,0xa3,0x80b2,0xa,0xa3,0xa,0x8023,0xa,0x10a,0x19,0x1c, +0x804f,0x37,0x804e,2,0x8057,2,0x8025,2,0x115,0x2f,0x31,0x8053,0x2f,0x31,0x80c1,0x2f, +0x8031,2,0x8007,0x79,0x80c2,0x79,0x123,0x89,0x87,0x8087}; -static const int32_t indexes[UPROPS_INDEX_COUNT]={0x2d08,0x2d08,0x2d08,0x2d08,0x6ce6,3,0x8924,0x89b1,0x89b1,0x89b1,0xb47c7,0x2a75a31,0,0,0,0}; +static const int32_t indexes[UPROPS_INDEX_COUNT]={0x2d4e,0x2d4e,0x2d4e,0x2d4e,0x6d50,3,0x89ac,0x8a41,0x8a41,0x8a41,0xb48c7,0x2f75a31,0,0,0,0}; #endif // INCLUDED_FROM_UCHAR_C diff --git a/thirdparty/icu4c/common/ucurr.cpp b/thirdparty/icu4c/common/ucurr.cpp index ffca8aac5f..70b1bbf223 100644 --- a/thirdparty/icu4c/common/ucurr.cpp +++ b/thirdparty/icu4c/common/ucurr.cpp @@ -11,6 +11,8 @@ #if !UCONFIG_NO_FORMATTING +#include <utility> + #include "unicode/ucurr.h" #include "unicode/locid.h" #include "unicode/ures.h" @@ -20,6 +22,7 @@ #include "unicode/usetiter.h" #include "unicode/utf16.h" #include "ustr_imp.h" +#include "bytesinkutil.h" #include "charstr.h" #include "cmemory.h" #include "cstring.h" @@ -520,14 +523,18 @@ ucurr_forLocale(const char* locale, return 0; } - char currency[4]; // ISO currency codes are alpha3 codes. UErrorCode localStatus = U_ZERO_ERROR; - int32_t resLen = uloc_getKeywordValue(locale, "currency", - currency, UPRV_LENGTHOF(currency), &localStatus); - if (U_SUCCESS(localStatus) && resLen == 3 && uprv_isInvariantString(currency, resLen)) { + CharString currency; + { + CharStringByteSink sink(¤cy); + ulocimp_getKeywordValue(locale, "currency", sink, &localStatus); + } + int32_t resLen = currency.length(); + + if (U_SUCCESS(localStatus) && resLen == 3 && uprv_isInvariantString(currency.data(), resLen)) { if (resLen < buffCapacity) { - T_CString_toUpperCase(currency); - u_charsToUChars(currency, buff, resLen); + T_CString_toUpperCase(currency.data()); + u_charsToUChars(currency.data(), buff, resLen); } return u_terminateUChars(buff, buffCapacity, resLen, ec); } @@ -597,11 +604,15 @@ ucurr_forLocale(const char* locale, if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) { // We don't know about it. Check to see if we support the variant. - uloc_getParent(locale, id, UPRV_LENGTHOF(id), ec); + CharString parent; + { + CharStringByteSink sink(&parent); + ulocimp_getParent(locale, sink, ec); + } *ec = U_USING_FALLBACK_WARNING; - // TODO: Loop over the shortened id rather than recursing and + // TODO: Loop over the parent rather than recursing and // looking again for a currency keyword. - return ucurr_forLocale(id, buff, buffCapacity, ec); + return ucurr_forLocale(parent.data(), buff, buffCapacity, ec); } if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) { // There is nothing to fallback to. Report the failure/warning if possible. @@ -624,20 +635,22 @@ ucurr_forLocale(const char* locale, * @return true if the fallback happened; false if locale is already * root (""). */ -static UBool fallback(char *loc) { - if (!*loc) { +static UBool fallback(CharString& loc) { + if (loc.isEmpty()) { return false; } UErrorCode status = U_ZERO_ERROR; - if (uprv_strcmp(loc, "en_GB") == 0) { + if (loc == "en_GB") { // HACK: See #13368. We need "en_GB" to fall back to "en_001" instead of "en" // in order to consume the correct data strings. This hack will be removed // when proper data sink loading is implemented here. - // NOTE: "001" adds 1 char over "GB". However, both call sites allocate - // arrays with length ULOC_FULLNAME_CAPACITY (plenty of room for en_001). - uprv_strcpy(loc + 3, "001"); + loc.truncate(3); + loc.append("001", status); } else { - uloc_getParent(loc, loc, (int32_t)uprv_strlen(loc), &status); + CharString tmp; + CharStringByteSink sink(&tmp); + ulocimp_getParent(loc.data(), sink, &status); + loc = std::move(tmp); } /* char *i = uprv_strrchr(loc, '_'); @@ -692,9 +705,12 @@ ucurr_getName(const char16_t* currency, // this function. UErrorCode ec2 = U_ZERO_ERROR; - char loc[ULOC_FULLNAME_CAPACITY]; - uloc_getName(locale, loc, sizeof(loc), &ec2); - if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) { + CharString loc; + { + CharStringByteSink sink(&loc); + ulocimp_getName(locale, sink, &ec2); + } + if (U_FAILURE(ec2)) { *ec = U_ILLEGAL_ARGUMENT_ERROR; return 0; } @@ -707,7 +723,7 @@ ucurr_getName(const char16_t* currency, const char16_t* s = nullptr; ec2 = U_ZERO_ERROR; - LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_CURR, loc, &ec2)); + LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_CURR, loc.data(), &ec2)); if (nameStyle == UCURR_NARROW_SYMBOL_NAME || nameStyle == UCURR_FORMAL_SYMBOL_NAME || nameStyle == UCURR_VARIANT_SYMBOL_NAME) { CharString key; @@ -791,9 +807,12 @@ ucurr_getPluralName(const char16_t* currency, // this function. UErrorCode ec2 = U_ZERO_ERROR; - char loc[ULOC_FULLNAME_CAPACITY]; - uloc_getName(locale, loc, sizeof(loc), &ec2); - if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) { + CharString loc; + { + CharStringByteSink sink(&loc); + ulocimp_getName(locale, sink, &ec2); + } + if (U_FAILURE(ec2)) { *ec = U_ILLEGAL_ARGUMENT_ERROR; return 0; } @@ -803,7 +822,7 @@ ucurr_getPluralName(const char16_t* currency, const char16_t* s = nullptr; ec2 = U_ZERO_ERROR; - UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc, &ec2); + UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc.data(), &ec2); rb = ures_getByKey(rb, CURRENCYPLURALS, rb, &ec2); @@ -904,13 +923,17 @@ getCurrencyNameCount(const char* loc, int32_t* total_currency_name_count, int32_ *total_currency_name_count = 0; *total_currency_symbol_count = 0; const char16_t* s = nullptr; - char locale[ULOC_FULLNAME_CAPACITY] = ""; - uprv_strcpy(locale, loc); + CharString locale; + { + UErrorCode status = U_ZERO_ERROR; + locale.append(loc, status); + if (U_FAILURE(status)) { return; } + } const icu::Hashtable *currencySymbolsEquiv = getCurrSymbolsEquiv(); for (;;) { UErrorCode ec2 = U_ZERO_ERROR; // TODO: ures_openDirect? - UResourceBundle* rb = ures_open(U_ICUDATA_CURR, locale, &ec2); + UResourceBundle* rb = ures_open(U_ICUDATA_CURR, locale.data(), &ec2); UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, nullptr, &ec2); int32_t n = ures_getSize(curr); for (int32_t i=0; i<n; ++i) { @@ -979,14 +1002,17 @@ collectCurrencyNames(const char* locale, // Look up the Currencies resource for the given locale. UErrorCode ec2 = U_ZERO_ERROR; - char loc[ULOC_FULLNAME_CAPACITY] = ""; - uloc_getName(locale, loc, sizeof(loc), &ec2); - if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) { + CharString loc; + { + CharStringByteSink sink(&loc); + ulocimp_getName(locale, sink, &ec2); + } + if (U_FAILURE(ec2)) { ec = U_ILLEGAL_ARGUMENT_ERROR; } // Get maximum currency name count first. - getCurrencyNameCount(loc, total_currency_name_count, total_currency_symbol_count); + getCurrencyNameCount(loc.data(), total_currency_name_count, total_currency_symbol_count); *currencyNames = (CurrencyNameStruct*)uprv_malloc (sizeof(CurrencyNameStruct) * (*total_currency_name_count)); @@ -1014,7 +1040,7 @@ collectCurrencyNames(const char* locale, for (int32_t localeLevel = 0; ; ++localeLevel) { ec2 = U_ZERO_ERROR; // TODO: ures_openDirect - UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc, &ec2); + UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc.data(), &ec2); UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, nullptr, &ec2); int32_t n = ures_getSize(curr); for (int32_t i=0; i<n; ++i) { diff --git a/thirdparty/icu4c/common/udata.cpp b/thirdparty/icu4c/common/udata.cpp index 76d970f3f2..88126fc689 100644 --- a/thirdparty/icu4c/common/udata.cpp +++ b/thirdparty/icu4c/common/udata.cpp @@ -1196,7 +1196,7 @@ doOpenChoice(const char *path, const char *type, const char *name, *p = U_FILE_SEP_CHAR; } #if defined (UDATA_DEBUG) - fprintf(stderr, "Changed path from [%s] to [%s]\n", path, altSepPath.s); + fprintf(stderr, "Changed path from [%s] to [%s]\n", path, altSepPath.data()); #endif path = altSepPath.data(); } diff --git a/thirdparty/icu4c/common/uloc.cpp b/thirdparty/icu4c/common/uloc.cpp index 395df1466e..ce49d6c50e 100644 --- a/thirdparty/icu4c/common/uloc.cpp +++ b/thirdparty/icu4c/common/uloc.cpp @@ -103,12 +103,12 @@ static const char * const LANGUAGES[] = { "ba", "bal", "ban", "bar", "bas", "bax", "bbc", "bbj", "be", "bej", "bem", "bew", "bez", "bfd", "bfq", "bg", "bgc", "bgn", "bho", "bi", "bik", "bin", "bjn", "bkm", "bla", - "bm", "bn", "bo", "bpy", "bqi", "br", "bra", "brh", + "blo", "bm", "bn", "bo", "bpy", "bqi", "br", "bra", "brh", "brx", "bs", "bss", "bua", "bug", "bum", "byn", "byv", "ca", "cad", "car", "cay", "cch", "ccp", "ce", "ceb", "cgg", "ch", "chb", "chg", "chk", "chm", "chn", "cho", "chp", "chr", "chy", "ckb", "co", "cop", "cps", "cr", "crh", - "cs", "csb", "cu", "cv", "cy", + "cs", "csb", "csw", "cu", "cv", "cy", "da", "dak", "dar", "dav", "de", "del", "den", "dgr", "din", "dje", "doi", "dsb", "dtp", "dua", "dum", "dv", "dyo", "dyu", "dz", "dzg", @@ -135,7 +135,7 @@ static const char * const LANGUAGES[] = { "kkj", "kl", "kln", "km", "kmb", "kn", "ko", "koi", "kok", "kos", "kpe", "kr", "krc", "kri", "krj", "krl", "kru", "ks", "ksb", "ksf", "ksh", "ku", "kum", "kut", - "kv", "kw", "ky", + "kv", "kw", "kxv", "ky", "la", "lad", "lag", "lah", "lam", "lb", "lez", "lfn", "lg", "li", "lij", "liv", "lkt", "lmo", "ln", "lo", "lol", "loz", "lrc", "lt", "ltg", "lu", "lua", "lui", @@ -169,14 +169,14 @@ static const char * const LANGUAGES[] = { "sv", "sw", "swb", "syc", "syr", "szl", "ta", "tcy", "te", "tem", "teo", "ter", "tet", "tg", "th", "ti", "tig", "tiv", "tk", "tkl", "tkr", - "tlh", "tli", "tly", "tmh", "tn", "to", "tog", "tpi", + "tlh", "tli", "tly", "tmh", "tn", "to", "tog", "tok", "tpi", "tr", "tru", "trv", "ts", "tsd", "tsi", "tt", "ttt", "tum", "tvl", "tw", "twq", "ty", "tyv", "tzm", "udm", "ug", "uga", "uk", "umb", "und", "ur", "uz", - "vai", "ve", "vec", "vep", "vi", "vls", "vmf", "vo", - "vot", "vro", "vun", + "vai", "ve", "vec", "vep", "vi", "vls", "vmf", "vmw", + "vo", "vot", "vro", "vun", "wa", "wae", "wal", "war", "was", "wbp", "wo", "wuu", - "xal", "xh", "xmf", "xog", + "xal", "xh", "xmf", "xnr", "xog", "yao", "yap", "yav", "ybb", "yi", "yo", "yrl", "yue", "za", "zap", "zbl", "zea", "zen", "zgh", "zh", "zu", "zun", "zxx", "zza", @@ -220,12 +220,12 @@ static const char * const LANGUAGES_3[] = { "bak", "bal", "ban", "bar", "bas", "bax", "bbc", "bbj", "bel", "bej", "bem", "bew", "bez", "bfd", "bfq", "bul", "bgc", "bgn", "bho", "bis", "bik", "bin", "bjn", "bkm", "bla", - "bam", "ben", "bod", "bpy", "bqi", "bre", "bra", "brh", + "blo", "bam", "ben", "bod", "bpy", "bqi", "bre", "bra", "brh", "brx", "bos", "bss", "bua", "bug", "bum", "byn", "byv", "cat", "cad", "car", "cay", "cch", "ccp", "che", "ceb", "cgg", "cha", "chb", "chg", "chk", "chm", "chn", "cho", "chp", "chr", "chy", "ckb", "cos", "cop", "cps", "cre", "crh", - "ces", "csb", "chu", "chv", "cym", + "ces", "csb", "csw", "chu", "chv", "cym", "dan", "dak", "dar", "dav", "deu", "del", "den", "dgr", "din", "dje", "doi", "dsb", "dtp", "dua", "dum", "div", "dyo", "dyu", "dzo", "dzg", @@ -252,7 +252,7 @@ static const char * const LANGUAGES_3[] = { "kkj", "kal", "kln", "khm", "kmb", "kan", "kor", "koi", "kok", "kos", "kpe", "kau", "krc", "kri", "krj", "krl", "kru", "kas", "ksb", "ksf", "ksh", "kur", "kum", "kut", - "kom", "cor", "kir", + "kom", "cor", "kxv", "kir", "lat", "lad", "lag", "lah", "lam", "ltz", "lez", "lfn", "lug", "lim", "lij", "liv", "lkt", "lmo", "lin", "lao", "lol", "loz", "lrc", "lit", "ltg", "lub", "lua", "lui", @@ -286,14 +286,14 @@ static const char * const LANGUAGES_3[] = { "swe", "swa", "swb", "syc", "syr", "szl", "tam", "tcy", "tel", "tem", "teo", "ter", "tet", "tgk", "tha", "tir", "tig", "tiv", "tuk", "tkl", "tkr", - "tlh", "tli", "tly", "tmh", "tsn", "ton", "tog", "tpi", + "tlh", "tli", "tly", "tmh", "tsn", "ton", "tog", "tok", "tpi", "tur", "tru", "trv", "tso", "tsd", "tsi", "tat", "ttt", "tum", "tvl", "twi", "twq", "tah", "tyv", "tzm", "udm", "uig", "uga", "ukr", "umb", "und", "urd", "uzb", - "vai", "ven", "vec", "vep", "vie", "vls", "vmf", "vol", - "vot", "vro", "vun", + "vai", "ven", "vec", "vep", "vie", "vls", "vmf", "vmw", + "vol", "vot", "vro", "vun", "wln", "wae", "wal", "war", "was", "wbp", "wol", "wuu", - "xal", "xho", "xmf", "xog", + "xal", "xho", "xmf", "xnr", "xog", "yao", "yap", "yav", "ybb", "yid", "yor", "yrl", "yue", "zha", "zap", "zbl", "zea", "zen", "zgh", "zho", "zul", "zun", "zxx", "zza", @@ -477,25 +477,6 @@ static const CanonicalizationMap CANONICALIZE_MAP[] = { /* ### BCP47 Conversion *******************************************/ /* Test if the locale id has BCP47 u extension and does not have '@' */ #define _hasBCP47Extension(id) (id && uprv_strstr(id, "@") == nullptr && getShortestSubtagLength(localeID) == 1) -/* Converts the BCP47 id to Unicode id. Does nothing to id if conversion fails */ -static const char* _ConvertBCP47( - const char* id, char* buffer, int32_t length, - UErrorCode* err, int32_t* pLocaleIdSize) { - const char* finalID; - int32_t localeIDSize = uloc_forLanguageTag(id, buffer, length, nullptr, err); - if (localeIDSize <= 0 || U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) { - finalID=id; - if (*err == U_STRING_NOT_TERMINATED_WARNING) { - *err = U_BUFFER_OVERFLOW_ERROR; - } - } else { - finalID=buffer; - } - if (pLocaleIdSize != nullptr) { - *pLocaleIdSize = localeIDSize; - } - return finalID; -} /* Gets the size of the shortest subtag in the given localeID. */ static int32_t getShortestSubtagLength(const char *localeID) { int32_t localeIDLength = static_cast<int32_t>(uprv_strlen(localeID)); @@ -762,7 +743,7 @@ ulocimp_getKeywordValue(const char* localeID, char localeKeywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN]; if(status && U_SUCCESS(*status) && localeID) { - char tempBuffer[ULOC_FULLNAME_CAPACITY]; + CharString tempBuffer; const char* tmpLocaleID; if (keywordName == nullptr || keywordName[0] == 0) { @@ -776,8 +757,9 @@ ulocimp_getKeywordValue(const char* localeID, } if (_hasBCP47Extension(localeID)) { - tmpLocaleID = _ConvertBCP47(localeID, tempBuffer, - sizeof(tempBuffer), status, nullptr); + CharStringByteSink sink(&tempBuffer); + ulocimp_forLanguageTag(localeID, -1, sink, nullptr, status); + tmpLocaleID = U_SUCCESS(*status) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID; } else { tmpLocaleID=localeID; } @@ -1406,7 +1388,7 @@ U_CAPI UEnumeration* U_EXPORT2 uloc_openKeywords(const char* localeID, UErrorCode* status) { - char tempBuffer[ULOC_FULLNAME_CAPACITY]; + CharString tempBuffer; const char* tmpLocaleID; if(status==nullptr || U_FAILURE(*status)) { @@ -1414,8 +1396,9 @@ uloc_openKeywords(const char* localeID, } if (_hasBCP47Extension(localeID)) { - tmpLocaleID = _ConvertBCP47(localeID, tempBuffer, - sizeof(tempBuffer), status, nullptr); + CharStringByteSink sink(&tempBuffer); + ulocimp_forLanguageTag(localeID, -1, sink, nullptr, status); + tmpLocaleID = U_SUCCESS(*status) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID; } else { if (localeID==nullptr) { localeID=uloc_getDefault(); @@ -1489,7 +1472,7 @@ _canonicalize(const char* localeID, } int32_t j, fieldCount=0, scriptSize=0, variantSize=0; - PreflightingLocaleIDBuffer tempBuffer; // if localeID has a BCP47 extension, tmpLocaleID points to this + CharString tempBuffer; // if localeID has a BCP47 extension, tmpLocaleID points to this CharString localeIDWithHyphens; // if localeID has a BPC47 extension and have _, tmpLocaleID points to this const char* origLocaleID; const char* tmpLocaleID; @@ -1512,13 +1495,9 @@ _canonicalize(const char* localeID, } } - do { - // After this call tmpLocaleID may point to localeIDPtr which may - // point to either localeID or localeIDWithHyphens.data(). - tmpLocaleID = _ConvertBCP47(localeIDPtr, tempBuffer.getBuffer(), - tempBuffer.getCapacity(), err, - &(tempBuffer.requestedCapacity)); - } while (tempBuffer.needToTryAgain(err)); + CharStringByteSink tempSink(&tempBuffer); + ulocimp_forLanguageTag(localeIDPtr, -1, tempSink, nullptr, err); + tmpLocaleID = U_SUCCESS(*err) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeIDPtr; } else { if (localeID==nullptr) { localeID=uloc_getDefault(); @@ -1677,11 +1656,38 @@ uloc_getParent(const char* localeID, int32_t parentCapacity, UErrorCode* err) { + if (U_FAILURE(*err)) { + return 0; + } + + CheckedArrayByteSink sink(parent, parentCapacity); + ulocimp_getParent(localeID, sink, err); + + int32_t reslen = sink.NumberOfBytesAppended(); + + if (U_FAILURE(*err)) { + return reslen; + } + + if (sink.Overflowed()) { + *err = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(parent, parentCapacity, reslen, err); + } + + return reslen; +} + +U_CAPI void U_EXPORT2 +ulocimp_getParent(const char* localeID, + icu::ByteSink& sink, + UErrorCode* err) +{ const char *lastUnderscore; int32_t i; if (U_FAILURE(*err)) - return 0; + return; if (localeID == nullptr) localeID = uloc_getDefault(); @@ -1697,13 +1703,9 @@ uloc_getParent(const char* localeID, if (uprv_strnicmp(localeID, "und_", 4) == 0) { localeID += 3; i -= 3; - uprv_memmove(parent, localeID, uprv_min(i, parentCapacity)); - } else if (parent != localeID) { - uprv_memcpy(parent, localeID, uprv_min(i, parentCapacity)); } + sink.Append(localeID, i); } - - return u_terminateChars(parent, parentCapacity, i, err); } U_CAPI int32_t U_EXPORT2 @@ -1795,7 +1797,7 @@ uloc_getVariant(const char* localeID, int32_t variantCapacity, UErrorCode* err) { - char tempBuffer[ULOC_FULLNAME_CAPACITY]; + CharString tempBuffer; const char* tmpLocaleID; int32_t i=0; @@ -1804,7 +1806,9 @@ uloc_getVariant(const char* localeID, } if (_hasBCP47Extension(localeID)) { - tmpLocaleID =_ConvertBCP47(localeID, tempBuffer, sizeof(tempBuffer), err, nullptr); + CharStringByteSink sink(&tempBuffer); + ulocimp_forLanguageTag(localeID, -1, sink, nullptr, err); + tmpLocaleID = U_SUCCESS(*err) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID; } else { if (localeID==nullptr) { localeID=uloc_getDefault(); diff --git a/thirdparty/icu4c/common/uloc_tag.cpp b/thirdparty/icu4c/common/uloc_tag.cpp index 43d597549f..fe3261c75d 100644 --- a/thirdparty/icu4c/common/uloc_tag.cpp +++ b/thirdparty/icu4c/common/uloc_tag.cpp @@ -1326,14 +1326,23 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st attrBufLength = 0; for (; i < len; i++) { if (buf[i] != '-') { - attrBuf[attrBufLength++] = buf[i]; + if (static_cast<size_t>(attrBufLength) < sizeof(attrBuf)) { + attrBuf[attrBufLength++] = buf[i]; + } else { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } } else { i++; break; } } if (attrBufLength > 0) { - attrBuf[attrBufLength] = 0; + if (static_cast<size_t>(attrBufLength) < sizeof(attrBuf)) { + attrBuf[attrBufLength] = 0; + } else { + *status = U_STRING_NOT_TERMINATED_WARNING; + } } else if (i >= len){ break; @@ -1879,11 +1888,8 @@ static void _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UBool hadPosix, UErrorCode* status) { (void)hadPosix; char buf[ULOC_FULLNAME_CAPACITY]; - char tmpAppend[ULOC_FULLNAME_CAPACITY]; UErrorCode tmpStatus = U_ZERO_ERROR; int32_t len, i; - int32_t reslen = 0; - int32_t capacity = sizeof tmpAppend; if (U_FAILURE(*status)) { return; @@ -1936,37 +1942,18 @@ _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool } if (writeValue) { - if (reslen < capacity) { - tmpAppend[reslen++] = SEP; - } + sink.Append("-", 1); if (firstValue) { - if (reslen < capacity) { - tmpAppend[reslen++] = *PRIVATEUSE_KEY; - } - - if (reslen < capacity) { - tmpAppend[reslen++] = SEP; - } - - len = (int32_t)uprv_strlen(PRIVUSE_VARIANT_PREFIX); - if (reslen < capacity) { - uprv_memcpy(tmpAppend + reslen, PRIVUSE_VARIANT_PREFIX, uprv_min(len, capacity - reslen)); - } - reslen += len; - - if (reslen < capacity) { - tmpAppend[reslen++] = SEP; - } - + sink.Append(PRIVATEUSE_KEY, UPRV_LENGTHOF(PRIVATEUSE_KEY) - 1); + sink.Append("-", 1); + sink.Append(PRIVUSE_VARIANT_PREFIX, UPRV_LENGTHOF(PRIVUSE_VARIANT_PREFIX) - 1); + sink.Append("-", 1); firstValue = false; } len = (int32_t)uprv_strlen(pPriv); - if (reslen < capacity) { - uprv_memcpy(tmpAppend + reslen, pPriv, uprv_min(len, capacity - reslen)); - } - reslen += len; + sink.Append(pPriv, len); } } /* reset private use starting position */ @@ -1976,15 +1963,6 @@ _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool } p++; } - - if (U_FAILURE(*status)) { - return; - } - } - - if (U_SUCCESS(*status)) { - len = reslen; - sink.Append(tmpAppend, len); } } @@ -2092,12 +2070,13 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta int32_t oldTagLength = tagLen; if (tagLen < newTagLength) { uprv_free(tagBuf); - tagBuf = (char*)uprv_malloc(newTagLength + 1); + // Change t->buf after the free and before return to avoid the second double free in + // the destructor of t when t is out of scope. + t->buf = tagBuf = (char*)uprv_malloc(newTagLength + 1); if (tagBuf == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; return nullptr; } - t->buf = tagBuf; tagLen = newTagLength; } parsedLenDelta = checkLegacyLen - replacementLen; @@ -2646,53 +2625,18 @@ ulocimp_toLanguageTag(const char* localeID, UBool strict, UErrorCode* status) { icu::CharString canonical; - int32_t reslen; UErrorCode tmpStatus = U_ZERO_ERROR; UBool hadPosix = false; const char* pKeywordStart; /* Note: uloc_canonicalize returns "en_US_POSIX" for input locale ID "". See #6835 */ - int32_t resultCapacity = static_cast<int32_t>(uprv_strlen(localeID)); - if (resultCapacity > 0) { - char* buffer; - - for (;;) { - buffer = canonical.getAppendBuffer( - /*minCapacity=*/resultCapacity, - /*desiredCapacityHint=*/resultCapacity, - resultCapacity, - tmpStatus); - - if (U_FAILURE(tmpStatus)) { - *status = tmpStatus; - return; - } - - reslen = - uloc_canonicalize(localeID, buffer, resultCapacity, &tmpStatus); - - if (tmpStatus != U_BUFFER_OVERFLOW_ERROR) { - break; - } - - resultCapacity = reslen; - tmpStatus = U_ZERO_ERROR; - } - - if (U_FAILURE(tmpStatus)) { - *status = U_ILLEGAL_ARGUMENT_ERROR; - return; - } - - canonical.append(buffer, reslen, tmpStatus); - if (tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { - tmpStatus = U_ZERO_ERROR; // Terminators provided by CharString. - } - - if (U_FAILURE(tmpStatus)) { - *status = tmpStatus; - return; - } + { + icu::CharStringByteSink canonicalSink(&canonical); + ulocimp_canonicalize(localeID, canonicalSink, &tmpStatus); + } + if (U_FAILURE(tmpStatus)) { + *status = tmpStatus; + return; } /* For handling special case - private use only tag */ diff --git a/thirdparty/icu4c/common/ulocale.cpp b/thirdparty/icu4c/common/ulocale.cpp new file mode 100644 index 0000000000..471ef0ce79 --- /dev/null +++ b/thirdparty/icu4c/common/ulocale.cpp @@ -0,0 +1,99 @@ +// © 2023 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +#include "unicode/errorcode.h" +#include "unicode/stringpiece.h" +#include "unicode/utypes.h" +#include "unicode/ustring.h" +#include "unicode/ulocale.h" +#include "unicode/locid.h" + +#include "charstr.h" +#include "cmemory.h" +#include "ustr_imp.h" + +U_NAMESPACE_USE +#define EXTERNAL(i) (reinterpret_cast<ULocale*>(i)) +#define CONST_INTERNAL(e) (reinterpret_cast<const icu::Locale*>(e)) +#define INTERNAL(e) (reinterpret_cast<icu::Locale*>(e)) + +ULocale* +ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err) { + CharString str(length < 0 ? StringPiece(localeID) : StringPiece(localeID, length), *err); + if (U_FAILURE(*err)) return nullptr; + return EXTERNAL(icu::Locale::createFromName(str.data()).clone()); +} + +ULocale* +ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err) { + Locale l = icu::Locale::forLanguageTag(length < 0 ? StringPiece(tag) : StringPiece(tag, length), *err); + if (U_FAILURE(*err)) return nullptr; + return EXTERNAL(l.clone()); +} + +void +ulocale_close(ULocale* locale) { + delete INTERNAL(locale); +} + +#define IMPL_ULOCALE_STRING_GETTER(N1, N2) \ +const char* ulocale_get ## N1(const ULocale* locale) { \ + if (locale == nullptr) return nullptr; \ + return CONST_INTERNAL(locale)->get ## N2(); \ +} + +#define IMPL_ULOCALE_STRING_IDENTICAL_GETTER(N) IMPL_ULOCALE_STRING_GETTER(N, N) + +#define IMPL_ULOCALE_GET_KEYWORD_VALUE(N) \ +int32_t ulocale_get ##N ( \ + const ULocale* locale, const char* keyword, int32_t keywordLength, \ + char* valueBuffer, int32_t bufferCapacity, UErrorCode *err) { \ + if (U_FAILURE(*err)) return 0; \ + if (locale == nullptr) { \ + *err = U_ILLEGAL_ARGUMENT_ERROR; \ + return 0; \ + } \ + CheckedArrayByteSink sink(valueBuffer, bufferCapacity); \ + CONST_INTERNAL(locale)->get ## N( \ + keywordLength < 0 ? StringPiece(keyword) : StringPiece(keyword, keywordLength), \ + sink, *err); \ + int32_t reslen = sink.NumberOfBytesAppended(); \ + if (U_FAILURE(*err)) { \ + return reslen; \ + } \ + if (sink.Overflowed()) { \ + *err = U_BUFFER_OVERFLOW_ERROR; \ + } else { \ + u_terminateChars(valueBuffer, bufferCapacity, reslen, err); \ + } \ + return reslen; \ +} + +#define IMPL_ULOCALE_GET_KEYWORDS(N) \ +UEnumeration* ulocale_get ## N(const ULocale* locale, UErrorCode *err) { \ + if (U_FAILURE(*err)) return nullptr; \ + if (locale == nullptr) { \ + *err = U_ILLEGAL_ARGUMENT_ERROR; \ + return nullptr; \ + } \ + return uenum_openFromStringEnumeration( \ + CONST_INTERNAL(locale)->create ## N(*err), err); \ +} + +IMPL_ULOCALE_STRING_IDENTICAL_GETTER(Language) +IMPL_ULOCALE_STRING_IDENTICAL_GETTER(Script) +IMPL_ULOCALE_STRING_GETTER(Region, Country) +IMPL_ULOCALE_STRING_IDENTICAL_GETTER(Variant) +IMPL_ULOCALE_STRING_GETTER(LocaleID, Name) +IMPL_ULOCALE_STRING_IDENTICAL_GETTER(BaseName) +IMPL_ULOCALE_GET_KEYWORD_VALUE(KeywordValue) +IMPL_ULOCALE_GET_KEYWORD_VALUE(UnicodeKeywordValue) +IMPL_ULOCALE_GET_KEYWORDS(Keywords) +IMPL_ULOCALE_GET_KEYWORDS(UnicodeKeywords) + +bool ulocale_isBogus(const ULocale* locale) { + if (locale == nullptr) return false; + return CONST_INTERNAL(locale)->isBogus(); +} + +/*eof*/ diff --git a/thirdparty/icu4c/common/ulocbuilder.cpp b/thirdparty/icu4c/common/ulocbuilder.cpp new file mode 100644 index 0000000000..a5af73bef4 --- /dev/null +++ b/thirdparty/icu4c/common/ulocbuilder.cpp @@ -0,0 +1,156 @@ +// © 2023 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include <utility> + +#include "unicode/bytestream.h" +#include "unicode/localebuilder.h" +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/umachine.h" +#include "unicode/ulocbuilder.h" +#include "cstring.h" +#include "ustr_imp.h" + +using icu::CheckedArrayByteSink; +using icu::StringPiece; + +#define EXTERNAL(i) (reinterpret_cast<ULocaleBuilder*>(i)) +#define INTERNAL(e) (reinterpret_cast<icu::LocaleBuilder*>(e)) +#define CONST_INTERNAL(e) (reinterpret_cast<const icu::LocaleBuilder*>(e)) + +ULocaleBuilder* ulocbld_open() { + return EXTERNAL(new icu::LocaleBuilder()); +} + +void ulocbld_close(ULocaleBuilder* builder) { + if (builder == nullptr) return; + delete INTERNAL(builder); +} + +void ulocbld_setLocale(ULocaleBuilder* builder, const char* locale, int32_t length) { + if (builder == nullptr) return; + icu::Locale l; + if (length < 0 || locale[length] == '\0') { + l = icu::Locale(locale); + } else { + if (length >= ULOC_FULLNAME_CAPACITY) { + l.setToBogus(); + } else { + // locale is not null termined but Locale API require one. + // Create a null termined version in buf. + char buf[ULOC_FULLNAME_CAPACITY]; + uprv_memcpy(buf, locale, length); + buf[length] = '\0'; + l = icu::Locale(buf); + } + } + INTERNAL(builder)->setLocale(l); +} + +void +ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale) { + if (builder == nullptr) return; + INTERNAL(builder)->setLocale(*(reinterpret_cast<const icu::Locale*>(locale))); + ulocale_close(locale); +} + +#define STRING_PIECE(s, l) ((l)<0 ? StringPiece(s) : StringPiece((s), (l))) + +#define IMPL_ULOCBLD_SETTER(N) \ +void ulocbld_##N(ULocaleBuilder* bld, const char* s, int32_t l) { \ + if (bld == nullptr) return; \ + INTERNAL(bld)->N(STRING_PIECE(s,l)); \ +} + +IMPL_ULOCBLD_SETTER(setLanguageTag) +IMPL_ULOCBLD_SETTER(setLanguage) +IMPL_ULOCBLD_SETTER(setScript) +IMPL_ULOCBLD_SETTER(setRegion) +IMPL_ULOCBLD_SETTER(setVariant) +IMPL_ULOCBLD_SETTER(addUnicodeLocaleAttribute) +IMPL_ULOCBLD_SETTER(removeUnicodeLocaleAttribute) + +void ulocbld_setExtension(ULocaleBuilder* builder, char key, const char* value, int32_t length) { + if (builder == nullptr) return; + INTERNAL(builder)->setExtension(key, STRING_PIECE(value, length)); +} + +void ulocbld_setUnicodeLocaleKeyword( + ULocaleBuilder* builder, const char* key, int32_t keyLength, + const char* type, int32_t typeLength) { + if (builder == nullptr) return; + INTERNAL(builder)->setUnicodeLocaleKeyword( + STRING_PIECE(key, keyLength), STRING_PIECE(type, typeLength)); +} + +void ulocbld_clear(ULocaleBuilder* builder) { + if (builder == nullptr) return; + INTERNAL(builder)->clear(); +} + +void ulocbld_clearExtensions(ULocaleBuilder* builder) { + if (builder == nullptr) return; + INTERNAL(builder)->clearExtensions(); +} + + +ULocale* ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err) { + if (builder == nullptr) { + *err = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + icu::Locale l = INTERNAL(builder)->build(*err); + if (U_FAILURE(*err)) return nullptr; + icu::Locale* r = l.clone(); + if (r == nullptr) { + *err = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + return reinterpret_cast<ULocale*>(r); +} + +int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder, + char* buffer, int32_t bufferCapacity, UErrorCode* err) { + if (builder == nullptr) { + *err = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + icu::Locale l = INTERNAL(builder)->build(*err); + if (U_FAILURE(*err)) return 0; + int32_t length = (int32_t)(uprv_strlen(l.getName())); + if (0 < length && length <= bufferCapacity) { + uprv_memcpy(buffer, l.getName(), length); + } + return u_terminateChars(buffer, bufferCapacity, length, err); +} + +int32_t ulocbld_buildLanguageTag(ULocaleBuilder* builder, + char* buffer, int32_t bufferCapacity, UErrorCode* err) { + if (builder == nullptr) { + *err = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + icu::Locale l = INTERNAL(builder)->build(*err); + if (U_FAILURE(*err)) return 0; + CheckedArrayByteSink sink(buffer, bufferCapacity); + l.toLanguageTag(sink, *err); + int32_t reslen = sink.NumberOfBytesAppended(); + if (U_FAILURE(*err)) { + return reslen; + } + if (sink.Overflowed()) { + *err = U_BUFFER_OVERFLOW_ERROR; + } else { + u_terminateChars(buffer, bufferCapacity, reslen, err); + } + return reslen; +} + +UBool ulocbld_copyErrorTo(const ULocaleBuilder* builder, UErrorCode *outErrorCode) { + if (builder == nullptr) { + *outErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return true; + } + return CONST_INTERNAL(builder)->copyErrorTo(*outErrorCode); +} diff --git a/thirdparty/icu4c/common/ulocimp.h b/thirdparty/icu4c/common/ulocimp.h index 48341054e3..efa0fa72e6 100644 --- a/thirdparty/icu4c/common/ulocimp.h +++ b/thirdparty/icu4c/common/ulocimp.h @@ -92,6 +92,11 @@ ulocimp_getKeywordValue(const char* localeID, icu::ByteSink& sink, UErrorCode* status); +U_CAPI void U_EXPORT2 +ulocimp_getParent(const char* localeID, + icu::ByteSink& sink, + UErrorCode* err); + /** * Writes a well-formed language tag for this locale ID. * @@ -237,6 +242,7 @@ ulocimp_addLikelySubtags(const char* localeID, * * @param localeID The locale to minimize * @param sink The output sink receiving the maximized locale + * @param favorScript favor to keep script if true, region if false. * @param err Error information if minimizing the locale failed. If the length * of the localeID and the null-terminator is greater than the maximum allowed size, * or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR. @@ -245,6 +251,7 @@ ulocimp_addLikelySubtags(const char* localeID, U_CAPI void U_EXPORT2 ulocimp_minimizeSubtags(const char* localeID, icu::ByteSink& sink, + bool favorScript, UErrorCode* err); U_CAPI const char * U_EXPORT2 @@ -307,72 +314,4 @@ U_CAPI const char* const* ulocimp_getKnownCanonicalizedLocaleForTest(int32_t* le // Return true if the value is already canonicalized. U_CAPI bool ulocimp_isCanonicalizedLocaleForTest(const char* localeName); -/** - * A utility class for handling locale IDs that may be longer than ULOC_FULLNAME_CAPACITY. - * This encompasses all of the logic to allocate a temporary locale ID buffer on the stack, - * and then, if it's not big enough, reallocate it on the heap and try again. - * - * You use it like this: - * UErrorCode err = U_ZERO_ERROR; - * - * PreflightingLocaleIDBuffer tempBuffer; - * do { - * tempBuffer.requestedCapacity = uloc_doSomething(localeID, tempBuffer.getBuffer(), tempBuffer.getCapacity(), &err); - * } while (tempBuffer.needToTryAgain(&err)); - * if (U_SUCCESS(err)) { - * uloc_doSomethingWithTheResult(tempBuffer.getBuffer()); - * } - */ -class PreflightingLocaleIDBuffer { -private: - char stackBuffer[ULOC_FULLNAME_CAPACITY]; - char* heapBuffer = nullptr; - int32_t capacity = ULOC_FULLNAME_CAPACITY; - -public: - int32_t requestedCapacity = ULOC_FULLNAME_CAPACITY; - - // No heap allocation. Use only on the stack. - static void* U_EXPORT2 operator new(size_t) noexcept = delete; - static void* U_EXPORT2 operator new[](size_t) noexcept = delete; -#if U_HAVE_PLACEMENT_NEW - static void* U_EXPORT2 operator new(size_t, void*) noexcept = delete; -#endif - - PreflightingLocaleIDBuffer() {} - - ~PreflightingLocaleIDBuffer() { uprv_free(heapBuffer); } - - char* getBuffer() { - if (heapBuffer == nullptr) { - return stackBuffer; - } else { - return heapBuffer; - } - } - - int32_t getCapacity() { - return capacity; - } - - bool needToTryAgain(UErrorCode* err) { - if (heapBuffer != nullptr) { - return false; - } - - if (*err == U_BUFFER_OVERFLOW_ERROR || *err == U_STRING_NOT_TERMINATED_WARNING) { - int32_t newCapacity = requestedCapacity + 2; // one for the terminating null, one just for paranoia - heapBuffer = static_cast<char*>(uprv_malloc(newCapacity)); - if (heapBuffer == nullptr) { - *err = U_MEMORY_ALLOCATION_ERROR; - } else { - *err = U_ZERO_ERROR; - capacity = newCapacity; - } - return U_SUCCESS(*err); - } - return false; - } -}; - #endif diff --git a/thirdparty/icu4c/common/unicode/brkiter.h b/thirdparty/icu4c/common/unicode/brkiter.h index 108652799e..1b10e6ef11 100644 --- a/thirdparty/icu4c/common/unicode/brkiter.h +++ b/thirdparty/icu4c/common/unicode/brkiter.h @@ -649,6 +649,7 @@ private: /** @internal (private) */ char actualLocale[ULOC_FULLNAME_CAPACITY]; char validLocale[ULOC_FULLNAME_CAPACITY]; + char requestLocale[ULOC_FULLNAME_CAPACITY]; }; #ifndef U_HIDE_DEPRECATED_API diff --git a/thirdparty/icu4c/common/unicode/docmain.h b/thirdparty/icu4c/common/unicode/docmain.h index 1349f49703..581b2e186d 100644 --- a/thirdparty/icu4c/common/unicode/docmain.h +++ b/thirdparty/icu4c/common/unicode/docmain.h @@ -114,7 +114,7 @@ * </tr> * <tr> * <td>Locales </td> - * <td>uloc.h</a></td> + * <td>uloc.h, ulocale.h, ulocbuilder.h</a></td> * <td>icu::Locale, icu::LocaleBuilder, icu::LocaleMatcher</td> * </tr> * <tr> diff --git a/thirdparty/icu4c/common/unicode/locid.h b/thirdparty/icu4c/common/unicode/locid.h index a6fbbb7041..f0bdc7ca51 100644 --- a/thirdparty/icu4c/common/unicode/locid.h +++ b/thirdparty/icu4c/common/unicode/locid.h @@ -984,7 +984,10 @@ public: static const char* const* U_EXPORT2 getISOCountries(); /** - * Gets a list of all available language codes defined in ISO 639. This is a pointer + * Returns a list of all unique language codes defined in ISO 639. + * They can be 2 or 3 letter codes, as defined by + * <a href="https://www.ietf.org/rfc/bcp/bcp47.html#section-2.2.1"> + * BCP 47, section 2.2.1</a>. This is a pointer * to an array of pointers to arrays of char. All of these pointers are owned * by ICU-- do not delete them, and do not write through them. The array is * terminated with a null pointer. @@ -1110,6 +1113,15 @@ protected: /* only protected for testing purposes. DO NOT USE. */ * @internal */ void setFromPOSIXID(const char *posixID); + /** + * Minimize the subtags for this Locale, per the algorithm described + * @param favorScript favor to keep script if true, to keep region if false. + * @param status error information if maximizing this Locale failed. + * If this Locale is not well-formed, the error code is + * U_ILLEGAL_ARGUMENT_ERROR. + * @internal + */ + void minimizeSubtags(bool favorScript, UErrorCode& status); #endif /* U_HIDE_INTERNAL_API */ private: diff --git a/thirdparty/icu4c/common/unicode/normalizer2.h b/thirdparty/icu4c/common/unicode/normalizer2.h index 972894ec42..6856ff8720 100644 --- a/thirdparty/icu4c/common/unicode/normalizer2.h +++ b/thirdparty/icu4c/common/unicode/normalizer2.h @@ -147,7 +147,10 @@ public: getNFKDInstance(UErrorCode &errorCode); /** - * Returns a Normalizer2 instance for Unicode NFKC_Casefold normalization. + * Returns a Normalizer2 instance for Unicode toNFKC_Casefold() normalization + * which is equivalent to applying the NFKC_Casefold mappings and then NFC. + * See https://www.unicode.org/reports/tr44/#NFKC_Casefold + * * Same as getInstance(nullptr, "nfkc_cf", UNORM2_COMPOSE, errorCode). * Returns an unmodifiable singleton instance. Do not delete it. * @param errorCode Standard ICU error code. Its input value must @@ -160,6 +163,25 @@ public: static const Normalizer2 * getNFKCCasefoldInstance(UErrorCode &errorCode); +#ifndef U_HIDE_DRAFT_API + /** + * Returns a Normalizer2 instance for a variant of Unicode toNFKC_Casefold() normalization + * which is equivalent to applying the NFKC_Simple_Casefold mappings and then NFC. + * See https://www.unicode.org/reports/tr44/#NFKC_Simple_Casefold + * + * Same as getInstance(nullptr, "nfkc_scf", UNORM2_COMPOSE, errorCode). + * Returns an unmodifiable singleton instance. Do not delete it. + * @param errorCode Standard ICU error code. Its input value must + * pass the U_SUCCESS() test, or else the function returns + * immediately. Check for U_FAILURE() on output or use with + * function chaining. (See User Guide for details.) + * @return the requested Normalizer2, if successful + * @draft ICU 74 + */ + static const Normalizer2 * + getNFKCSimpleCasefoldInstance(UErrorCode &errorCode); +#endif // U_HIDE_DRAFT_API + /** * Returns a Normalizer2 instance which uses the specified data file * (packageName/name similar to ucnv_openPackage() and ures_open()/ResourceBundle) @@ -172,7 +194,7 @@ public: * Use name="nfkc_cf" and UNORM2_COMPOSE for Unicode standard NFKC_CF=NFKC_Casefold. * * @param packageName nullptr for ICU built-in data, otherwise application data package name - * @param name "nfc" or "nfkc" or "nfkc_cf" or name of custom data file + * @param name "nfc" or "nfkc" or "nfkc_cf" or "nfkc_scf" or name of custom data file * @param mode normalization mode (compose or decompose etc.) * @param errorCode Standard ICU error code. Its input value must * pass the U_SUCCESS() test, or else the function returns diff --git a/thirdparty/icu4c/common/unicode/rbbi.h b/thirdparty/icu4c/common/unicode/rbbi.h index 418b52e41f..045238ac5d 100644 --- a/thirdparty/icu4c/common/unicode/rbbi.h +++ b/thirdparty/icu4c/common/unicode/rbbi.h @@ -43,6 +43,69 @@ class RBBIDataWrapper; class UnhandledEngine; class UStack; + +#ifndef U_HIDE_DRAFT_API +/** + * The ExternalBreakEngine class define an abstract interface for the host environment + * to provide a low level facility to break text for unicode text in script that the text boundary + * cannot be handled by upper level rule based logic, for example, for Chinese and Japanese + * word breaking, Thai, Khmer, Burmese, Lao and other Southeast Asian scripts. + * The host environment implement one or more subclass of ExternalBreakEngine and + * register them in the initialization time by calling + * RuleBasedBreakIterator::registerExternalBreakEngine(). ICU adopt and own the engine and will + * delete the registered external engine in proper time during the clean up + * event. + * @internal ICU 74 technology preview + */ +class ExternalBreakEngine : public UObject { + public: + /** + * destructor + * @internal ICU 74 technology preview + */ + virtual ~ExternalBreakEngine() {} + + /** + * <p>Indicate whether this engine handles a particular character when + * the RuleBasedBreakIterator is used for a particular locale. This method is used + * by the RuleBasedBreakIterator to find a break engine.</p> + * @param c A character which begins a run that the engine might handle. + * @param locale The locale. + * @return true if this engine handles the particular character for that locale. + * @internal ICU 74 technology preview + */ + virtual bool isFor(UChar32 c, const char* locale) const = 0; + + /** + * <p>Indicate whether this engine handles a particular character.This method is + * used by the RuleBasedBreakIterator after it already find a break engine to see which + * characters after the first one can be handled by this break engine.</p> + * @param c A character that the engine might handle. + * @return true if this engine handles the particular character. + * @internal ICU 74 technology preview + */ + virtual bool handles(UChar32 c) const = 0; + + /** + * <p>Divide up a range of text handled by this break engine.</p> + * + * @param text A UText representing the text + * @param start The start of the range of known characters + * @param end The end of the range of known characters + * @param foundBreaks Output of C array of int32_t break positions, or + * nullptr + * @param foundBreaksCapacity The capacity of foundBreaks + * @param status Information on any errors encountered. + * @return The number of breaks found + * @internal ICU 74 technology preview + */ + virtual int32_t fillBreaks(UText* text, int32_t start, int32_t end, + int32_t* foundBreaks, int32_t foundBreaksCapacity, + UErrorCode& status) const = 0; +}; +#endif /* U_HIDE_DRAFT_API */ + + /** * * A subclass of BreakIterator whose behavior is specified using a list of rules. @@ -716,9 +779,10 @@ private: * This function returns the appropriate LanguageBreakEngine for a * given character c. * @param c A character in the dictionary set + * @param locale The locale. * @internal (private) */ - const LanguageBreakEngine *getLanguageBreakEngine(UChar32 c); + const LanguageBreakEngine *getLanguageBreakEngine(UChar32 c, const char* locale); public: #ifndef U_HIDE_INTERNAL_API @@ -734,8 +798,24 @@ private: */ void dumpTables(); #endif /* U_HIDE_INTERNAL_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Register a new external break engine. The external break engine will be adopted. + * Because ICU may choose to cache break engine internally, this must + * be called at application startup, prior to any calls to + * object methods of RuleBasedBreakIterator to avoid undefined behavior. + * @param toAdopt the ExternalBreakEngine instance to be adopted + * @param status the in/out status code, no special meanings are assigned + * @internal ICU 74 technology preview + */ + static void U_EXPORT2 registerExternalBreakEngine( + ExternalBreakEngine* toAdopt, UErrorCode& status); +#endif /* U_HIDE_DRAFT_API */ + }; + U_NAMESPACE_END #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ diff --git a/thirdparty/icu4c/common/unicode/uchar.h b/thirdparty/icu4c/common/unicode/uchar.h index 4f82a9fb58..7470891338 100644 --- a/thirdparty/icu4c/common/unicode/uchar.h +++ b/thirdparty/icu4c/common/unicode/uchar.h @@ -60,7 +60,7 @@ U_CDECL_BEGIN * @see u_getUnicodeVersion * @stable ICU 2.0 */ -#define U_UNICODE_VERSION "15.0" +#define U_UNICODE_VERSION "15.1" /** * \file @@ -532,12 +532,33 @@ typedef enum UProperty { * @stable ICU 70 */ UCHAR_RGI_EMOJI=71, +#ifndef U_HIDE_DRAFT_API + /** + * Binary property IDS_Unary_Operator. + * For programmatic determination of Ideographic Description Sequences. + * + * @draft ICU 74 + */ + UCHAR_IDS_UNARY_OPERATOR=72, + /** + * Binary property ID_Compat_Math_Start. + * Used in mathematical identifier profile in UAX #31. + * @draft ICU 74 + */ + UCHAR_ID_COMPAT_MATH_START=73, + /** + * Binary property ID_Compat_Math_Continue. + * Used in mathematical identifier profile in UAX #31. + * @draft ICU 74 + */ + UCHAR_ID_COMPAT_MATH_CONTINUE=74, +#endif // U_HIDE_DRAFT_API #ifndef U_HIDE_DEPRECATED_API /** * One more than the last constant for binary Unicode properties. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UCHAR_BINARY_LIMIT=72, + UCHAR_BINARY_LIMIT=75, #endif // U_HIDE_DEPRECATED_API /** Enumerated property Bidi_Class. @@ -1900,6 +1921,11 @@ enum UBlockCode { /** @stable ICU 72 */ UBLOCK_NAG_MUNDARI = 327, /*[1E4D0]*/ + // New block in Unicode 15.1 + + /** @stable ICU 74 */ + UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_I = 328, /*[2EBF0]*/ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UBlockCode value. @@ -1907,7 +1933,7 @@ enum UBlockCode { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UBLOCK_COUNT = 328, + UBLOCK_COUNT = 329, #endif // U_HIDE_DEPRECATED_API /** @stable ICU 2.0 */ @@ -2439,6 +2465,16 @@ typedef enum ULineBreak { U_LB_E_MODIFIER = 41, /*[EM]*/ /** @stable ICU 58 */ U_LB_ZWJ = 42, /*[ZWJ]*/ + /** @stable ICU 74 */ + U_LB_AKSARA = 43, /*[AK]*/ + /** @stable ICU 74 */ + U_LB_AKSARA_PREBASE = 44, /*[AP]*/ + /** @stable ICU 74 */ + U_LB_AKSARA_START = 45, /*[AS]*/ + /** @stable ICU 74 */ + U_LB_VIRAMA_FINAL = 46, /*[VF]*/ + /** @stable ICU 74 */ + U_LB_VIRAMA = 47, /*[VI]*/ #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal ULineBreak value. @@ -2446,7 +2482,7 @@ typedef enum ULineBreak { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - U_LB_COUNT = 43 + U_LB_COUNT = 48 #endif // U_HIDE_DEPRECATED_API } ULineBreak; diff --git a/thirdparty/icu4c/common/unicode/ulocale.h b/thirdparty/icu4c/common/unicode/ulocale.h new file mode 100644 index 0000000000..33e92844bc --- /dev/null +++ b/thirdparty/icu4c/common/unicode/ulocale.h @@ -0,0 +1,229 @@ +// © 2023 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#ifndef ULOCALE_H +#define ULOCALE_H + +#include "unicode/localpointer.h" +#include "unicode/uenum.h" +#include "unicode/utypes.h" + +/** + * \file + * \brief C API: Locale ID functionality similar to C++ class Locale + */ + +#ifndef U_HIDE_DRAFT_API +/** + * Opaque C service object type for the locale API + * @draft ICU 74 + */ +struct ULocale; + +/** + * C typedef for struct ULocale. + * @draft ICU 74 + */ +typedef struct ULocale ULocale; + +/** + * Constructs an ULocale from the locale ID. + * The created ULocale should be destroyed by calling + * ulocale_close(); + * @param localeID the locale, a const char * pointer (need not be terminated when + * the length is non-negative) + * @param length the length of the locale; if negative, then the locale need to be + * null terminated. + * @param err the error code + * @return the locale. + * + * @draft ICU 74 + */ +U_CAPI ULocale* U_EXPORT2 +ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err); + +/** + * Constructs an ULocale from the provided IETF BCP 47 language tag. + * The created ULocale should be destroyed by calling + * ulocale_close(); + * @param tag the language tag, defined as IETF BCP 47 language tag, const + * char* pointer (need not be terminated when the length is non-negative) + * @param length the length of the tag; if negative, then the tag need to be + * null terminated. + * @param err the error code + * @return the locale. + * + * @draft ICU 74 + */ +U_CAPI ULocale* U_EXPORT2 +ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err); + +/** + * Close the locale and destroy it's internal states. + * + * @param locale the locale + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocale_close(ULocale* locale); + +/** + * Returns the locale's ISO-639 language code. + * + * @param locale the locale + * @return the language code of the locale. + * @draft ICU 74 + */ +U_CAPI const char* U_EXPORT2 +ulocale_getLanguage(const ULocale* locale); + +/** + * Returns the locale's ISO-15924 abbreviation script code. + * + * @param locale the locale + * @return A pointer to the script. + * @draft ICU 74 + */ +U_CAPI const char* U_EXPORT2 +ulocale_getScript(const ULocale* locale); + +/** + * Returns the locale's ISO-3166 region code. + * + * @param locale the locale + * @return A pointer to the region. + * @draft ICU 74 + */ +U_CAPI const char* U_EXPORT2 +ulocale_getRegion(const ULocale* locale); + +/** + * Returns the locale's variant code. + * + * @param locale the locale + * @return A pointer to the variant. + * @draft ICU 74 + */ +U_CAPI const char* U_EXPORT2 +ulocale_getVariant(const ULocale* locale); + +/** + * Returns the programmatic name of the entire locale, with the language, + * country and variant separated by underbars. If a field is missing, up + * to two leading underbars will occur. Example: "en", "de_DE", "en_US_WIN", + * "de__POSIX", "fr__MAC", "__MAC", "_MT", "_FR_EURO" + * + * @param locale the locale + * @return A pointer to "name". + * @draft ICU 74 + */ +U_CAPI const char* U_EXPORT2 +ulocale_getLocaleID(const ULocale* locale); + +/** + * Returns the programmatic name of the entire locale as ulocale_getLocaleID() + * would return, but without keywords. + * + * @param locale the locale + * @return A pointer to "base name". + * @draft ICU 74 + */ +U_CAPI const char* U_EXPORT2 +ulocale_getBaseName(const ULocale* locale); + +/** + * Gets the bogus state. Locale object can be bogus if it doesn't exist + * + * @param locale the locale + * @return false if it is a real locale, true if it is a bogus locale + * @draft ICU 74 + */ +U_CAPI bool U_EXPORT2 +ulocale_isBogus(const ULocale* locale); + +/** + * Gets the list of keywords for the specified locale. + * + * @param locale the locale + * @param err the error code + * @return pointer to UEnumeration, or nullptr if there are no keywords. + * Client must call uenum_close() to dispose the returned value. + * @draft ICU 74 + */ +U_CAPI UEnumeration* U_EXPORT2 +ulocale_getKeywords(const ULocale* locale, UErrorCode *err); + +/** + * Gets the list of unicode keywords for the specified locale. + * + * @param locale the locale + * @param err the error code + * @return pointer to UEnumeration, or nullptr if there are no keywords. + * Client must call uenum_close() to dispose the returned value. + * @draft ICU 74 + */ +U_CAPI UEnumeration* U_EXPORT2 +ulocale_getUnicodeKeywords(const ULocale* locale, UErrorCode *err); + +/** + * Gets the value for a keyword. + * + * This uses legacy keyword=value pairs, like "collation=phonebook". + * + * @param locale the locale + * @param keyword the keyword, a const char * pointer (need not be + * terminated when the length is non-negative) + * @param keywordLength the length of the keyword; if negative, then the + * keyword need to be null terminated. + * @param valueBuffer The buffer to receive the value. + * @param valueBufferCapacity The capacity of receiving valueBuffer. + * @param err the error code + * @draft ICU 74 + */ +U_CAPI int32_t U_EXPORT2 +ulocale_getKeywordValue( + const ULocale* locale, const char* keyword, int32_t keywordLength, + char* valueBuffer, int32_t valueBufferCapacity, UErrorCode *err); + +/** + * Gets the Unicode value for a Unicode keyword. + * + * This uses Unicode key-value pairs, like "co-phonebk". + * + * @param locale the locale + * @param keyword the Unicode keyword, a const char * pointer (need not be + * terminated when the length is non-negative) + * @param keywordLength the length of the Unicode keyword; if negative, + * then the keyword need to be null terminated. + * @param valueBuffer The buffer to receive the Unicode value. + * @param valueBufferCapacity The capacity of receiving valueBuffer. + * @param err the error code + * @draft ICU 74 + */ +U_CAPI int32_t U_EXPORT2 +ulocale_getUnicodeKeywordValue( + const ULocale* locale, const char* keyword, int32_t keywordLength, + char* valueBuffer, int32_t valueBufferCapacity, UErrorCode *err); + +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalULocalePointer + * "Smart pointer" class, closes a ULocale via ulocale_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @draft ICU 74 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalULocalePointer, ULocale, ulocale_close); + +U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + +#endif /* U_HIDE_DRAFT_API */ + +#endif /*_ULOCALE */ diff --git a/thirdparty/icu4c/common/unicode/ulocbuilder.h b/thirdparty/icu4c/common/unicode/ulocbuilder.h new file mode 100644 index 0000000000..f2e98612f0 --- /dev/null +++ b/thirdparty/icu4c/common/unicode/ulocbuilder.h @@ -0,0 +1,441 @@ +// © 2023 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +#ifndef __ULOCBUILDER_H__ +#define __ULOCBUILDER_H__ + +#include "unicode/localpointer.h" +#include "unicode/ulocale.h" +#include "unicode/utypes.h" + +/** + * \file + * \brief C API: Builder API for Locale + */ + +#ifndef U_HIDE_DRAFT_API + +/** + * Opaque C service object type for the locale builder API + * @draft ICU 74 + */ +struct ULocaleBuilder; + +/** + * C typedef for struct ULocaleBuilder. + * @draft ICU 74 + */ +typedef struct ULocaleBuilder ULocaleBuilder; + +/** + * <code>ULocaleBuilder</code> is used to build valid <code>locale</code> id + * string or IETF BCP 47 language tag from values configured by the setters. + * The <code>ULocaleBuilder</code> checks if a value configured by a + * setter satisfies the syntax requirements defined by the <code>Locale</code> + * class. A string of Locale created by a <code>ULocaleBuilder</code> is + * well-formed and can be transformed to a well-formed IETF BCP 47 language tag + * without losing information. + * + * <p>The following example shows how to create a <code>locale</code> string + * with the <code>ULocaleBuilder</code>. + * <blockquote> + * <pre> + * UErrorCode err = U_ZERO_ERROR; + * char buffer[ULOC_FULLNAME_CAPACITY]; + * ULocaleBuilder* builder = ulocbld_open(); + * ulocbld_setLanguage(builder, "sr", -1); + * ulocbld_setScript(builder, "Latn", -1); + * ulocbld_setRegion(builder, "RS", -1); + * int32_t length = ulocbld_buildLocaleID( + * builder, buffer, ULOC_FULLNAME_CAPACITY, &error); + * ulocbld_close(builder); + * </pre> + * </blockquote> + * + * <p>ULocaleBuilders can be reused; <code>ulocbld_clear()</code> resets all + * fields to their default values. + * + * <p>ULocaleBuilder tracks errors in an internal UErrorCode. For all setters, + * except ulocbld_setLanguageTag and ulocbld_setLocale, ULocaleBuilder will return immediately + * if the internal UErrorCode is in error state. + * To reset internal state and error code, call clear method. + * The ulocbld_setLanguageTag and setLocale method will first clear the internal + * UErrorCode, then track the error of the validation of the input parameter + * into the internal UErrorCode. + * + * @draft ICU 74 + */ + +/** + * Constructs an empty ULocaleBuilder. The default value of all + * fields, extensions, and private use information is the + * empty string. The created builder should be destroyed by calling + * ulocbld_close(); + * + * @draft ICU 74 + */ +U_CAPI ULocaleBuilder* U_EXPORT2 +ulocbld_open(); + +/** + * Close the builder and destroy it's internal states. + * @param builder the builder + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_close(ULocaleBuilder* builder); + +/** + * Resets the <code>ULocaleBuilder</code> to match the provided + * <code>locale</code>. Existing state is discarded. + * + * <p>All fields of the locale must be well-formed. + * <p>This method clears the internal UErrorCode. + * + * @param builder the builder + * @param locale the locale, a const char * pointer (need not be terminated when + * the length is non-negative) + * @param length the length of the locale; if negative, then the locale need to be + * null terminated, + * + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_setLocale(ULocaleBuilder* builder, const char* locale, int32_t length); + +/** + * Resets the <code>ULocaleBuilder</code> to match the provided + * <code>ULocale</code>. Existing state is discarded. + * + * <p>The locale must be not bogus. + * <p>This method clears the internal UErrorCode. + * + * @param builder the builder. + * @param locale the locale, a ULocale* pointer. The builder adopts the locale + * after the call and the client must not delete it. + * + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale); + +/** + * Resets the ULocaleBuilder to match the provided IETF BCP 47 language tag. + * Discards the existing state. + * The empty string causes the builder to be reset, like {@link #ulocbld_clear}. + * Legacy language tags (marked as “Type: grandfathered” in BCP 47) + * are converted to their canonical form before being processed. + * Otherwise, the <code>language tag</code> must be well-formed, + * or else the ulocbld_buildLocaleID() and ulocbld_buildLanguageTag() methods + * will later report an U_ILLEGAL_ARGUMENT_ERROR. + * + * <p>This method clears the internal UErrorCode. + * + * @param builder the builder + * @param tag the language tag, defined as IETF BCP 47 language tag, a + * const char * pointer (need not be terminated when + * the length is non-negative) + * @param length the length of the tag; if negative, then the tag need to be + * null terminated, + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_setLanguageTag(ULocaleBuilder* builder, const char* tag, int32_t length); + +/** + * Sets the language. If <code>language</code> is the empty string, the + * language in this <code>ULocaleBuilder</code> is removed. Otherwise, the + * <code>language</code> must be well-formed, or else the ulocbld_buildLocaleID() + * and ulocbld_buildLanguageTag() methods will + * later report an U_ILLEGAL_ARGUMENT_ERROR. + * + * <p>The syntax of language value is defined as + * [unicode_language_subtag](http://www.unicode.org/reports/tr35/tr35.html#unicode_language_subtag). + * + * @param builder the builder + * @param language the language, a const char * pointer (need not be terminated when + * the length is non-negative) + * @param length the length of the language; if negative, then the language need to be + * null terminated, + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_setLanguage(ULocaleBuilder* builder, const char* language, int32_t length); + +/** + * Sets the script. If <code>script</code> is the empty string, the script in + * this <code>ULocaleBuilder</code> is removed. + * Otherwise, the <code>script</code> must be well-formed, or else the + * ulocbld_buildLocaleID() and ulocbld_buildLanguageTag() methods will later + * report an U_ILLEGAL_ARGUMENT_ERROR. + * + * <p>The script value is a four-letter script code as + * [unicode_script_subtag](http://www.unicode.org/reports/tr35/tr35.html#unicode_script_subtag) + * defined by ISO 15924 + * + * @param builder the builder + * @param script the script, a const char * pointer (need not be terminated when + * the length is non-negative) + * @param length the length of the script; if negative, then the script need to be + * null terminated, + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_setScript(ULocaleBuilder* builder, const char* script, int32_t length); + +/** + * Sets the region. If region is the empty string, the region in this + * <code>ULocaleBuilder</code> is removed. Otherwise, the <code>region</code> + * must be well-formed, or else the ulocbld_buildLocaleID() and + * ulocbld_buildLanguageTag() methods will later report an + * U_ILLEGAL_ARGUMENT_ERROR. + * + * <p>The region value is defined by + * [unicode_region_subtag](http://www.unicode.org/reports/tr35/tr35.html#unicode_region_subtag) + * as a two-letter ISO 3166 code or a three-digit UN M.49 area code. + * + * <p>The region value in the <code>Locale</code> created by the + * <code>ULocaleBuilder</code> is always normalized to upper case. + * + * @param builder the builder + * @param region the region, a const char * pointer (need not be terminated when + * the length is non-negative) + * @param length the length of the region; if negative, then the region need to be + * null terminated, + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_setRegion(ULocaleBuilder* builder, const char* region, int32_t length); + +/** + * Sets the variant. If variant is the empty string, the variant in this + * <code>ULocaleBuilder</code> is removed. Otherwise, the <code>variant</code> + * must be well-formed, or else the ulocbld_buildLocaleID() and + * ulocbld_buildLanguageTag() methods will later report an + * U_ILLEGAL_ARGUMENT_ERROR. + * + * <p><b>Note:</b> This method checks if <code>variant</code> + * satisfies the + * [unicode_variant_subtag](http://www.unicode.org/reports/tr35/tr35.html#unicode_variant_subtag) + * syntax requirements, and normalizes the value to lowercase letters. However, + * the <code>Locale</code> class does not impose any syntactic + * restriction on variant. To set an ill-formed variant, use a Locale constructor. + * If there are multiple unicode_variant_subtag, the caller must concatenate + * them with '-' as separator (ex: "foobar-fibar"). + * + * @param builder the builder + * @param variant the variant, a const char * pointer (need not be terminated when + * the length is non-negative) + * @param length the length of the variant; if negative, then the variant need to be + * null terminated, + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_setVariant(ULocaleBuilder* builder, const char* variant, int32_t length); + +/** + * Sets the extension for the given key. If the value is the empty string, + * the extension is removed. Otherwise, the <code>key</code> and + * <code>value</code> must be well-formed, or else the ulocbld_buildLocaleID() + * and ulocbld_buildLanguageTag() methods will + * later report an U_ILLEGAL_ARGUMENT_ERROR. + * + * <p><b>Note:</b> The key ('u') is used for the Unicode locale extension. + * Setting a value for this key replaces any existing Unicode locale key/type + * pairs with those defined in the extension. + * + * <p><b>Note:</b> The key ('x') is used for the private use code. To be + * well-formed, the value for this key needs only to have subtags of one to + * eight alphanumeric characters, not two to eight as in the general case. + * + * @param builder the builder + * @param key the extension key + * @param value the value, a const char * pointer (need not be terminated when + * the length is non-negative) + * @param length the length of the value; if negative, then the value need to be + * null terminated, + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_setExtension(ULocaleBuilder* builder, char key, const char* value, int32_t length); + +/** + * Sets the Unicode locale keyword type for the given key. If the type + * StringPiece is constructed with a nullptr, the keyword is removed. + * If the type is the empty string, the keyword is set without type subtags. + * Otherwise, the key and type must be well-formed, or else the + * ulocbld_buildLocaleID() and ulocbld_buildLanguageTag() methods will later + * report an U_ILLEGAL_ARGUMENT_ERROR. + * + * <p>Keys and types are converted to lower case. + * + * <p><b>Note</b>:Setting the 'u' extension via {@link #ulocbld_setExtension} + * replaces all Unicode locale keywords with those defined in the + * extension. + * + * @param builder the builder + * @param key the Unicode locale key, a const char * pointer (need not be + * terminated when the length is non-negative) + * @param keyLength the length of the key; if negative, then the key need to be + * null terminated, + * @param type the Unicode locale type, a const char * pointer (need not be + * terminated when the length is non-negative) + * @param typeLength the length of the type; if negative, then the type need to + * be null terminated, + * @return This builder. + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_setUnicodeLocaleKeyword(ULocaleBuilder* builder, + const char* key, int32_t keyLength, const char* type, int32_t typeLength); + +/** + * Adds a unicode locale attribute, if not already present, otherwise + * has no effect. The attribute must not be empty string and must be + * well-formed or U_ILLEGAL_ARGUMENT_ERROR will be set to status + * during the ulocbld_buildLocaleID() and ulocbld_buildLanguageTag() calls. + * + * @param builder the builder + * @param attribute the attribute, a const char * pointer (need not be + * terminated when the length is non-negative) + * @param length the length of the attribute; if negative, then the attribute + * need to be null terminated, + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_addUnicodeLocaleAttribute( + ULocaleBuilder* builder, const char* attribute, int32_t length); + +/** + * Removes a unicode locale attribute, if present, otherwise has no + * effect. The attribute must not be empty string and must be well-formed + * or U_ILLEGAL_ARGUMENT_ERROR will be set to status during the ulocbld_buildLocaleID() + * and ulocbld_buildLanguageTag() calls. + * + * <p>Attribute comparison for removal is case-insensitive. + * + * @param builder the builder + * @param attribute the attribute, a const char * pointer (need not be + * terminated when the length is non-negative) + * @param length the length of the attribute; if negative, then the attribute + * need to be null terminated, + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_removeUnicodeLocaleAttribute( + ULocaleBuilder* builder, const char* attribute, int32_t length); + +/** + * Resets the builder to its initial, empty state. + * <p>This method clears the internal UErrorCode. + * + * @param builder the builder + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_clear(ULocaleBuilder* builder); + +/** + * Resets the extensions to their initial, empty state. + * Language, script, region and variant are unchanged. + * + * @param builder the builder + * @draft ICU 74 + */ +U_CAPI void U_EXPORT2 +ulocbld_clearExtensions(ULocaleBuilder* builder); + +/** + * Build the LocaleID string from the fields set on this builder. + * If any set methods or during the ulocbld_buildLocaleID() call require memory + * allocation but fail U_MEMORY_ALLOCATION_ERROR will be set to status. + * If any of the fields set by the setters are not well-formed, the status + * will be set to U_ILLEGAL_ARGUMENT_ERROR. The state of the builder will + * not change after the ulocbld_buildLocaleID() call and the caller is + * free to keep using the same builder to build more locales. + * + * @param builder the builder + * @param locale the locale id + * @param localeCapacity the size of the locale buffer to store the locale id + * @param err the error code + * @return the length of the locale id in buffer + * @draft ICU 74 + */ +U_CAPI int32_t U_EXPORT2 +ulocbld_buildLocaleID(ULocaleBuilder* builder, char* locale, + int32_t localeCapacity, UErrorCode* err); + +/** + * Build the ULocale object from the fields set on this builder. + * If any set methods or during the ulocbld_buildULocale() call require memory + * allocation but fail U_MEMORY_ALLOCATION_ERROR will be set to status. + * If any of the fields set by the setters are not well-formed, the status + * will be set to U_ILLEGAL_ARGUMENT_ERROR. The state of the builder will + * not change after the ulocbld_buildULocale() call and the caller is + * free to keep using the same builder to build more locales. + * + * @param builder the builder. + * @param err the error code. + * @return the locale, a ULocale* pointer. The created ULocale must be + * destroyed by calling {@link ulocale_close}. + * @draft ICU 74 + */ +U_CAPI ULocale* U_EXPORT2 +ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err); + +/** + * Build the IETF BCP 47 language tag string from the fields set on this builder. + * If any set methods or during the ulocbld_buildLanguageTag() call require memory + * allocation but fail U_MEMORY_ALLOCATION_ERROR will be set to status. + * If any of the fields set by the setters are not well-formed, the status + * will be set to U_ILLEGAL_ARGUMENT_ERROR. The state of the builder will + * not change after the ulocbld_buildLanguageTag() call and the caller is free + * to keep using the same builder to build more locales. + * + * @param builder the builder + * @param language the language tag + * @param languageCapacity the size of the language buffer to store the language + * tag + * @param err the error code + * @return the length of the language tag in buffer + * @draft ICU 74 + */ +U_CAPI int32_t U_EXPORT2 +ulocbld_buildLanguageTag(ULocaleBuilder* builder, char* language, + int32_t languageCapacity, UErrorCode* err); + +/** + * Sets the UErrorCode if an error occurred while recording sets. + * Preserves older error codes in the outErrorCode. + * + * @param builder the builder + * @param outErrorCode Set to an error code that occurred while setting subtags. + * Unchanged if there is no such error or if outErrorCode + * already contained an error. + * @return true if U_FAILURE(*outErrorCode) + * @draft ICU 74 + */ +U_CAPI UBool U_EXPORT2 +ulocbld_copyErrorTo(const ULocaleBuilder* builder, UErrorCode *outErrorCode); + +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalULocaleBuilderPointer + * "Smart pointer" class, closes a ULocaleBuilder via ulocbld_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @draft ICU 74 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalULocaleBuilderPointer, ULocaleBuilder, ulocbld_close); + +U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + +#endif /* U_HIDE_DRAFT_API */ + +#endif // __ULOCBUILDER_H__ diff --git a/thirdparty/icu4c/common/unicode/unorm2.h b/thirdparty/icu4c/common/unicode/unorm2.h index 24417b7103..3844041f17 100644 --- a/thirdparty/icu4c/common/unicode/unorm2.h +++ b/thirdparty/icu4c/common/unicode/unorm2.h @@ -181,7 +181,10 @@ U_CAPI const UNormalizer2 * U_EXPORT2 unorm2_getNFKDInstance(UErrorCode *pErrorCode); /** - * Returns a UNormalizer2 instance for Unicode NFKC_Casefold normalization. + * Returns a UNormalizer2 instance for Unicode toNFKC_Casefold() normalization + * which is equivalent to applying the NFKC_Casefold mappings and then NFC. + * See https://www.unicode.org/reports/tr44/#NFKC_Casefold + * * Same as unorm2_getInstance(NULL, "nfkc_cf", UNORM2_COMPOSE, pErrorCode). * Returns an unmodifiable singleton instance. Do not delete it. * @param pErrorCode Standard ICU error code. Its input value must @@ -194,6 +197,25 @@ unorm2_getNFKDInstance(UErrorCode *pErrorCode); U_CAPI const UNormalizer2 * U_EXPORT2 unorm2_getNFKCCasefoldInstance(UErrorCode *pErrorCode); +#ifndef U_HIDE_DRAFT_API +/** + * Returns a UNormalizer2 instance for a variant of Unicode toNFKC_Casefold() normalization + * which is equivalent to applying the NFKC_Simple_Casefold mappings and then NFC. + * See https://www.unicode.org/reports/tr44/#NFKC_Simple_Casefold + * + * Same as unorm2_getInstance(NULL, "nfkc_scf", UNORM2_COMPOSE, pErrorCode). + * Returns an unmodifiable singleton instance. Do not delete it. + * @param pErrorCode Standard ICU error code. Its input value must + * pass the U_SUCCESS() test, or else the function returns + * immediately. Check for U_FAILURE() on output or use with + * function chaining. (See User Guide for details.) + * @return the requested Normalizer2, if successful + * @draft ICU 74 + */ +U_CAPI const UNormalizer2 * U_EXPORT2 +unorm2_getNFKCSimpleCasefoldInstance(UErrorCode *pErrorCode); +#endif // U_HIDE_DRAFT_API + /** * Returns a UNormalizer2 instance which uses the specified data file * (packageName/name similar to ucnv_openPackage() and ures_open()/ResourceBundle) @@ -206,7 +228,7 @@ unorm2_getNFKCCasefoldInstance(UErrorCode *pErrorCode); * Use name="nfkc_cf" and UNORM2_COMPOSE for Unicode standard NFKC_CF=NFKC_Casefold. * * @param packageName NULL for ICU built-in data, otherwise application data package name - * @param name "nfc" or "nfkc" or "nfkc_cf" or name of custom data file + * @param name "nfc" or "nfkc" or "nfkc_cf" or "nfkc_scf" or name of custom data file * @param mode normalization mode (compose or decompose etc.) * @param pErrorCode Standard ICU error code. Its input value must * pass the U_SUCCESS() test, or else the function returns diff --git a/thirdparty/icu4c/common/unicode/urename.h b/thirdparty/icu4c/common/unicode/urename.h index b35df45380..74f2cae510 100644 --- a/thirdparty/icu4c/common/unicode/urename.h +++ b/thirdparty/icu4c/common/unicode/urename.h @@ -138,8 +138,8 @@ #define locale_getKeywordsStart U_ICU_ENTRY_POINT_RENAME(locale_getKeywordsStart) #define locale_get_default U_ICU_ENTRY_POINT_RENAME(locale_get_default) #define locale_set_default U_ICU_ENTRY_POINT_RENAME(locale_set_default) +#define mixedMeasuresToMicros U_ICU_ENTRY_POINT_RENAME(mixedMeasuresToMicros) #define numSysCleanup U_ICU_ENTRY_POINT_RENAME(numSysCleanup) -#define rbbi_cleanup U_ICU_ENTRY_POINT_RENAME(rbbi_cleanup) #define pl_addFontRun U_ICU_ENTRY_POINT_RENAME(pl_addFontRun) #define pl_addLocaleRun U_ICU_ENTRY_POINT_RENAME(pl_addLocaleRun) #define pl_addValueRun U_ICU_ENTRY_POINT_RENAME(pl_addValueRun) @@ -193,6 +193,7 @@ #define pl_resetFontRuns U_ICU_ENTRY_POINT_RENAME(pl_resetFontRuns) #define pl_resetLocaleRuns U_ICU_ENTRY_POINT_RENAME(pl_resetLocaleRuns) #define pl_resetValueRuns U_ICU_ENTRY_POINT_RENAME(pl_resetValueRuns) +#define rbbi_cleanup U_ICU_ENTRY_POINT_RENAME(rbbi_cleanup) #define res_countArrayItems U_ICU_ENTRY_POINT_RENAME(res_countArrayItems) #define res_findResource U_ICU_ENTRY_POINT_RENAME(res_findResource) #define res_getAlias U_ICU_ENTRY_POINT_RENAME(res_getAlias) @@ -512,9 +513,6 @@ #define ubrk_setText U_ICU_ENTRY_POINT_RENAME(ubrk_setText) #define ubrk_setUText U_ICU_ENTRY_POINT_RENAME(ubrk_setUText) #define ubrk_swap U_ICU_ENTRY_POINT_RENAME(ubrk_swap) -#define ucache_compareKeys U_ICU_ENTRY_POINT_RENAME(ucache_compareKeys) -#define ucache_deleteKey U_ICU_ENTRY_POINT_RENAME(ucache_deleteKey) -#define ucache_hashKeys U_ICU_ENTRY_POINT_RENAME(ucache_hashKeys) #define ucal_add U_ICU_ENTRY_POINT_RENAME(ucal_add) #define ucal_clear U_ICU_ENTRY_POINT_RENAME(ucal_clear) #define ucal_clearField U_ICU_ENTRY_POINT_RENAME(ucal_clearField) @@ -532,6 +530,7 @@ #define ucal_getFieldDifference U_ICU_ENTRY_POINT_RENAME(ucal_getFieldDifference) #define ucal_getGregorianChange U_ICU_ENTRY_POINT_RENAME(ucal_getGregorianChange) #define ucal_getHostTimeZone U_ICU_ENTRY_POINT_RENAME(ucal_getHostTimeZone) +#define ucal_getIanaTimeZoneID U_ICU_ENTRY_POINT_RENAME(ucal_getIanaTimeZoneID) #define ucal_getKeywordValuesForLocale U_ICU_ENTRY_POINT_RENAME(ucal_getKeywordValuesForLocale) #define ucal_getLimit U_ICU_ENTRY_POINT_RENAME(ucal_getLimit) #define ucal_getLocaleByType U_ICU_ENTRY_POINT_RENAME(ucal_getLocaleByType) @@ -587,6 +586,7 @@ #define ucasemap_getLocale U_ICU_ENTRY_POINT_RENAME(ucasemap_getLocale) #define ucasemap_getOptions U_ICU_ENTRY_POINT_RENAME(ucasemap_getOptions) #define ucasemap_internalUTF8ToTitle U_ICU_ENTRY_POINT_RENAME(ucasemap_internalUTF8ToTitle) +#define ucasemap_mapUTF8 U_ICU_ENTRY_POINT_RENAME(ucasemap_mapUTF8) #define ucasemap_open U_ICU_ENTRY_POINT_RENAME(ucasemap_open) #define ucasemap_setBreakIterator U_ICU_ENTRY_POINT_RENAME(ucasemap_setBreakIterator) #define ucasemap_setLocale U_ICU_ENTRY_POINT_RENAME(ucasemap_setLocale) @@ -955,9 +955,16 @@ #define ufieldpositer_close U_ICU_ENTRY_POINT_RENAME(ufieldpositer_close) #define ufieldpositer_next U_ICU_ENTRY_POINT_RENAME(ufieldpositer_next) #define ufieldpositer_open U_ICU_ENTRY_POINT_RENAME(ufieldpositer_open) +#define ufile_close_translit U_ICU_ENTRY_POINT_RENAME(ufile_close_translit) +#define ufile_fill_uchar_buffer U_ICU_ENTRY_POINT_RENAME(ufile_fill_uchar_buffer) +#define ufile_flush_io U_ICU_ENTRY_POINT_RENAME(ufile_flush_io) +#define ufile_flush_translit U_ICU_ENTRY_POINT_RENAME(ufile_flush_translit) #define ufile_getch U_ICU_ENTRY_POINT_RENAME(ufile_getch) #define ufile_getch32 U_ICU_ENTRY_POINT_RENAME(ufile_getch32) +#define ufmt_64tou U_ICU_ENTRY_POINT_RENAME(ufmt_64tou) #define ufmt_close U_ICU_ENTRY_POINT_RENAME(ufmt_close) +#define ufmt_defaultCPToUnicode U_ICU_ENTRY_POINT_RENAME(ufmt_defaultCPToUnicode) +#define ufmt_digitvalue U_ICU_ENTRY_POINT_RENAME(ufmt_digitvalue) #define ufmt_getArrayItemByIndex U_ICU_ENTRY_POINT_RENAME(ufmt_getArrayItemByIndex) #define ufmt_getArrayLength U_ICU_ENTRY_POINT_RENAME(ufmt_getArrayLength) #define ufmt_getDate U_ICU_ENTRY_POINT_RENAME(ufmt_getDate) @@ -969,7 +976,11 @@ #define ufmt_getType U_ICU_ENTRY_POINT_RENAME(ufmt_getType) #define ufmt_getUChars U_ICU_ENTRY_POINT_RENAME(ufmt_getUChars) #define ufmt_isNumeric U_ICU_ENTRY_POINT_RENAME(ufmt_isNumeric) +#define ufmt_isdigit U_ICU_ENTRY_POINT_RENAME(ufmt_isdigit) #define ufmt_open U_ICU_ENTRY_POINT_RENAME(ufmt_open) +#define ufmt_ptou U_ICU_ENTRY_POINT_RENAME(ufmt_ptou) +#define ufmt_uto64 U_ICU_ENTRY_POINT_RENAME(ufmt_uto64) +#define ufmt_utop U_ICU_ENTRY_POINT_RENAME(ufmt_utop) #define ufmtval_getString U_ICU_ENTRY_POINT_RENAME(ufmtval_getString) #define ufmtval_nextPosition U_ICU_ENTRY_POINT_RENAME(ufmtval_nextPosition) #define ugender_getInstance U_ICU_ENTRY_POINT_RENAME(ugender_getInstance) @@ -1133,6 +1144,39 @@ #define uloc_toLegacyType U_ICU_ENTRY_POINT_RENAME(uloc_toLegacyType) #define uloc_toUnicodeLocaleKey U_ICU_ENTRY_POINT_RENAME(uloc_toUnicodeLocaleKey) #define uloc_toUnicodeLocaleType U_ICU_ENTRY_POINT_RENAME(uloc_toUnicodeLocaleType) +#define ulocale_close U_ICU_ENTRY_POINT_RENAME(ulocale_close) +#define ulocale_getBaseName U_ICU_ENTRY_POINT_RENAME(ulocale_getBaseName) +#define ulocale_getKeywordValue U_ICU_ENTRY_POINT_RENAME(ulocale_getKeywordValue) +#define ulocale_getKeywords U_ICU_ENTRY_POINT_RENAME(ulocale_getKeywords) +#define ulocale_getLanguage U_ICU_ENTRY_POINT_RENAME(ulocale_getLanguage) +#define ulocale_getLocaleID U_ICU_ENTRY_POINT_RENAME(ulocale_getLocaleID) +#define ulocale_getRegion U_ICU_ENTRY_POINT_RENAME(ulocale_getRegion) +#define ulocale_getScript U_ICU_ENTRY_POINT_RENAME(ulocale_getScript) +#define ulocale_getUnicodeKeywordValue U_ICU_ENTRY_POINT_RENAME(ulocale_getUnicodeKeywordValue) +#define ulocale_getUnicodeKeywords U_ICU_ENTRY_POINT_RENAME(ulocale_getUnicodeKeywords) +#define ulocale_getVariant U_ICU_ENTRY_POINT_RENAME(ulocale_getVariant) +#define ulocale_isBogus U_ICU_ENTRY_POINT_RENAME(ulocale_isBogus) +#define ulocale_openForLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocale_openForLanguageTag) +#define ulocale_openForLocaleID U_ICU_ENTRY_POINT_RENAME(ulocale_openForLocaleID) +#define ulocbld_addUnicodeLocaleAttribute U_ICU_ENTRY_POINT_RENAME(ulocbld_addUnicodeLocaleAttribute) +#define ulocbld_adoptULocale U_ICU_ENTRY_POINT_RENAME(ulocbld_adoptULocale) +#define ulocbld_buildLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocbld_buildLanguageTag) +#define ulocbld_buildLocaleID U_ICU_ENTRY_POINT_RENAME(ulocbld_buildLocaleID) +#define ulocbld_buildULocale U_ICU_ENTRY_POINT_RENAME(ulocbld_buildULocale) +#define ulocbld_clear U_ICU_ENTRY_POINT_RENAME(ulocbld_clear) +#define ulocbld_clearExtensions U_ICU_ENTRY_POINT_RENAME(ulocbld_clearExtensions) +#define ulocbld_close U_ICU_ENTRY_POINT_RENAME(ulocbld_close) +#define ulocbld_copyErrorTo U_ICU_ENTRY_POINT_RENAME(ulocbld_copyErrorTo) +#define ulocbld_open U_ICU_ENTRY_POINT_RENAME(ulocbld_open) +#define ulocbld_removeUnicodeLocaleAttribute U_ICU_ENTRY_POINT_RENAME(ulocbld_removeUnicodeLocaleAttribute) +#define ulocbld_setExtension U_ICU_ENTRY_POINT_RENAME(ulocbld_setExtension) +#define ulocbld_setLanguage U_ICU_ENTRY_POINT_RENAME(ulocbld_setLanguage) +#define ulocbld_setLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocbld_setLanguageTag) +#define ulocbld_setLocale U_ICU_ENTRY_POINT_RENAME(ulocbld_setLocale) +#define ulocbld_setRegion U_ICU_ENTRY_POINT_RENAME(ulocbld_setRegion) +#define ulocbld_setScript U_ICU_ENTRY_POINT_RENAME(ulocbld_setScript) +#define ulocbld_setUnicodeLocaleKeyword U_ICU_ENTRY_POINT_RENAME(ulocbld_setUnicodeLocaleKeyword) +#define ulocbld_setVariant U_ICU_ENTRY_POINT_RENAME(ulocbld_setVariant) #define ulocdata_close U_ICU_ENTRY_POINT_RENAME(ulocdata_close) #define ulocdata_getCLDRVersion U_ICU_ENTRY_POINT_RENAME(ulocdata_getCLDRVersion) #define ulocdata_getDelimiter U_ICU_ENTRY_POINT_RENAME(ulocdata_getDelimiter) @@ -1213,6 +1257,7 @@ #define unorm2_getNFDInstance U_ICU_ENTRY_POINT_RENAME(unorm2_getNFDInstance) #define unorm2_getNFKCCasefoldInstance U_ICU_ENTRY_POINT_RENAME(unorm2_getNFKCCasefoldInstance) #define unorm2_getNFKCInstance U_ICU_ENTRY_POINT_RENAME(unorm2_getNFKCInstance) +#define unorm2_getNFKCSimpleCasefoldInstance U_ICU_ENTRY_POINT_RENAME(unorm2_getNFKCSimpleCasefoldInstance) #define unorm2_getNFKDInstance U_ICU_ENTRY_POINT_RENAME(unorm2_getNFKDInstance) #define unorm2_getRawDecomposition U_ICU_ENTRY_POINT_RENAME(unorm2_getRawDecomposition) #define unorm2_hasBoundaryAfter U_ICU_ENTRY_POINT_RENAME(unorm2_hasBoundaryAfter) @@ -1349,6 +1394,7 @@ #define uprv_convertToPosix U_ICU_ENTRY_POINT_RENAME(uprv_convertToPosix) #define uprv_copyAscii U_ICU_ENTRY_POINT_RENAME(uprv_copyAscii) #define uprv_copyEbcdic U_ICU_ENTRY_POINT_RENAME(uprv_copyEbcdic) +#define uprv_currencyLeads U_ICU_ENTRY_POINT_RENAME(uprv_currencyLeads) #define uprv_decContextClearStatus U_ICU_ENTRY_POINT_RENAME(uprv_decContextClearStatus) #define uprv_decContextDefault U_ICU_ENTRY_POINT_RENAME(uprv_decContextDefault) #define uprv_decContextGetRounding U_ICU_ENTRY_POINT_RENAME(uprv_decContextGetRounding) @@ -1367,6 +1413,7 @@ #define uprv_decNumberAbs U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAbs) #define uprv_decNumberAdd U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAdd) #define uprv_decNumberAnd U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAnd) +#define uprv_decNumberClass U_ICU_ENTRY_POINT_RENAME(uprv_decNumberClass) #define uprv_decNumberClassToString U_ICU_ENTRY_POINT_RENAME(uprv_decNumberClassToString) #define uprv_decNumberCompare U_ICU_ENTRY_POINT_RENAME(uprv_decNumberCompare) #define uprv_decNumberCompareSignal U_ICU_ENTRY_POINT_RENAME(uprv_decNumberCompareSignal) @@ -1763,6 +1810,9 @@ #define usnumf_formatInt64 U_ICU_ENTRY_POINT_RENAME(usnumf_formatInt64) #define usnumf_openForLocale U_ICU_ENTRY_POINT_RENAME(usnumf_openForLocale) #define usnumf_openForLocaleAndGroupingStrategy U_ICU_ENTRY_POINT_RENAME(usnumf_openForLocaleAndGroupingStrategy) +#define uspoof_areBidiConfusable U_ICU_ENTRY_POINT_RENAME(uspoof_areBidiConfusable) +#define uspoof_areBidiConfusableUTF8 U_ICU_ENTRY_POINT_RENAME(uspoof_areBidiConfusableUTF8) +#define uspoof_areBidiConfusableUnicodeString U_ICU_ENTRY_POINT_RENAME(uspoof_areBidiConfusableUnicodeString) #define uspoof_areConfusable U_ICU_ENTRY_POINT_RENAME(uspoof_areConfusable) #define uspoof_areConfusableUTF8 U_ICU_ENTRY_POINT_RENAME(uspoof_areConfusableUTF8) #define uspoof_areConfusableUnicodeString U_ICU_ENTRY_POINT_RENAME(uspoof_areConfusableUnicodeString) @@ -1778,6 +1828,9 @@ #define uspoof_getAllowedChars U_ICU_ENTRY_POINT_RENAME(uspoof_getAllowedChars) #define uspoof_getAllowedLocales U_ICU_ENTRY_POINT_RENAME(uspoof_getAllowedLocales) #define uspoof_getAllowedUnicodeSet U_ICU_ENTRY_POINT_RENAME(uspoof_getAllowedUnicodeSet) +#define uspoof_getBidiSkeleton U_ICU_ENTRY_POINT_RENAME(uspoof_getBidiSkeleton) +#define uspoof_getBidiSkeletonUTF8 U_ICU_ENTRY_POINT_RENAME(uspoof_getBidiSkeletonUTF8) +#define uspoof_getBidiSkeletonUnicodeString U_ICU_ENTRY_POINT_RENAME(uspoof_getBidiSkeletonUnicodeString) #define uspoof_getCheckResultChecks U_ICU_ENTRY_POINT_RENAME(uspoof_getCheckResultChecks) #define uspoof_getCheckResultNumerics U_ICU_ENTRY_POINT_RENAME(uspoof_getCheckResultNumerics) #define uspoof_getCheckResultRestrictionLevel U_ICU_ENTRY_POINT_RENAME(uspoof_getCheckResultRestrictionLevel) diff --git a/thirdparty/icu4c/common/unicode/uvernum.h b/thirdparty/icu4c/common/unicode/uvernum.h index fc784b2492..9fc98e7380 100644 --- a/thirdparty/icu4c/common/unicode/uvernum.h +++ b/thirdparty/icu4c/common/unicode/uvernum.h @@ -53,13 +53,13 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 73 +#define U_ICU_VERSION_MAJOR_NUM 74 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_MINOR_NUM 2 +#define U_ICU_VERSION_MINOR_NUM 1 /** The current ICU patchlevel version as an integer. * This value will change in the subsequent releases of ICU @@ -79,7 +79,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_SUFFIX _73 +#define U_ICU_VERSION_SUFFIX _74 /** * \def U_DEF2_ICU_ENTRY_POINT_RENAME @@ -132,7 +132,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION "73.2" +#define U_ICU_VERSION "74.1" /** * The current ICU library major version number as a string, for library name suffixes. @@ -145,13 +145,13 @@ * * @stable ICU 2.6 */ -#define U_ICU_VERSION_SHORT "73" +#define U_ICU_VERSION_SHORT "74" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "73.2" +#define U_ICU_DATA_VERSION "74.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/thirdparty/icu4c/common/uniquecharstr.h b/thirdparty/icu4c/common/uniquecharstr.h index 10cc924f7f..e5d3b73418 100644 --- a/thirdparty/icu4c/common/uniquecharstr.h +++ b/thirdparty/icu4c/common/uniquecharstr.h @@ -10,6 +10,7 @@ #include "charstr.h" #include "uassert.h" #include "uhash.h" +#include "cmemory.h" U_NAMESPACE_BEGIN @@ -47,22 +48,20 @@ public: } /** - * Adds a string and returns a unique number for it. - * The string's buffer contents must not change, nor move around in memory, + * Adds a NUL-terminated string and returns a unique number for it. + * The string must not change, nor move around in memory, * while this UniqueCharStrings is in use. - * The string contents must be NUL-terminated exactly at s.length(). * - * Best used with read-only-alias UnicodeString objects that point to - * stable storage, such as strings returned by resource bundle functions. + * Best used with string data in a stable storage, such as strings returned + * by resource bundle functions. */ - int32_t add(const UnicodeString &s, UErrorCode &errorCode) { - if (U_FAILURE(errorCode)) { return 0; } + int32_t add(const char16_t*p, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return -1; } if (isFrozen) { errorCode = U_NO_WRITE_PERMISSION; - return 0; + return -1; } // The string points into the resource bundle. - const char16_t *p = s.getBuffer(); int32_t oldIndex = uhash_geti(&map, p); if (oldIndex != 0) { // found duplicate return oldIndex; @@ -71,11 +70,33 @@ public: // The strings object is also terminated with one implicit NUL. strings->append(0, errorCode); int32_t newIndex = strings->length(); - strings->appendInvariantChars(s, errorCode); + strings->appendInvariantChars(p, u_strlen(p), errorCode); uhash_puti(&map, const_cast<char16_t *>(p), newIndex, &errorCode); return newIndex; } + /** + * Adds a unicode string by value and returns a unique number for it. + */ + int32_t addByValue(UnicodeString s, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return -1; } + if (isFrozen) { + errorCode = U_NO_WRITE_PERMISSION; + return -1; + } + int32_t oldIndex = uhash_geti(&map, s.getTerminatedBuffer()); + if (oldIndex != 0) { // found duplicate + return oldIndex; + } + // We need to store the string content of the UnicodeString. + UnicodeString *key = keyStore.create(s); + if (key == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return -1; + } + return add(key->getTerminatedBuffer(), errorCode); + } + void freeze() { isFrozen = true; } /** @@ -90,6 +111,7 @@ public: private: UHashtable map; CharString *strings; + MemoryPool<UnicodeString> keyStore; bool isFrozen = false; }; diff --git a/thirdparty/icu4c/common/uprops.cpp b/thirdparty/icu4c/common/uprops.cpp index 28540186c6..314fa6fb86 100644 --- a/thirdparty/icu4c/common/uprops.cpp +++ b/thirdparty/icu4c/common/uprops.cpp @@ -328,6 +328,53 @@ static UBool hasEmojiProperty(const BinaryProperty &/*prop*/, UChar32 c, UProper return EmojiProps::hasBinaryProperty(c, which); } +static UBool isIDSUnaryOperator(const BinaryProperty &/*prop*/, UChar32 c, UProperty /*which*/) { + // New in Unicode 15.1 for just two characters. + return 0x2FFE<=c && c<=0x2FFF; +} + +/** Ranges (start/limit pairs) of ID_Compat_Math_Continue (only), from UCD PropList.txt. */ +static constexpr UChar32 ID_COMPAT_MATH_CONTINUE[] = { + 0x00B2, 0x00B3 + 1, + 0x00B9, 0x00B9 + 1, + 0x2070, 0x2070 + 1, + 0x2074, 0x207E + 1, + 0x2080, 0x208E + 1 +}; + +/** ID_Compat_Math_Start characters, from UCD PropList.txt. */ +static constexpr UChar32 ID_COMPAT_MATH_START[] = { + 0x2202, + 0x2207, + 0x221E, + 0x1D6C1, + 0x1D6DB, + 0x1D6FB, + 0x1D715, + 0x1D735, + 0x1D74F, + 0x1D76F, + 0x1D789, + 0x1D7A9, + 0x1D7C3 +}; + +static UBool isIDCompatMathStart(const BinaryProperty &/*prop*/, UChar32 c, UProperty /*which*/) { + if (c < ID_COMPAT_MATH_START[0]) { return false; } // fastpath for common scripts + for (UChar32 startChar : ID_COMPAT_MATH_START) { + if (c == startChar) { return true; } + } + return false; +} + +static UBool isIDCompatMathContinue(const BinaryProperty &prop, UChar32 c, UProperty /*which*/) { + for (int32_t i = 0; i < UPRV_LENGTHOF(ID_COMPAT_MATH_CONTINUE); i += 2) { + if (c < ID_COMPAT_MATH_CONTINUE[i]) { return false; } // below range start + if (c < ID_COMPAT_MATH_CONTINUE[i + 1]) { return true; } // below range limit + } + return isIDCompatMathStart(prop, c, UCHAR_ID_COMPAT_MATH_START); +} + static const BinaryProperty binProps[UCHAR_BINARY_LIMIT]={ /* * column and mask values for binary properties from u_getUnicodeProperties(). @@ -409,6 +456,9 @@ static const BinaryProperty binProps[UCHAR_BINARY_LIMIT]={ { UPROPS_SRC_EMOJI, 0, hasEmojiProperty }, // UCHAR_RGI_EMOJI_TAG_SEQUENCE { UPROPS_SRC_EMOJI, 0, hasEmojiProperty }, // UCHAR_RGI_EMOJI_ZWJ_SEQUENCE { UPROPS_SRC_EMOJI, 0, hasEmojiProperty }, // UCHAR_RGI_EMOJI + { UPROPS_SRC_IDSU, 0, isIDSUnaryOperator }, // UCHAR_IDS_UNARY_OPERATOR + { UPROPS_SRC_ID_COMPAT_MATH, 0, isIDCompatMathStart }, // UCHAR_ID_COMPAT_MATH_START + { UPROPS_SRC_ID_COMPAT_MATH, 0, isIDCompatMathContinue }, // UCHAR_ID_COMPAT_MATH_CONTINUE }; U_CAPI UBool U_EXPORT2 @@ -759,6 +809,19 @@ uprops_getSource(UProperty which) { U_CFUNC void U_EXPORT2 uprops_addPropertyStarts(UPropertySource src, const USetAdder *sa, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { return; } + if (src == UPROPS_SRC_ID_COMPAT_MATH) { + // range limits + for (UChar32 c : ID_COMPAT_MATH_CONTINUE) { + sa->add(sa->set, c); + } + // single characters + for (UChar32 c : ID_COMPAT_MATH_START) { + sa->add(sa->set, c); + sa->add(sa->set, c + 1); + } + return; + } if (!ulayout_ensureData(*pErrorCode)) { return; } const UCPTrie *trie; switch (src) { diff --git a/thirdparty/icu4c/common/uprops.h b/thirdparty/icu4c/common/uprops.h index 1e06d03519..80347eab57 100644 --- a/thirdparty/icu4c/common/uprops.h +++ b/thirdparty/icu4c/common/uprops.h @@ -379,6 +379,8 @@ enum UPropertySource { UPROPS_SRC_INSC, UPROPS_SRC_VO, UPROPS_SRC_EMOJI, + UPROPS_SRC_IDSU, + UPROPS_SRC_ID_COMPAT_MATH, /** One more than the highest UPropertySource (UPROPS_SRC_) constant. */ UPROPS_SRC_COUNT }; diff --git a/thirdparty/icu4c/common/uresbund.cpp b/thirdparty/icu4c/common/uresbund.cpp index d02bba8921..5aa1c5fa2f 100644 --- a/thirdparty/icu4c/common/uresbund.cpp +++ b/thirdparty/icu4c/common/uresbund.cpp @@ -24,6 +24,7 @@ #include "unicode/ures.h" #include "unicode/ustring.h" #include "unicode/ucnv.h" +#include "bytesinkutil.h" #include "charstr.h" #include "uresimp.h" #include "ustr_imp.h" @@ -2351,7 +2352,66 @@ struct GetAllChildrenSink : public ResourceSink { aliasedValue.setData(aliasRB->getResData()); aliasedValue.setValidLocaleDataEntry(aliasRB->fValidLocaleDataEntry); aliasedValue.setResource(aliasRB->fRes, ResourceTracer(aliasRB)); - dest.put(key, aliasedValue, isRoot, errorCode); + + if (aliasedValue.getType() != URES_TABLE) { + dest.put(key, aliasedValue, isRoot, errorCode); + } else { + // if the resource we're aliasing over to is a table, the sink might iterate over its contents. + // If it does, it'll get only the things defined in the actual alias target, not the things + // the target inherits from its parent resources. So we walk the parent chain for the *alias target*, + // calling dest.put() for each of the parent tables we could be inheriting from. This means + // that dest.put() has to iterate over the children of multiple tables to get all of the inherited + // resource values, but it already has to do that to handle normal vertical inheritance. + UResType aliasedValueType = URES_TABLE; + CharString tablePath; + tablePath.append(aliasRB->fResPath, errorCode); + const char* parentKey = key; // dest.put() changes the key + dest.put(parentKey, aliasedValue, isRoot, errorCode); + UResourceDataEntry* entry = aliasRB->fData; + Resource res = aliasRB->fRes; + while (aliasedValueType == URES_TABLE && entry->fParent != nullptr) { + CharString localPath; + localPath.copyFrom(tablePath, errorCode); + char* localPathAsCharPtr = localPath.data(); + const char* childKey; + entry = entry->fParent; + res = entry->fData.rootRes; + Resource newRes = res_findResource(&entry->fData, res, &localPathAsCharPtr, &childKey); + if (newRes != RES_BOGUS) { + aliasedValue.setData(entry->fData); + // TODO: do I also need to call aliasedValue.setValueLocaleDataEntry() ? + aliasedValue.setResource(newRes, ResourceTracer(aliasRB)); // probably wrong to use aliasRB here + aliasedValueType = aliasedValue.getType(); + if (aliasedValueType == URES_ALIAS) { + // in a few rare cases, when we get to the root resource bundle, the resource in question + // won't be an actual table, but will instead be an alias to a table. That is, we have + // two aliases in the inheritance path. (For some locales, such as Zulu, we see this with + // children of the "fields" resource: "day-narrow" aliases to "day-short", which aliases + // to "day".) When this happens, we need to make sure we follow all the aliases. + ResourceDataValue& rdv2 = static_cast<ResourceDataValue&>(aliasedValue); + aliasRB = getAliasTargetAsResourceBundle(rdv2.getData(), rdv2.getResource(), nullptr, -1, + rdv2.getValidLocaleDataEntry(), nullptr, 0, + stackTempBundle.getAlias(), &errorCode); + tablePath.clear(); + tablePath.append(aliasRB->fResPath, errorCode); + entry = aliasRB->fData; + res = aliasRB->fRes; + aliasedValue.setData(entry->fData); + // TODO: do I also need to call aliasedValue.setValueLocaleDataEntry() ? + aliasedValue.setResource(res, ResourceTracer(aliasRB)); // probably wrong to use aliasRB here + aliasedValueType = aliasedValue.getType(); + } + if (aliasedValueType == URES_TABLE) { + dest.put(parentKey, aliasedValue, isRoot, errorCode); + } else { + // once we've followed the alias, the resource we're looking at really should + // be a table + errorCode = U_INTERNAL_PROGRAM_ERROR; + return; + } + } + } + } } } else { dest.put(key, value, isRoot, errorCode); @@ -2657,13 +2717,16 @@ ures_openWithType(UResourceBundle *r, const char* path, const char* localeID, UResourceDataEntry *entry; if(openType != URES_OPEN_DIRECT) { /* first "canonicalize" the locale ID */ - char canonLocaleID[ULOC_FULLNAME_CAPACITY]; - uloc_getBaseName(localeID, canonLocaleID, UPRV_LENGTHOF(canonLocaleID), status); - if(U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) { + CharString canonLocaleID; + { + CharStringByteSink sink(&canonLocaleID); + ulocimp_getBaseName(localeID, sink, status); + } + if(U_FAILURE(*status)) { *status = U_ILLEGAL_ARGUMENT_ERROR; return nullptr; } - entry = entryOpen(path, canonLocaleID, openType, status); + entry = entryOpen(path, canonLocaleID.data(), openType, status); } else { entry = entryOpenDirect(path, localeID, status); } @@ -2974,15 +3037,39 @@ static UBool isLocaleInList(UEnumeration *locEnum, const char *locToSearch, UErr return false; } +static void getParentForFunctionalEquivalent(const char* localeID, + UResourceBundle* res, + UResourceBundle* bund1, + char* parent, + int32_t parentCapacity) { + // Get parent. + // First check for a parent from %%Parent resource (Note that in resource trees + // such as collation, data may have different parents than in parentLocales). + UErrorCode subStatus = U_ZERO_ERROR; + parent[0] = '\0'; + if (res != NULL) { + ures_getByKey(res, "%%Parent", bund1, &subStatus); + if (U_SUCCESS(subStatus)) { + int32_t parentLen = parentCapacity; + ures_getUTF8String(bund1, parent, &parentLen, true, &subStatus); + } + } + + // If none there, use normal truncation parent + if (U_FAILURE(subStatus) || parent[0] == 0) { + subStatus = U_ZERO_ERROR; + uloc_getParent(localeID, parent, parentCapacity, &subStatus); + } +} + U_CAPI int32_t U_EXPORT2 ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, const char *path, const char *resName, const char *keyword, const char *locid, UBool *isAvailable, UBool omitDefault, UErrorCode *status) { - char kwVal[1024] = ""; /* value of keyword 'keyword' */ char defVal[1024] = ""; /* default value for given locale */ char defLoc[1024] = ""; /* default value for given locale */ - char base[1024] = ""; /* base locale */ + CharString base; /* base locale */ char found[1024] = ""; char parent[1024] = ""; char full[1024] = ""; @@ -2991,23 +3078,29 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, UErrorCode subStatus = U_ZERO_ERROR; int32_t length = 0; if(U_FAILURE(*status)) return 0; - uloc_getKeywordValue(locid, keyword, kwVal, 1024-1,&subStatus); - if(!uprv_strcmp(kwVal, DEFAULT_TAG)) { - kwVal[0]=0; + CharString kwVal; + { + CharStringByteSink sink(&kwVal); + ulocimp_getKeywordValue(locid, keyword, sink, &subStatus); + } + if(kwVal == DEFAULT_TAG) { + kwVal.clear(); + } + { + CharStringByteSink sink(&base); + ulocimp_getBaseName(locid, sink, &subStatus); } - uloc_getBaseName(locid, base, 1024-1,&subStatus); #if defined(URES_TREE_DEBUG) fprintf(stderr, "getFunctionalEquivalent: \"%s\" [%s=%s] in %s - %s\n", - locid, keyword, kwVal, base, u_errorName(subStatus)); + locid, keyword, kwVal.data(), base.data(), u_errorName(subStatus)); #endif ures_initStackObject(&bund1); ures_initStackObject(&bund2); - - - uprv_strcpy(parent, base); - uprv_strcpy(found, base); - if(isAvailable) { + base.extract(parent, UPRV_LENGTHOF(parent), subStatus); + base.extract(found, UPRV_LENGTHOF(found), subStatus); + + if(isAvailable) { UEnumeration *locEnum = ures_openAvailableLocales(path, &subStatus); *isAvailable = true; if (U_SUCCESS(subStatus)) { @@ -3054,11 +3147,11 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, path?path:"ICUDATA", parent, keyword, defVal, u_errorName(subStatus)); #endif uprv_strcpy(defLoc, parent); - if(kwVal[0]==0) { - uprv_strcpy(kwVal, defVal); + if(kwVal.isEmpty()) { + kwVal.append(defVal, defLen, subStatus); #if defined(URES_TREE_DEBUG) fprintf(stderr, "%s;%s -> kwVal = %s\n", - path?path:"ICUDATA", parent, keyword, kwVal); + path?path:"ICUDATA", parent, keyword, kwVal.data()); #endif } } @@ -3071,16 +3164,19 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, uprv_strcpy(found, ures_getLocaleByType(res, ULOC_VALID_LOCALE, &subStatus)); } - uloc_getParent(found,parent,sizeof(parent),&subStatus); + if (uprv_strcmp(found, parent) != 0) { + uprv_strcpy(parent, found); + } else { + getParentForFunctionalEquivalent(found,res,&bund1,parent,sizeof(parent)); + } ures_close(res); } while(!defVal[0] && *found && uprv_strcmp(found, "root") != 0 && U_SUCCESS(*status)); /* Now, see if we can find the kwVal collator.. start the search over.. */ - uprv_strcpy(parent, base); - uprv_strcpy(found, base); - + base.extract(parent, UPRV_LENGTHOF(parent), subStatus); + base.extract(found, UPRV_LENGTHOF(found), subStatus); + do { - subStatus = U_ZERO_ERROR; res = ures_open(path, parent, &subStatus); if((subStatus == U_USING_FALLBACK_WARNING) && isAvailable) { *isAvailable = false; @@ -3089,7 +3185,7 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, #if defined(URES_TREE_DEBUG) fprintf(stderr, "%s;%s -> %s (looking for %s)\n", - path?path:"ICUDATA", parent, u_errorName(subStatus), kwVal); + path?path:"ICUDATA", parent, u_errorName(subStatus), kwVal.data()); #endif if(U_FAILURE(subStatus)) { *status = subStatus; @@ -3099,14 +3195,14 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, /**/ fprintf(stderr,"@%d [%s] %s\n", __LINE__, resName, u_errorName(subStatus)); #endif if(subStatus == U_ZERO_ERROR) { - ures_getByKey(&bund1, kwVal, &bund2, &subStatus); + ures_getByKey(&bund1, kwVal.data(), &bund2, &subStatus); #if defined(URES_TREE_DEBUG) -/**/ fprintf(stderr,"@%d [%s] %s\n", __LINE__, kwVal, u_errorName(subStatus)); +/**/ fprintf(stderr,"@%d [%s] %s\n", __LINE__, kwVal.data(), u_errorName(subStatus)); #endif if(subStatus == U_ZERO_ERROR) { #if defined(URES_TREE_DEBUG) fprintf(stderr, "%s;%s -> full0 %s=%s, %s\n", - path?path:"ICUDATA", parent, keyword, kwVal, u_errorName(subStatus)); + path?path:"ICUDATA", parent, keyword, kwVal.data(), u_errorName(subStatus)); #endif uprv_strcpy(full, parent); if(*full == 0) { @@ -3139,29 +3235,52 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, } else { #if defined(URES_TREE_DEBUG) fprintf(stderr, "err=%s in %s looking for %s\n", - u_errorName(subStatus), parent, kwVal); + u_errorName(subStatus), parent, kwVal.data()); #endif } } } - subStatus = U_ZERO_ERROR; - - uprv_strcpy(found, parent); - uloc_getParent(found,parent,1023,&subStatus); + UBool haveFound = false; + // At least for collations which may be aliased, we need to use the VALID locale + // as the parent instead of just truncating, as long as the VALID locale is not + // root and has a different language than the parent. Use of the VALID locale + // here is similar to the procedure used at the end of the previous do-while loop + // for all resource types. + if (res != NULL && uprv_strcmp(resName, "collations") == 0) { + subStatus = U_ZERO_ERROR; + const char *validLoc = ures_getLocaleByType(res, ULOC_VALID_LOCALE, &subStatus); + if (U_SUCCESS(subStatus) && validLoc != NULL && validLoc[0] != 0 && uprv_strcmp(validLoc, "root") != 0) { + char validLang[ULOC_LANG_CAPACITY]; + char parentLang[ULOC_LANG_CAPACITY]; + uloc_getLanguage(validLoc, validLang, ULOC_LANG_CAPACITY, &subStatus); + uloc_getLanguage(parent, parentLang, ULOC_LANG_CAPACITY, &subStatus); + if (U_SUCCESS(subStatus) && uprv_strcmp(validLang, parentLang) != 0) { + // validLoc is not root and has a different language than parent, use it instead + uprv_strcpy(found, validLoc); + haveFound = true; + } + } + subStatus = U_ZERO_ERROR; + } + if (!haveFound) { + uprv_strcpy(found, parent); + } + + getParentForFunctionalEquivalent(found,res,&bund1,parent,1023); ures_close(res); + subStatus = U_ZERO_ERROR; } while(!full[0] && *found && U_SUCCESS(*status)); - - if((full[0]==0) && uprv_strcmp(kwVal, defVal)) { + + if((full[0]==0) && kwVal != defVal) { #if defined(URES_TREE_DEBUG) - fprintf(stderr, "Failed to locate kw %s - try default %s\n", kwVal, defVal); + fprintf(stderr, "Failed to locate kw %s - try default %s\n", kwVal.data(), defVal); #endif - uprv_strcpy(kwVal, defVal); - uprv_strcpy(parent, base); - uprv_strcpy(found, base); - + kwVal.clear().append(defVal, subStatus); + base.extract(parent, UPRV_LENGTHOF(parent), subStatus); + base.extract(found, UPRV_LENGTHOF(found), subStatus); + do { /* search for 'default' named item */ - subStatus = U_ZERO_ERROR; res = ures_open(path, parent, &subStatus); if((subStatus == U_USING_FALLBACK_WARNING) && isAvailable) { *isAvailable = false; @@ -3170,18 +3289,18 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, #if defined(URES_TREE_DEBUG) fprintf(stderr, "%s;%s -> %s (looking for default %s)\n", - path?path:"ICUDATA", parent, u_errorName(subStatus), kwVal); + path?path:"ICUDATA", parent, u_errorName(subStatus), kwVal.data()); #endif if(U_FAILURE(subStatus)) { *status = subStatus; } else if(subStatus == U_ZERO_ERROR) { ures_getByKey(res,resName,&bund1, &subStatus); if(subStatus == U_ZERO_ERROR) { - ures_getByKey(&bund1, kwVal, &bund2, &subStatus); + ures_getByKey(&bund1, kwVal.data(), &bund2, &subStatus); if(subStatus == U_ZERO_ERROR) { #if defined(URES_TREE_DEBUG) fprintf(stderr, "%s;%s -> full1 %s=%s, %s\n", path?path:"ICUDATA", - parent, keyword, kwVal, u_errorName(subStatus)); + parent, keyword, kwVal.data(), u_errorName(subStatus)); #endif uprv_strcpy(full, parent); if(*full == 0) { @@ -3215,18 +3334,18 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, } } } - subStatus = U_ZERO_ERROR; uprv_strcpy(found, parent); - uloc_getParent(found,parent,1023,&subStatus); + getParentForFunctionalEquivalent(found,res,&bund1,parent,1023); ures_close(res); + subStatus = U_ZERO_ERROR; } while(!full[0] && *found && U_SUCCESS(*status)); } if(U_SUCCESS(*status)) { if(!full[0]) { #if defined(URES_TREE_DEBUG) - fprintf(stderr, "Still could not load keyword %s=%s\n", keyword, kwVal); + fprintf(stderr, "Still could not load keyword %s=%s\n", keyword, kwVal.data()); #endif *status = U_MISSING_RESOURCE_ERROR; } else if(omitDefault) { @@ -3235,21 +3354,21 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity, #endif if(uprv_strlen(defLoc) <= uprv_strlen(full)) { /* found the keyword in a *child* of where the default tag was present. */ - if(!uprv_strcmp(kwVal, defVal)) { /* if the requested kw is default, */ + if(kwVal == defVal) { /* if the requested kw is default, */ /* and the default is in or in an ancestor of the current locale */ #if defined(URES_TREE_DEBUG) - fprintf(stderr, "Removing unneeded var %s=%s\n", keyword, kwVal); + fprintf(stderr, "Removing unneeded var %s=%s\n", keyword, kwVal.data()); #endif - kwVal[0]=0; + kwVal.clear(); } } } uprv_strcpy(found, full); - if(kwVal[0]) { + if(!kwVal.isEmpty()) { uprv_strcat(found, "@"); uprv_strcat(found, keyword); uprv_strcat(found, "="); - uprv_strcat(found, kwVal); + uprv_strcat(found, kwVal.data()); } else if(!omitDefault) { uprv_strcat(found, "@"); uprv_strcat(found, keyword); diff --git a/thirdparty/icu4c/common/ustrcase.cpp b/thirdparty/icu4c/common/ustrcase.cpp index 537b5ba857..e4aec8a1c7 100644 --- a/thirdparty/icu4c/common/ustrcase.cpp +++ b/thirdparty/icu4c/common/ustrcase.cpp @@ -1130,14 +1130,18 @@ int32_t toUpper(uint32_t options, // Adding one only to the final vowel in a longer sequence // (which does not occur in normal writing) would require lookahead. // Set the same flag as for preserving an existing dialytika. - if ((data & HAS_VOWEL) != 0 && (state & AFTER_VOWEL_WITH_ACCENT) != 0 && - (upper == 0x399 || upper == 0x3A5)) { - data |= HAS_DIALYTIKA; + if ((data & HAS_VOWEL) != 0 && + (state & (AFTER_VOWEL_WITH_PRECOMPOSED_ACCENT | AFTER_VOWEL_WITH_COMBINING_ACCENT)) != + 0 && + (upper == 0x399 || upper == 0x3A5)) { + data |= (state & AFTER_VOWEL_WITH_PRECOMPOSED_ACCENT) ? HAS_DIALYTIKA + : HAS_COMBINING_DIALYTIKA; } int32_t numYpogegrammeni = 0; // Map each one to a trailing, spacing, capital iota. if ((data & HAS_YPOGEGRAMMENI) != 0) { numYpogegrammeni = 1; } + const UBool hasPrecomposedAccent = (data & HAS_ACCENT) != 0; // Skip combining diacritics after this Greek letter. while (nextIndex < srcLength) { uint32_t diacriticData = getDiacriticData(src[nextIndex]); @@ -1152,7 +1156,8 @@ int32_t toUpper(uint32_t options, } } if ((data & HAS_VOWEL_AND_ACCENT_AND_DIALYTIKA) == HAS_VOWEL_AND_ACCENT) { - nextState |= AFTER_VOWEL_WITH_ACCENT; + nextState |= hasPrecomposedAccent ? AFTER_VOWEL_WITH_PRECOMPOSED_ACCENT + : AFTER_VOWEL_WITH_COMBINING_ACCENT; } // Map according to Greek rules. UBool addTonos = false; @@ -1163,7 +1168,7 @@ int32_t toUpper(uint32_t options, !isFollowedByCasedLetter(src, nextIndex, srcLength)) { // Keep disjunctive "or" with (only) a tonos. // We use the same "word boundary" conditions as for the Final_Sigma test. - if (i == nextIndex) { + if (hasPrecomposedAccent) { upper = 0x389; // Preserve the precomposed form. } else { addTonos = true; diff --git a/thirdparty/icu4c/common/uts46.cpp b/thirdparty/icu4c/common/uts46.cpp index fce2af4130..28f15f7175 100644 --- a/thirdparty/icu4c/common/uts46.cpp +++ b/thirdparty/icu4c/common/uts46.cpp @@ -669,14 +669,6 @@ UTS46::mapDevChars(UnicodeString &dest, int32_t labelStart, int32_t mappingStart return length; } -// Some non-ASCII characters are equivalent to sequences with -// non-LDH ASCII characters. To find them: -// grep disallowed_STD3_valid IdnaMappingTable.txt (or uts46.txt) -static inline UBool -isNonASCIIDisallowedSTD3Valid(UChar32 c) { - return c==0x2260 || c==0x226E || c==0x226F; -} - // Replace the label in dest with the label string, if the label was modified. // If &label==&dest then the label was modified in-place and labelLength // is the new label length, different from label.length(). @@ -820,10 +812,7 @@ UTS46::processLabel(UnicodeString &dest, } } else { oredChars|=c; - if(disallowNonLDHDot && isNonASCIIDisallowedSTD3Valid(c)) { - info.labelErrors|=UIDNA_ERROR_DISALLOWED; - *s=0xfffd; - } else if(c==0xfffd) { + if(c==0xfffd) { info.labelErrors|=UIDNA_ERROR_DISALLOWED; } } diff --git a/thirdparty/icu4c/i18n/unicode/uspoof.h b/thirdparty/icu4c/i18n/unicode/uspoof.h index 442655bb54..20d29d62b2 100644 --- a/thirdparty/icu4c/i18n/unicode/uspoof.h +++ b/thirdparty/icu4c/i18n/unicode/uspoof.h @@ -19,6 +19,7 @@ #ifndef USPOOF_H #define USPOOF_H +#include "unicode/ubidi.h" #include "unicode/utypes.h" #include "unicode/uset.h" #include "unicode/parseerr.h" @@ -83,6 +84,25 @@ * the instance should be created once (e.g., upon application startup), and the efficient * {@link uspoof_areConfusable} method can be used at runtime. * + * If the paragraph direction used to display the strings is known, the bidi function should be used instead: + * + * \code{.c} + * UErrorCode status = U_ZERO_ERROR; + * // These strings look identical when rendered in a left-to-right context. + * // They look distinct in a right-to-left context. + * UChar* str1 = (UChar*) u"A1\u05D0"; // A1א + * UChar* str2 = (UChar*) u"A\u05D01"; // Aא1 + * + * USpoofChecker* sc = uspoof_open(&status); + * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status); + * + * int32_t bitmask = uspoof_areBidiConfusable(sc, UBIDI_LTR, str1, -1, str2, -1, &status); + * UBool result = bitmask != 0; + * // areBidiConfusable: 1 (status: U_ZERO_ERROR) + * printf("areBidiConfusable: %d (status: %s)\n", result, u_errorName(status)); + * uspoof_close(sc); + * \endcode + * * <p> * The type {@link LocalUSpoofCheckerPointer} is exposed for C++ programmers. It will automatically call * {@link uspoof_close} when the object goes out of scope: @@ -339,6 +359,51 @@ * COMMON or INHERITED, such as numbers and punctuation, are ignored when computing whether a string has multiple * scripts. * + * <h2>Advanced bidirectional usage</h2> + * If the paragraph direction with which the identifiers will be displayed is not known, there are + * multiple options for confusable detection depending on the circumstances. + * + * <p> + * In some circumstances, the only concern is confusion between identifiers displayed with the same + * paragraph direction. + * + * <p> + * An example is the case where identifiers are usernames prefixed with the @ symbol. + * That symbol will appear to the left in a left-to-right context, and to the right in a + * right-to-left context, so that an identifier displayed in a left-to-right context can never be + * confused with an identifier displayed in a right-to-left context: + * <ul> + * <li> + * The usernames "A1א" (A one aleph) and "Aא1" (A aleph 1) + * would be considered confusable, since they both appear as \@A1א in a left-to-right context, and the + * usernames "אA_1" (aleph A underscore one) and "א1_A" (aleph one underscore A) would be considered + * confusable, since they both appear as A_1א@ in a right-to-left context. + * </li> + * <li> + * The username "Mark_" would not be considered confusable with the username "_Mark", + * even though the latter would appear as Mark_@ in a right-to-left context, and the + * former as \@Mark_ in a left-to-right context. + * </li> + * </ul> + * <p> + * In that case, the caller should check for both LTR-confusability and RTL-confusability: + * + * \code{.cpp} + * bool confusableInEitherDirection = + * uspoof_areBidiConfusableUnicodeString(sc, UBIDI_LTR, id1, id2, &status) || + * uspoof_areBidiConfusableUnicodeString(sc, UBIDI_RTL, id1, id2, &status); + * \endcode + * + * If the bidiSkeleton is used, the LTR and RTL skeleta should be kept separately and compared, LTR + * with LTR and RTL with RTL. + * + * <p> + * In cases where confusability between the visual appearances of an identifier displayed in a + * left-to-right context with another identifier displayed in a right-to-left context is a concern, + * the LTR skeleton of one can be compared with the RTL skeleton of the other. However, this + * very broad definition of confusability may have unexpected results; for instance, it treats the + * ASCII identifiers "Mark_" and "_Mark" as confusable. + * * <h2>Additional Information</h2> * * A <code>USpoofChecker</code> instance may be used repeatedly to perform checks on any number of identifiers. @@ -519,7 +584,7 @@ typedef enum USpoofChecks { /** - * Constants from UAX #39 for use in {@link uspoof_setRestrictionLevel}, and + * Constants from UTS #39 for use in {@link uspoof_setRestrictionLevel}, and * for returned identifier restriction levels in check results. * * @stable ICU 51 @@ -633,8 +698,8 @@ uspoof_openFromSerialized(const void *data, int32_t length, int32_t *pActualLeng /** * Open a Spoof Checker from the source form of the spoof data. * The input corresponds to the Unicode data file confusables.txt - * as described in Unicode UAX #39. The syntax of the source data - * is as described in UAX #39 for this file, and the content of + * as described in Unicode Technical Standard #39. The syntax of the source data + * is as described in UTS #39 for this file, and the content of * this file is acceptable input. * * The character encoding of the (char *) input text is UTF-8. @@ -1111,7 +1176,7 @@ uspoof_getCheckResultNumerics(const USpoofCheckResult *checkResult, UErrorCode * /** - * Check the whether two specified strings are visually confusable. + * Check whether two specified strings are visually confusable. * * If the strings are confusable, the return value will be nonzero, as long as * {@link USPOOF_CONFUSABLE} was enabled in uspoof_setChecks(). @@ -1159,7 +1224,58 @@ uspoof_areConfusable(const USpoofChecker *sc, const UChar *id2, int32_t length2, UErrorCode *status); - +#ifndef U_HIDE_DRAFT_API +/** + * Check whether two specified strings are visually confusable when + * displayed in a context with the given paragraph direction. + * + * If the strings are confusable, the return value will be nonzero, as long as + * {@link USPOOF_CONFUSABLE} was enabled in uspoof_setChecks(). + * + * The bits in the return value correspond to flags for each of the classes of + * confusables applicable to the two input strings. According to UTS 39 + * section 4, the possible flags are: + * + * <ul> + * <li>{@link USPOOF_SINGLE_SCRIPT_CONFUSABLE}</li> + * <li>{@link USPOOF_MIXED_SCRIPT_CONFUSABLE}</li> + * <li>{@link USPOOF_WHOLE_SCRIPT_CONFUSABLE}</li> + * </ul> + * + * If one or more of the above flags were not listed in uspoof_setChecks(), this + * function will never report that class of confusable. The check + * {@link USPOOF_CONFUSABLE} enables all three flags. + * + * + * @param sc The USpoofChecker + * @param direction The paragraph direction with which the identifiers are + * displayed. Must be either UBIDI_LTR or UBIDI_RTL. + * @param id1 The first of the two identifiers to be compared for + * confusability. The strings are in UTF-16 format. + * @param length1 the length of the first identifier, expressed in + * 16 bit UTF-16 code units, or -1 if the string is + * nul terminated. + * @param id2 The second of the two identifiers to be compared for + * confusability. The identifiers are in UTF-16 format. + * @param length2 The length of the second identifiers, expressed in + * 16 bit UTF-16 code units, or -1 if the string is + * nul terminated. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Confusability of the identifiers is not reported here, + * but through this function's return value. + * @return An integer value with bit(s) set corresponding to + * the type of confusability found, as defined by + * enum USpoofChecks. Zero is returned if the identifiers + * are not confusable. + * + * @draft ICU 74 + */ +U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusable(const USpoofChecker *sc, UBiDiDirection direction, + const UChar *id1, int32_t length1, + const UChar *id2, int32_t length2, + UErrorCode *status); +#endif /* U_HIDE_DRAFT_API */ /** * A version of {@link uspoof_areConfusable} accepting strings in UTF-8 format. @@ -1192,14 +1308,45 @@ uspoof_areConfusableUTF8(const USpoofChecker *sc, const char *id2, int32_t length2, UErrorCode *status); - - +#ifndef U_HIDE_DRAFT_API +/** + * A version of {@link uspoof_areBidiConfusable} accepting strings in UTF-8 format. + * + * @param sc The USpoofChecker + * @param direction The paragraph direction with which the identifiers are + * displayed. Must be either UBIDI_LTR or UBIDI_RTL. + * @param id1 The first of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param length1 the length of the first identifiers, in bytes, or -1 + * if the string is nul terminated. + * @param id2 The second of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param length2 The length of the second string in bytes, or -1 + * if the string is nul terminated. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Confusability of the strings is not reported here, + * but through this function's return value. + * @return An integer value with bit(s) set corresponding to + * the type of confusability found, as defined by + * enum USpoofChecks. Zero is returned if the strings + * are not confusable. + * + * @draft ICU 74 + * + * @see uspoof_areBidiConfusable + */ +U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusableUTF8(const USpoofChecker *sc, UBiDiDirection direction, + const char *id1, int32_t length1, + const char *id2, int32_t length2, + UErrorCode *status); +#endif /* U_HIDE_DRAFT_API */ /** * Get the "skeleton" for an identifier. * Skeletons are a transformation of the input identifier; * Two identifiers are confusable if their skeletons are identical. - * See Unicode UAX #39 for additional information. + * See Unicode Technical Standard #39 for additional information. * * Using skeletons directly makes it possible to quickly check * whether an identifier is confusable with any of some large @@ -1233,11 +1380,50 @@ uspoof_getSkeleton(const USpoofChecker *sc, UChar *dest, int32_t destCapacity, UErrorCode *status); +#ifndef U_HIDE_DRAFT_API +/** + * Get the "bidiSkeleton" for an identifier and a direction. + * Skeletons are a transformation of the input identifier; + * Two identifiers are LTR-confusable if their LTR bidiSkeletons are identical; + * they are RTL-confusable if their RTL bidiSkeletons are identical. + * See Unicode Technical Standard #39 for additional information: + * https://www.unicode.org/reports/tr39/#Confusable_Detection. + * + * Using skeletons directly makes it possible to quickly check + * whether an identifier is confusable with any of some large + * set of existing identifiers, by creating an efficiently + * searchable collection of the skeletons. + * + * @param sc The USpoofChecker. + * @param direction The context direction with which the identifier will be + * displayed. Must be either UBIDI_LTR or UBIDI_RTL. + * @param id The input identifier whose skeleton will be computed. + * @param length The length of the input identifier, expressed in 16 bit + * UTF-16 code units, or -1 if the string is zero terminated. + * @param dest The output buffer, to receive the skeleton string. + * @param destCapacity The length of the output buffer, in 16 bit units. + * The destCapacity may be zero, in which case the function will + * return the actual length of the skeleton. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * @return The length of the skeleton string. The returned length + * is always that of the complete skeleton, even when the + * supplied buffer is too small (or of zero length) + * + * @draft ICU 74 + * @see uspoof_areBidiConfusable + */ +U_CAPI int32_t U_EXPORT2 uspoof_getBidiSkeleton(const USpoofChecker *sc, + UBiDiDirection direction, + const UChar *id, int32_t length, + UChar *dest, int32_t destCapacity, UErrorCode *status); +#endif /* U_HIDE_DRAFT_API */ + /** * Get the "skeleton" for an identifier. * Skeletons are a transformation of the input identifier; * Two identifiers are confusable if their skeletons are identical. - * See Unicode UAX #39 for additional information. + * See Unicode Technical Standard #39 for additional information. * * Using skeletons directly makes it possible to quickly check * whether an identifier is confusable with any of some large @@ -1273,6 +1459,46 @@ uspoof_getSkeletonUTF8(const USpoofChecker *sc, char *dest, int32_t destCapacity, UErrorCode *status); +#ifndef U_HIDE_DRAFT_API +/** + * Get the "bidiSkeleton" for an identifier and a direction. + * Skeletons are a transformation of the input identifier; + * Two identifiers are LTR-confusable if their LTR bidiSkeletons are identical; + * they are RTL-confusable if their RTL bidiSkeletons are identical. + * See Unicode Technical Standard #39 for additional information: + * https://www.unicode.org/reports/tr39/#Confusable_Detection. + * + * Using skeletons directly makes it possible to quickly check + * whether an identifier is confusable with any of some large + * set of existing identifiers, by creating an efficiently + * searchable collection of the skeletons. + * + * @param sc The USpoofChecker + * @param direction The context direction with which the identifier will be + * displayed. Must be either UBIDI_LTR or UBIDI_RTL. + * @param id The UTF-8 format identifier whose skeleton will be computed. + * @param length The length of the input string, in bytes, + * or -1 if the string is zero terminated. + * @param dest The output buffer, to receive the skeleton string. + * @param destCapacity The length of the output buffer, in bytes. + * The destCapacity may be zero, in which case the function will + * return the actual length of the skeleton. + * @param status The error code, set if an error occurred while attempting to + * perform the check. Possible Errors include U_INVALID_CHAR_FOUND + * for invalid UTF-8 sequences, and + * U_BUFFER_OVERFLOW_ERROR if the destination buffer is too small + * to hold the complete skeleton. + * @return The length of the skeleton string, in bytes. The returned length + * is always that of the complete skeleton, even when the + * supplied buffer is too small (or of zero length) + * + * @draft ICU 74 + */ +U_CAPI int32_t U_EXPORT2 uspoof_getBidiSkeletonUTF8(const USpoofChecker *sc, UBiDiDirection direction, + const char *id, int32_t length, char *dest, + int32_t destCapacity, UErrorCode *status); +#endif /* U_HIDE_DRAFT_API */ + /** * Get the set of Candidate Characters for Inclusion in Identifiers, as defined * in http://unicode.org/Public/security/latest/xidmodifications.txt @@ -1510,11 +1736,42 @@ uspoof_areConfusableUnicodeString(const USpoofChecker *sc, const icu::UnicodeString &s2, UErrorCode *status); +#ifndef U_HIDE_DRAFT_API +/** + * A version of {@link uspoof_areBidiConfusable} accepting UnicodeStrings. + * + * @param sc The USpoofChecker + * @param direction The paragraph direction with which the identifiers are + * displayed. Must be either UBIDI_LTR or UBIDI_RTL. + * @param s1 The first of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param s2 The second of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Confusability of the identifiers is not reported here, + * but through this function's return value. + * @return An integer value with bit(s) set corresponding to + * the type of confusability found, as defined by + * enum USpoofChecks. Zero is returned if the identifiers + * are not confusable. + * + * @draft ICU 74 + * + * @see uspoof_areBidiConfusable + */ +U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusableUnicodeString(const USpoofChecker *sc, + UBiDiDirection direction, + const icu::UnicodeString &s1, + const icu::UnicodeString &s2, + UErrorCode *status); +#endif /* U_HIDE_DRAFT_API */ + /** * Get the "skeleton" for an identifier. * Skeletons are a transformation of the input identifier; * Two identifiers are confusable if their skeletons are identical. - * See Unicode UAX #39 for additional information. + * See Unicode Technical Standard #39 for additional information. * * Using skeletons directly makes it possible to quickly check * whether an identifier is confusable with any of some large @@ -1540,6 +1797,36 @@ uspoof_getSkeletonUnicodeString(const USpoofChecker *sc, icu::UnicodeString &dest, UErrorCode *status); +#ifndef U_HIDE_DRAFT_API +/** + * Get the "bidiSkeleton" for an identifier and a direction. + * Skeletons are a transformation of the input identifier; + * Two identifiers are LTR-confusable if their LTR bidiSkeletons are identical; + * they are RTL-confusable if their RTL bidiSkeletons are identical. + * See Unicode Technical Standard #39 for additional information. + * https://www.unicode.org/reports/tr39/#Confusable_Detection. + * + * Using skeletons directly makes it possible to quickly check + * whether an identifier is confusable with any of some large + * set of existing identifiers, by creating an efficiently + * searchable collection of the skeletons. + * + * @param sc The USpoofChecker. + * @param direction The context direction with which the identifier will be + * displayed. Must be either UBIDI_LTR or UBIDI_RTL. + * @param id The input identifier whose bidiSkeleton will be computed. + * @param dest The output identifier, to receive the skeleton string. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * @return A reference to the destination (skeleton) string. + * + * @draft ICU 74 + */ +U_I18N_API icu::UnicodeString &U_EXPORT2 uspoof_getBidiSkeletonUnicodeString( + const USpoofChecker *sc, UBiDiDirection direction, const icu::UnicodeString &id, + icu::UnicodeString &dest, UErrorCode *status); +#endif /* U_HIDE_DRAFT_API */ + /** * Get the set of Candidate Characters for Inclusion in Identifiers, as defined * in http://unicode.org/Public/security/latest/xidmodifications.txt diff --git a/thirdparty/icu4c/i18n/uspoof.cpp b/thirdparty/icu4c/i18n/uspoof.cpp index 271caeafff..47dac8418e 100644 --- a/thirdparty/icu4c/i18n/uspoof.cpp +++ b/thirdparty/icu4c/i18n/uspoof.cpp @@ -15,6 +15,7 @@ * * Unicode Spoof Detection */ +#include "unicode/ubidi.h" #include "unicode/utypes.h" #include "unicode/normalizer2.h" #include "unicode/uspoof.h" @@ -141,8 +142,8 @@ void U_CALLCONV initializeStatics(UErrorCode &status) { u"\\U0001DF00-\\U0001DF1E\\U0001DF25-\\U0001DF2A\\U0001E08F\\U0001E7E0-" u"\\U0001E7E6\\U0001E7E8-\\U0001E7EB\\U0001E7ED\\U0001E7EE\\U0001E7F0-" u"\\U0001E7FE\\U00020000-\\U0002A6DF\\U0002A700-\\U0002B739\\U0002B740-" - u"\\U0002B81D\\U0002B820-\\U0002CEA1\\U0002CEB0-\\U0002EBE0\\U00030000-" - u"\\U0003134A\\U00031350-\\U000323AF]"; + u"\\U0002B81D\\U0002B820-\\U0002CEA1\\U0002CEB0-\\U0002EBE0\\U0002EBF0-" + u"\\U0002EE5D\\U00030000-\\U0003134A\\U00031350-\\U000323AF]"; gRecommendedSet = new UnicodeSet(UnicodeString(recommendedPat), status); if (gRecommendedSet == nullptr) { @@ -538,6 +539,90 @@ uspoof_areConfusableUnicodeString(const USpoofChecker *sc, return result; } +U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusable(const USpoofChecker *sc, UBiDiDirection direction, + const char16_t *id1, int32_t length1, + const char16_t *id2, int32_t length2, + UErrorCode *status) { + UnicodeString id1Str((length1 == -1), id1, length1); // Aliasing constructor + UnicodeString id2Str((length2 == -1), id2, length2); // Aliasing constructor + if (id1Str.isBogus() || id2Str.isBogus()) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + return uspoof_areBidiConfusableUnicodeString(sc, direction, id1Str, id2Str, status); +} + +U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusableUTF8(const USpoofChecker *sc, UBiDiDirection direction, + const char *id1, int32_t length1, const char *id2, + int32_t length2, UErrorCode *status) { + if (length1 < -1 || length2 < -1) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + UnicodeString id1Str = UnicodeString::fromUTF8( + StringPiece(id1, length1 >= 0 ? length1 : static_cast<int32_t>(uprv_strlen(id1)))); + UnicodeString id2Str = UnicodeString::fromUTF8( + StringPiece(id2, length2 >= 0 ? length2 : static_cast<int32_t>(uprv_strlen(id2)))); + return uspoof_areBidiConfusableUnicodeString(sc, direction, id1Str, id2Str, status); +} + +U_CAPI uint32_t U_EXPORT2 uspoof_areBidiConfusableUnicodeString(const USpoofChecker *sc, + UBiDiDirection direction, + const icu::UnicodeString &id1, + const icu::UnicodeString &id2, + UErrorCode *status) { + const SpoofImpl *This = SpoofImpl::validateThis(sc, *status); + if (U_FAILURE(*status)) { + return 0; + } + // + // See section 4 of UTS 39 for the algorithm for checking whether two strings are confusable, + // and for definitions of the types (single, whole, mixed-script) of confusables. + + // We only care about a few of the check flags. Ignore the others. + // If no tests relevant to this function have been specified, return an error. + // TODO: is this really the right thing to do? It's probably an error on the caller's part, + // but logically we would just return 0 (no error). + if ((This->fChecks & USPOOF_CONFUSABLE) == 0) { + *status = U_INVALID_STATE_ERROR; + return 0; + } + + // Compute the skeletons and check for confusability. + UnicodeString id1Skeleton; + uspoof_getBidiSkeletonUnicodeString(sc, direction, id1, id1Skeleton, status); + UnicodeString id2Skeleton; + uspoof_getBidiSkeletonUnicodeString(sc, direction, id2, id2Skeleton, status); + if (U_FAILURE(*status)) { + return 0; + } + if (id1Skeleton != id2Skeleton) { + return 0; + } + + // If we get here, the strings are confusable. Now we just need to set the flags for the appropriate + // classes of confusables according to UTS 39 section 4. Start by computing the resolved script sets + // of id1 and id2. + ScriptSet id1RSS; + This->getResolvedScriptSet(id1, id1RSS, *status); + ScriptSet id2RSS; + This->getResolvedScriptSet(id2, id2RSS, *status); + + // Turn on all applicable flags + uint32_t result = 0; + if (id1RSS.intersects(id2RSS)) { + result |= USPOOF_SINGLE_SCRIPT_CONFUSABLE; + } else { + result |= USPOOF_MIXED_SCRIPT_CONFUSABLE; + if (!id1RSS.isEmpty() && !id2RSS.isEmpty()) { + result |= USPOOF_WHOLE_SCRIPT_CONFUSABLE; + } + } + + // Turn off flags that the user doesn't want + return result & This->fChecks; +} + U_CAPI int32_t U_EXPORT2 uspoof_checkUnicodeString(const USpoofChecker *sc, @@ -697,6 +782,60 @@ uspoof_getSkeleton(const USpoofChecker *sc, return destStr.length(); } +U_CAPI int32_t U_EXPORT2 uspoof_getBidiSkeleton(const USpoofChecker *sc, UBiDiDirection direction, + const UChar *id, int32_t length, UChar *dest, + int32_t destCapacity, UErrorCode *status) { + UnicodeString idStr((length == -1), id, length); // Aliasing constructor + if (idStr.isBogus()) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + UnicodeString destStr; + uspoof_getBidiSkeletonUnicodeString(sc, direction, idStr, destStr, status); + return destStr.extract(dest, destCapacity, *status); +} + + + +U_I18N_API UnicodeString &U_EXPORT2 uspoof_getBidiSkeletonUnicodeString(const USpoofChecker *sc, + UBiDiDirection direction, + const UnicodeString &id, + UnicodeString &dest, + UErrorCode *status) { + dest.remove(); + if (direction != UBIDI_LTR && direction != UBIDI_RTL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return dest; + } + UBiDi *bidi = ubidi_open(); + ubidi_setPara(bidi, id.getBuffer(), id.length(), direction, + /*embeddingLevels*/ nullptr, status); + if (U_FAILURE(*status)) { + ubidi_close(bidi); + return dest; + } + UnicodeString reordered; + int32_t const size = ubidi_getProcessedLength(bidi); + UChar* const reorderedBuffer = reordered.getBuffer(size); + if (reorderedBuffer == nullptr) { + *status = U_MEMORY_ALLOCATION_ERROR; + ubidi_close(bidi); + return dest; + } + ubidi_writeReordered(bidi, reorderedBuffer, size, + UBIDI_KEEP_BASE_COMBINING | UBIDI_DO_MIRRORING, status); + reordered.releaseBuffer(size); + ubidi_close(bidi); + + if (U_FAILURE(*status)) { + return dest; + } + + // The type parameter is deprecated since ICU 58; any number may be passed. + constexpr uint32_t deprecatedType = 58; + return uspoof_getSkeletonUnicodeString(sc, deprecatedType, reordered, dest, status); +} + U_I18N_API UnicodeString & U_EXPORT2 @@ -721,19 +860,17 @@ uspoof_getSkeletonUnicodeString(const USpoofChecker *sc, for (inputIndex=0; inputIndex < normalizedLen; ) { UChar32 c = nfdId.char32At(inputIndex); inputIndex += U16_LENGTH(c); - This->fSpoofData->confusableLookup(c, skelStr); + if (!u_hasBinaryProperty(c, UCHAR_DEFAULT_IGNORABLE_CODE_POINT)) { + This->fSpoofData->confusableLookup(c, skelStr); + } } gNfdNormalizer->normalize(skelStr, dest, *status); return dest; } - -U_CAPI int32_t U_EXPORT2 -uspoof_getSkeletonUTF8(const USpoofChecker *sc, - uint32_t type, - const char *id, int32_t length, - char *dest, int32_t destCapacity, +U_CAPI int32_t U_EXPORT2 uspoof_getSkeletonUTF8(const USpoofChecker *sc, uint32_t type, const char *id, + int32_t length, char *dest, int32_t destCapacity, UErrorCode *status) { SpoofImpl::validateThis(sc, *status); if (U_FAILURE(*status)) { @@ -744,7 +881,8 @@ uspoof_getSkeletonUTF8(const USpoofChecker *sc, return 0; } - UnicodeString srcStr = UnicodeString::fromUTF8(StringPiece(id, length>=0 ? length : static_cast<int32_t>(uprv_strlen(id)))); + UnicodeString srcStr = UnicodeString::fromUTF8( + StringPiece(id, length >= 0 ? length : static_cast<int32_t>(uprv_strlen(id)))); UnicodeString destStr; uspoof_getSkeletonUnicodeString(sc, type, srcStr, destStr, status); if (U_FAILURE(*status)) { @@ -752,8 +890,28 @@ uspoof_getSkeletonUTF8(const USpoofChecker *sc, } int32_t lengthInUTF8 = 0; - u_strToUTF8(dest, destCapacity, &lengthInUTF8, - destStr.getBuffer(), destStr.length(), status); + u_strToUTF8(dest, destCapacity, &lengthInUTF8, destStr.getBuffer(), destStr.length(), status); + return lengthInUTF8; +} + +U_CAPI int32_t U_EXPORT2 uspoof_getBidiSkeletonUTF8(const USpoofChecker *sc, UBiDiDirection direction, + const char *id, int32_t length, char *dest, + int32_t destCapacity, UErrorCode *status) { + if (length < -1) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + UnicodeString srcStr = UnicodeString::fromUTF8( + StringPiece(id, length >= 0 ? length : static_cast<int32_t>(uprv_strlen(id)))); + UnicodeString destStr; + uspoof_getBidiSkeletonUnicodeString(sc, direction, srcStr, destStr, status); + if (U_FAILURE(*status)) { + return 0; + } + + int32_t lengthInUTF8 = 0; + u_strToUTF8(dest, destCapacity, &lengthInUTF8, destStr.getBuffer(), destStr.length(), status); return lengthInUTF8; } diff --git a/thirdparty/icu4c/icudt73l.dat b/thirdparty/icu4c/icudt74l.dat Binary files differindex fc007e5f96..8576067fd0 100644 --- a/thirdparty/icu4c/icudt73l.dat +++ b/thirdparty/icu4c/icudt74l.dat diff --git a/thirdparty/linuxbsd_headers/README.md b/thirdparty/linuxbsd_headers/README.md index af902aa97a..225dd62ad0 100644 --- a/thirdparty/linuxbsd_headers/README.md +++ b/thirdparty/linuxbsd_headers/README.md @@ -9,20 +9,21 @@ readability. - Upstream: https://www.alsa-project.org/ - Version: 1.1.3-5 -- License: LPGL-2.1+ +- License: LGPL-2.1+ Patches in the `patches` directory should be re-applied after updates. + ## dbus -- Upstream: https://www.freedesktop.org/wiki/software/dbus/ +- Upstream: https://www.freedesktop.org/wiki/Software/dbus/ - Version: 1.12.2 - License: AFL-2.1 ## fontconfig -- Upstream: https://www.freedesktop.org/wiki/software/fontconfig/ +- Upstream: https://www.freedesktop.org/wiki/Software/fontconfig/ - Version: 2.12.6 - License: fontconfig @@ -31,21 +32,21 @@ Patches in the `patches` directory should be re-applied after updates. - Upstream: http://pulseaudio.org/ - Version: 1.11.1 -- License: LPGL-2.1+ +- License: LGPL-2.1+ -# speechd +## speechd - Upstream: https://www.freebsoft.org/pub/projects/speechd/ - Version: 0.8.8 -- License: LPGL-2.1+ +- License: LGPL-2.1+ -# udev +## udev -- Upstream: https://www.freedesktop.org/wiki/software/systemd/ +- Upstream: https://www.freedesktop.org/wiki/Software/systemd/ - Version: 237 -- License: LPGL-2.1+ +- License: LGPL-2.1+ ## X11 diff --git a/thirdparty/openxr/COPYING.adoc b/thirdparty/openxr/COPYING.adoc index 473e7fdc5d..18c85fa6c7 100644 --- a/thirdparty/openxr/COPYING.adoc +++ b/thirdparty/openxr/COPYING.adoc @@ -1,6 +1,6 @@ = COPYING.adoc for the Khronos Group OpenXR projects -// Copyright (c) 2020-2023, The Khronos Group Inc. +// Copyright (c) 2020-2024, The Khronos Group Inc. // // SPDX-License-Identifier: CC-BY-4.0 diff --git a/thirdparty/openxr/include/openxr/openxr.h b/thirdparty/openxr/include/openxr/openxr.h index 9ba17cbe06..3e9d6599bb 100644 --- a/thirdparty/openxr/include/openxr/openxr.h +++ b/thirdparty/openxr/include/openxr/openxr.h @@ -2,7 +2,7 @@ #define OPENXR_H_ 1 /* -** Copyright 2017-2023 The Khronos Group Inc. +** Copyright 2017-2024, The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -25,7 +25,7 @@ extern "C" { ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL)) // OpenXR current version number. -#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 31) +#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 33) #define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL) #define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL) @@ -218,6 +218,18 @@ typedef enum XrResult { XR_RENDER_MODEL_UNAVAILABLE_FB = 1000119020, XR_ERROR_MARKER_NOT_TRACKED_VARJO = -1000124000, XR_ERROR_MARKER_ID_INVALID_VARJO = -1000124001, + XR_ERROR_MARKER_DETECTOR_PERMISSION_DENIED_ML = -1000138000, + XR_ERROR_MARKER_DETECTOR_LOCATE_FAILED_ML = -1000138001, + XR_ERROR_MARKER_DETECTOR_INVALID_DATA_QUERY_ML = -1000138002, + XR_ERROR_MARKER_DETECTOR_INVALID_CREATE_INFO_ML = -1000138003, + XR_ERROR_MARKER_INVALID_ML = -1000138004, + XR_ERROR_LOCALIZATION_MAP_INCOMPATIBLE_ML = -1000139000, + XR_ERROR_LOCALIZATION_MAP_UNAVAILABLE_ML = -1000139001, + XR_ERROR_LOCALIZATION_MAP_FAIL_ML = -1000139002, + XR_ERROR_LOCALIZATION_MAP_IMPORT_EXPORT_PERMISSION_DENIED_ML = -1000139003, + XR_ERROR_LOCALIZATION_MAP_PERMISSION_DENIED_ML = -1000139004, + XR_ERROR_LOCALIZATION_MAP_ALREADY_EXISTS_ML = -1000139005, + XR_ERROR_LOCALIZATION_MAP_CANNOT_EXPORT_CLOUD_MAP_ML = -1000139006, XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT = -1000142001, XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT = -1000142002, XR_SCENE_MARKER_DATA_NOT_STRING_MSFT = 1000147000, @@ -228,6 +240,7 @@ typedef enum XrResult { XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB = -1000169004, XR_ERROR_PASSTHROUGH_COLOR_LUT_BUFFER_SIZE_MISMATCH_META = -1000266000, XR_ERROR_HINT_ALREADY_SET_QCOM = -1000306000, + XR_ERROR_NOT_AN_ANCHOR_HTC = -1000319000, XR_ERROR_SPACE_NOT_LOCATABLE_EXT = -1000429000, XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT = -1000429001, XR_RESULT_MAX_ENUM = 0x7FFFFFFF @@ -445,6 +458,20 @@ typedef enum XrStructureType { XR_TYPE_FRAME_END_INFO_ML = 1000135000, XR_TYPE_GLOBAL_DIMMER_FRAME_END_INFO_ML = 1000136000, XR_TYPE_COORDINATE_SPACE_CREATE_INFO_ML = 1000137000, + XR_TYPE_SYSTEM_MARKER_UNDERSTANDING_PROPERTIES_ML = 1000138000, + XR_TYPE_MARKER_DETECTOR_CREATE_INFO_ML = 1000138001, + XR_TYPE_MARKER_DETECTOR_ARUCO_INFO_ML = 1000138002, + XR_TYPE_MARKER_DETECTOR_SIZE_INFO_ML = 1000138003, + XR_TYPE_MARKER_DETECTOR_APRIL_TAG_INFO_ML = 1000138004, + XR_TYPE_MARKER_DETECTOR_CUSTOM_PROFILE_INFO_ML = 1000138005, + XR_TYPE_MARKER_DETECTOR_SNAPSHOT_INFO_ML = 1000138006, + XR_TYPE_MARKER_DETECTOR_STATE_ML = 1000138007, + XR_TYPE_MARKER_SPACE_CREATE_INFO_ML = 1000138008, + XR_TYPE_LOCALIZATION_MAP_ML = 1000139000, + XR_TYPE_EVENT_DATA_LOCALIZATION_CHANGED_ML = 1000139001, + XR_TYPE_MAP_LOCALIZATION_REQUEST_INFO_ML = 1000139002, + XR_TYPE_LOCALIZATION_MAP_IMPORT_INFO_ML = 1000139003, + XR_TYPE_LOCALIZATION_ENABLE_EVENTS_INFO_ML = 1000139004, XR_TYPE_EVENT_DATA_HEADSET_FIT_CHANGED_ML = 1000472000, XR_TYPE_EVENT_DATA_EYE_CALIBRATION_CHANGED_ML = 1000472001, XR_TYPE_USER_CALIBRATION_ENABLE_EVENTS_INFO_ML = 1000472002, @@ -534,6 +561,8 @@ typedef enum XrStructureType { XR_TYPE_FOVEATION_APPLY_INFO_HTC = 1000318000, XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC = 1000318001, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC = 1000318002, + XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC = 1000319000, + XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC = 1000319001, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT = 1000373000, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX = 1000375000, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX = 1000375001, @@ -580,6 +609,7 @@ typedef enum XrReferenceSpaceType { XR_REFERENCE_SPACE_TYPE_STAGE = 3, XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT = 1000038000, XR_REFERENCE_SPACE_TYPE_COMBINED_EYE_VARJO = 1000121000, + XR_REFERENCE_SPACE_TYPE_LOCALIZATION_MAP_ML = 1000139000, XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT = 1000426000, XR_REFERENCE_SPACE_TYPE_MAX_ENUM = 0x7FFFFFFF } XrReferenceSpaceType; @@ -634,6 +664,8 @@ typedef enum XrObjectType { XR_OBJECT_TYPE_PASSTHROUGH_FB = 1000118000, XR_OBJECT_TYPE_PASSTHROUGH_LAYER_FB = 1000118002, XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB = 1000118004, + XR_OBJECT_TYPE_MARKER_DETECTOR_ML = 1000138000, + XR_OBJECT_TYPE_EXPORTED_LOCALIZATION_MAP_ML = 1000139000, XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT = 1000142000, XR_OBJECT_TYPE_FACE_TRACKER_FB = 1000201000, XR_OBJECT_TYPE_EYE_TRACKER_FB = 1000202000, @@ -1677,7 +1709,7 @@ typedef struct XrCompositionLayerColorScaleBiasKHR { #define XR_KHR_loader_init 1 -#define XR_KHR_loader_init_SPEC_VERSION 1 +#define XR_KHR_loader_init_SPEC_VERSION 2 #define XR_KHR_LOADER_INIT_EXTENSION_NAME "XR_KHR_loader_init" typedef struct XR_MAY_ALIAS XrLoaderInitInfoBaseHeaderKHR { XrStructureType type; @@ -4342,6 +4374,360 @@ typedef struct XrGlobalDimmerFrameEndInfoML { +#define XR_ML_marker_understanding 1 +XR_DEFINE_ATOM(XrMarkerML) +XR_DEFINE_HANDLE(XrMarkerDetectorML) +#define XR_ML_marker_understanding_SPEC_VERSION 1 +#define XR_ML_MARKER_UNDERSTANDING_EXTENSION_NAME "XR_ML_marker_understanding" + +typedef enum XrMarkerDetectorProfileML { + XR_MARKER_DETECTOR_PROFILE_DEFAULT_ML = 0, + XR_MARKER_DETECTOR_PROFILE_SPEED_ML = 1, + XR_MARKER_DETECTOR_PROFILE_ACCURACY_ML = 2, + XR_MARKER_DETECTOR_PROFILE_SMALL_TARGETS_ML = 3, + XR_MARKER_DETECTOR_PROFILE_LARGE_FOV_ML = 4, + XR_MARKER_DETECTOR_PROFILE_CUSTOM_ML = 5, + XR_MARKER_DETECTOR_PROFILE_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerDetectorProfileML; + +typedef enum XrMarkerTypeML { + XR_MARKER_TYPE_ARUCO_ML = 0, + XR_MARKER_TYPE_APRIL_TAG_ML = 1, + XR_MARKER_TYPE_QR_ML = 2, + XR_MARKER_TYPE_EAN_13_ML = 3, + XR_MARKER_TYPE_UPC_A_ML = 4, + XR_MARKER_TYPE_CODE_128_ML = 5, + XR_MARKER_TYPE_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerTypeML; + +typedef enum XrMarkerArucoDictML { + XR_MARKER_ARUCO_DICT_4X4_50_ML = 0, + XR_MARKER_ARUCO_DICT_4X4_100_ML = 1, + XR_MARKER_ARUCO_DICT_4X4_250_ML = 2, + XR_MARKER_ARUCO_DICT_4X4_1000_ML = 3, + XR_MARKER_ARUCO_DICT_5X5_50_ML = 4, + XR_MARKER_ARUCO_DICT_5X5_100_ML = 5, + XR_MARKER_ARUCO_DICT_5X5_250_ML = 6, + XR_MARKER_ARUCO_DICT_5X5_1000_ML = 7, + XR_MARKER_ARUCO_DICT_6X6_50_ML = 8, + XR_MARKER_ARUCO_DICT_6X6_100_ML = 9, + XR_MARKER_ARUCO_DICT_6X6_250_ML = 10, + XR_MARKER_ARUCO_DICT_6X6_1000_ML = 11, + XR_MARKER_ARUCO_DICT_7X7_50_ML = 12, + XR_MARKER_ARUCO_DICT_7X7_100_ML = 13, + XR_MARKER_ARUCO_DICT_7X7_250_ML = 14, + XR_MARKER_ARUCO_DICT_7X7_1000_ML = 15, + XR_MARKER_ARUCO_DICT_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerArucoDictML; + +typedef enum XrMarkerAprilTagDictML { + XR_MARKER_APRIL_TAG_DICT_16H5_ML = 0, + XR_MARKER_APRIL_TAG_DICT_25H9_ML = 1, + XR_MARKER_APRIL_TAG_DICT_36H10_ML = 2, + XR_MARKER_APRIL_TAG_DICT_36H11_ML = 3, + XR_MARKER_APRIL_TAG_DICT_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerAprilTagDictML; + +typedef enum XrMarkerDetectorFpsML { + XR_MARKER_DETECTOR_FPS_LOW_ML = 0, + XR_MARKER_DETECTOR_FPS_MEDIUM_ML = 1, + XR_MARKER_DETECTOR_FPS_HIGH_ML = 2, + XR_MARKER_DETECTOR_FPS_MAX_ML = 3, + XR_MARKER_DETECTOR_FPS_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerDetectorFpsML; + +typedef enum XrMarkerDetectorResolutionML { + XR_MARKER_DETECTOR_RESOLUTION_LOW_ML = 0, + XR_MARKER_DETECTOR_RESOLUTION_MEDIUM_ML = 1, + XR_MARKER_DETECTOR_RESOLUTION_HIGH_ML = 2, + XR_MARKER_DETECTOR_RESOLUTION_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerDetectorResolutionML; + +typedef enum XrMarkerDetectorCameraML { + XR_MARKER_DETECTOR_CAMERA_RGB_CAMERA_ML = 0, + XR_MARKER_DETECTOR_CAMERA_WORLD_CAMERAS_ML = 1, + XR_MARKER_DETECTOR_CAMERA_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerDetectorCameraML; + +typedef enum XrMarkerDetectorCornerRefineMethodML { + XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_NONE_ML = 0, + XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_SUBPIX_ML = 1, + XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_CONTOUR_ML = 2, + XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_APRIL_TAG_ML = 3, + XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerDetectorCornerRefineMethodML; + +typedef enum XrMarkerDetectorFullAnalysisIntervalML { + XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_MAX_ML = 0, + XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_FAST_ML = 1, + XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_MEDIUM_ML = 2, + XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_SLOW_ML = 3, + XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerDetectorFullAnalysisIntervalML; + +typedef enum XrMarkerDetectorStatusML { + XR_MARKER_DETECTOR_STATUS_PENDING_ML = 0, + XR_MARKER_DETECTOR_STATUS_READY_ML = 1, + XR_MARKER_DETECTOR_STATUS_ERROR_ML = 2, + XR_MARKER_DETECTOR_STATUS_MAX_ENUM_ML = 0x7FFFFFFF +} XrMarkerDetectorStatusML; +// XrSystemMarkerUnderstandingPropertiesML extends XrSystemProperties +typedef struct XrSystemMarkerUnderstandingPropertiesML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsMarkerUnderstanding; +} XrSystemMarkerUnderstandingPropertiesML; + +typedef struct XrMarkerDetectorCreateInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrMarkerDetectorProfileML profile; + XrMarkerTypeML markerType; +} XrMarkerDetectorCreateInfoML; + +// XrMarkerDetectorArucoInfoML extends XrMarkerDetectorCreateInfoML +typedef struct XrMarkerDetectorArucoInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrMarkerArucoDictML arucoDict; +} XrMarkerDetectorArucoInfoML; + +// XrMarkerDetectorSizeInfoML extends XrMarkerDetectorCreateInfoML +typedef struct XrMarkerDetectorSizeInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + float markerLength; +} XrMarkerDetectorSizeInfoML; + +// XrMarkerDetectorAprilTagInfoML extends XrMarkerDetectorCreateInfoML +typedef struct XrMarkerDetectorAprilTagInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrMarkerAprilTagDictML aprilTagDict; +} XrMarkerDetectorAprilTagInfoML; + +// XrMarkerDetectorCustomProfileInfoML extends XrMarkerDetectorCreateInfoML +typedef struct XrMarkerDetectorCustomProfileInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrMarkerDetectorFpsML fpsHint; + XrMarkerDetectorResolutionML resolutionHint; + XrMarkerDetectorCameraML cameraHint; + XrMarkerDetectorCornerRefineMethodML cornerRefineMethod; + XrBool32 useEdgeRefinement; + XrMarkerDetectorFullAnalysisIntervalML fullAnalysisIntervalHint; +} XrMarkerDetectorCustomProfileInfoML; + +typedef struct XrMarkerDetectorSnapshotInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrMarkerDetectorSnapshotInfoML; + +typedef struct XrMarkerDetectorStateML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrMarkerDetectorStatusML state; +} XrMarkerDetectorStateML; + +typedef struct XrMarkerSpaceCreateInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrMarkerDetectorML markerDetector; + XrMarkerML marker; + XrPosef poseInMarkerSpace; +} XrMarkerSpaceCreateInfoML; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateMarkerDetectorML)(XrSession session, const XrMarkerDetectorCreateInfoML* createInfo, XrMarkerDetectorML* markerDetector); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyMarkerDetectorML)(XrMarkerDetectorML markerDetector); +typedef XrResult (XRAPI_PTR *PFN_xrSnapshotMarkerDetectorML)(XrMarkerDetectorML markerDetector, XrMarkerDetectorSnapshotInfoML* snapshotInfo); +typedef XrResult (XRAPI_PTR *PFN_xrGetMarkerDetectorStateML)(XrMarkerDetectorML markerDetector, XrMarkerDetectorStateML* state); +typedef XrResult (XRAPI_PTR *PFN_xrGetMarkersML)(XrMarkerDetectorML markerDetector, uint32_t markerCapacityInput, uint32_t* markerCountOutput, XrMarkerML* markers); +typedef XrResult (XRAPI_PTR *PFN_xrGetMarkerReprojectionErrorML)(XrMarkerDetectorML markerDetector, XrMarkerML marker, float* reprojectionErrorMeters); +typedef XrResult (XRAPI_PTR *PFN_xrGetMarkerLengthML)(XrMarkerDetectorML markerDetector, XrMarkerML marker, float* meters); +typedef XrResult (XRAPI_PTR *PFN_xrGetMarkerNumberML)(XrMarkerDetectorML markerDetector, XrMarkerML marker, uint64_t* number); +typedef XrResult (XRAPI_PTR *PFN_xrGetMarkerStringML)(XrMarkerDetectorML markerDetector, XrMarkerML marker, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer); +typedef XrResult (XRAPI_PTR *PFN_xrCreateMarkerSpaceML)(XrSession session, const XrMarkerSpaceCreateInfoML* createInfo, XrSpace* space); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateMarkerDetectorML( + XrSession session, + const XrMarkerDetectorCreateInfoML* createInfo, + XrMarkerDetectorML* markerDetector); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroyMarkerDetectorML( + XrMarkerDetectorML markerDetector); + +XRAPI_ATTR XrResult XRAPI_CALL xrSnapshotMarkerDetectorML( + XrMarkerDetectorML markerDetector, + XrMarkerDetectorSnapshotInfoML* snapshotInfo); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetMarkerDetectorStateML( + XrMarkerDetectorML markerDetector, + XrMarkerDetectorStateML* state); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetMarkersML( + XrMarkerDetectorML markerDetector, + uint32_t markerCapacityInput, + uint32_t* markerCountOutput, + XrMarkerML* markers); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetMarkerReprojectionErrorML( + XrMarkerDetectorML markerDetector, + XrMarkerML marker, + float* reprojectionErrorMeters); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetMarkerLengthML( + XrMarkerDetectorML markerDetector, + XrMarkerML marker, + float* meters); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetMarkerNumberML( + XrMarkerDetectorML markerDetector, + XrMarkerML marker, + uint64_t* number); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetMarkerStringML( + XrMarkerDetectorML markerDetector, + XrMarkerML marker, + uint32_t bufferCapacityInput, + uint32_t* bufferCountOutput, + char* buffer); + +XRAPI_ATTR XrResult XRAPI_CALL xrCreateMarkerSpaceML( + XrSession session, + const XrMarkerSpaceCreateInfoML* createInfo, + XrSpace* space); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +#define XR_ML_localization_map 1 +XR_DEFINE_HANDLE(XrExportedLocalizationMapML) +#define XR_MAX_LOCALIZATION_MAP_NAME_LENGTH_ML 64 +#define XR_ML_localization_map_SPEC_VERSION 1 +#define XR_ML_LOCALIZATION_MAP_EXTENSION_NAME "XR_ML_localization_map" + +typedef enum XrLocalizationMapStateML { + XR_LOCALIZATION_MAP_STATE_NOT_LOCALIZED_ML = 0, + XR_LOCALIZATION_MAP_STATE_LOCALIZED_ML = 1, + XR_LOCALIZATION_MAP_STATE_LOCALIZATION_PENDING_ML = 2, + XR_LOCALIZATION_MAP_STATE_LOCALIZATION_SLEEPING_BEFORE_RETRY_ML = 3, + XR_LOCALIZATION_MAP_STATE_MAX_ENUM_ML = 0x7FFFFFFF +} XrLocalizationMapStateML; + +typedef enum XrLocalizationMapTypeML { + XR_LOCALIZATION_MAP_TYPE_ON_DEVICE_ML = 0, + XR_LOCALIZATION_MAP_TYPE_CLOUD_ML = 1, + XR_LOCALIZATION_MAP_TYPE_MAX_ENUM_ML = 0x7FFFFFFF +} XrLocalizationMapTypeML; + +typedef enum XrLocalizationMapConfidenceML { + XR_LOCALIZATION_MAP_CONFIDENCE_POOR_ML = 0, + XR_LOCALIZATION_MAP_CONFIDENCE_FAIR_ML = 1, + XR_LOCALIZATION_MAP_CONFIDENCE_GOOD_ML = 2, + XR_LOCALIZATION_MAP_CONFIDENCE_EXCELLENT_ML = 3, + XR_LOCALIZATION_MAP_CONFIDENCE_MAX_ENUM_ML = 0x7FFFFFFF +} XrLocalizationMapConfidenceML; +typedef XrFlags64 XrLocalizationMapErrorFlagsML; + +// Flag bits for XrLocalizationMapErrorFlagsML +static const XrLocalizationMapErrorFlagsML XR_LOCALIZATION_MAP_ERROR_UNKNOWN_BIT_ML = 0x00000001; +static const XrLocalizationMapErrorFlagsML XR_LOCALIZATION_MAP_ERROR_OUT_OF_MAPPED_AREA_BIT_ML = 0x00000002; +static const XrLocalizationMapErrorFlagsML XR_LOCALIZATION_MAP_ERROR_LOW_FEATURE_COUNT_BIT_ML = 0x00000004; +static const XrLocalizationMapErrorFlagsML XR_LOCALIZATION_MAP_ERROR_EXCESSIVE_MOTION_BIT_ML = 0x00000008; +static const XrLocalizationMapErrorFlagsML XR_LOCALIZATION_MAP_ERROR_LOW_LIGHT_BIT_ML = 0x00000010; +static const XrLocalizationMapErrorFlagsML XR_LOCALIZATION_MAP_ERROR_HEADPOSE_BIT_ML = 0x00000020; + +typedef struct XrLocalizationMapML { + XrStructureType type; + void* XR_MAY_ALIAS next; + char name[XR_MAX_LOCALIZATION_MAP_NAME_LENGTH_ML]; + XrUuidEXT mapUuid; + XrLocalizationMapTypeML mapType; +} XrLocalizationMapML; + +typedef struct XrEventDataLocalizationChangedML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSession session; + XrLocalizationMapStateML state; + XrLocalizationMapML map; + XrLocalizationMapConfidenceML confidence; + XrLocalizationMapErrorFlagsML errorFlags; +} XrEventDataLocalizationChangedML; + +typedef struct XrLocalizationMapQueryInfoBaseHeaderML { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrLocalizationMapQueryInfoBaseHeaderML; + +typedef struct XrMapLocalizationRequestInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrUuidEXT mapUuid; +} XrMapLocalizationRequestInfoML; + +typedef struct XrLocalizationMapImportInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t size; + char* data; +} XrLocalizationMapImportInfoML; + +typedef struct XrLocalizationEnableEventsInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrBool32 enabled; +} XrLocalizationEnableEventsInfoML; + +typedef XrResult (XRAPI_PTR *PFN_xrEnableLocalizationEventsML)(XrSession session, const XrLocalizationEnableEventsInfoML * info); +typedef XrResult (XRAPI_PTR *PFN_xrQueryLocalizationMapsML)(XrSession session, const XrLocalizationMapQueryInfoBaseHeaderML* queryInfo, uint32_t mapCapacityInput, uint32_t * mapCountOutput, XrLocalizationMapML* maps); +typedef XrResult (XRAPI_PTR *PFN_xrRequestMapLocalizationML)(XrSession session, const XrMapLocalizationRequestInfoML* requestInfo); +typedef XrResult (XRAPI_PTR *PFN_xrImportLocalizationMapML)(XrSession session, const XrLocalizationMapImportInfoML* importInfo, XrUuidEXT* mapUuid); +typedef XrResult (XRAPI_PTR *PFN_xrCreateExportedLocalizationMapML)(XrSession session, const XrUuidEXT* mapUuid, XrExportedLocalizationMapML* map); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyExportedLocalizationMapML)(XrExportedLocalizationMapML map); +typedef XrResult (XRAPI_PTR *PFN_xrGetExportedLocalizationMapDataML)(XrExportedLocalizationMapML map, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrEnableLocalizationEventsML( + XrSession session, + const XrLocalizationEnableEventsInfoML * info); + +XRAPI_ATTR XrResult XRAPI_CALL xrQueryLocalizationMapsML( + XrSession session, + const XrLocalizationMapQueryInfoBaseHeaderML* queryInfo, + uint32_t mapCapacityInput, + uint32_t * mapCountOutput, + XrLocalizationMapML* maps); + +XRAPI_ATTR XrResult XRAPI_CALL xrRequestMapLocalizationML( + XrSession session, + const XrMapLocalizationRequestInfoML* requestInfo); + +XRAPI_ATTR XrResult XRAPI_CALL xrImportLocalizationMapML( + XrSession session, + const XrLocalizationMapImportInfoML* importInfo, + XrUuidEXT* mapUuid); + +XRAPI_ATTR XrResult XRAPI_CALL xrCreateExportedLocalizationMapML( + XrSession session, + const XrUuidEXT* mapUuid, + XrExportedLocalizationMapML* map); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroyExportedLocalizationMapML( + XrExportedLocalizationMapML map); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetExportedLocalizationMapDataML( + XrExportedLocalizationMapML map, + uint32_t bufferCapacityInput, + uint32_t* bufferCountOutput, + char* buffer); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + #define XR_MSFT_spatial_anchor_persistence 1 XR_DEFINE_HANDLE(XrSpatialAnchorStoreConnectionMSFT) #define XR_MAX_SPATIAL_ANCHOR_NAME_SIZE_MSFT 256 @@ -5814,6 +6200,11 @@ XRAPI_ATTR XrResult XRAPI_CALL xrUpdatePassthroughColorLutMETA( #endif /* !XR_NO_PROTOTYPES */ +#define XR_META_touch_controller_plus 1 +#define XR_META_touch_controller_plus_SPEC_VERSION 1 +#define XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME "XR_META_touch_controller_plus" + + #define XR_EXT_uuid 1 #define XR_EXT_uuid_SPEC_VERSION 1 #define XR_EXT_UUID_EXTENSION_NAME "XR_EXT_uuid" @@ -5980,6 +6371,46 @@ XRAPI_ATTR XrResult XRAPI_CALL xrApplyFoveationHTC( #endif /* !XR_NO_PROTOTYPES */ +#define XR_HTC_anchor 1 +#define XR_MAX_SPATIAL_ANCHOR_NAME_SIZE_HTC 256 +#define XR_HTC_anchor_SPEC_VERSION 1 +#define XR_HTC_ANCHOR_EXTENSION_NAME "XR_HTC_anchor" +// XrSystemAnchorPropertiesHTC extends XrSystemProperties +typedef struct XrSystemAnchorPropertiesHTC { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsAnchor; +} XrSystemAnchorPropertiesHTC; + +typedef struct XrSpatialAnchorNameHTC { + char name[XR_MAX_SPATIAL_ANCHOR_NAME_SIZE_HTC]; +} XrSpatialAnchorNameHTC; + +typedef struct XrSpatialAnchorCreateInfoHTC { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace space; + XrPosef poseInSpace; + XrSpatialAnchorNameHTC name; +} XrSpatialAnchorCreateInfoHTC; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorHTC)(XrSession session, const XrSpatialAnchorCreateInfoHTC* createInfo, XrSpace* anchor); +typedef XrResult (XRAPI_PTR *PFN_xrGetSpatialAnchorNameHTC)(XrSpace anchor, XrSpatialAnchorNameHTC* name); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorHTC( + XrSession session, + const XrSpatialAnchorCreateInfoHTC* createInfo, + XrSpace* anchor); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetSpatialAnchorNameHTC( + XrSpace anchor, + XrSpatialAnchorNameHTC* name); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + #define XR_EXT_active_action_set_priority 1 #define XR_EXT_active_action_set_priority_SPEC_VERSION 1 #define XR_EXT_ACTIVE_ACTION_SET_PRIORITY_EXTENSION_NAME "XR_EXT_active_action_set_priority" @@ -6274,7 +6705,7 @@ typedef struct XrUserCalibrationEnableEventsInfoML { XrBool32 enabled; } XrUserCalibrationEnableEventsInfoML; -typedef XrResult (XRAPI_PTR *PFN_xrEnableUserCalibrationEventsML)(XrInstance instance, const XrUserCalibrationEnableEventsInfoML* enableInfo); +typedef XrResult (XRAPI_PTR *PFN_xrEnableUserCalibrationEventsML)(XrInstance instance, const XrUserCalibrationEnableEventsInfoML* enableInfo); #ifndef XR_NO_PROTOTYPES #ifdef XR_EXTENSION_PROTOTYPES diff --git a/thirdparty/openxr/include/openxr/openxr_loader_negotiation.h b/thirdparty/openxr/include/openxr/openxr_loader_negotiation.h new file mode 100644 index 0000000000..619b226760 --- /dev/null +++ b/thirdparty/openxr/include/openxr/openxr_loader_negotiation.h @@ -0,0 +1,140 @@ +#ifndef OPENXR_LOADER_NEGOTIATION_H_ +#define OPENXR_LOADER_NEGOTIATION_H_ 1 + +/* +** Copyright 2017-2024, The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 OR MIT +*/ + +/* +** This header is generated from the Khronos OpenXR XML API Registry. +** +*/ + +#include "openxr.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define XR_LOADER_VERSION_1_0 1 + +#define XR_CURRENT_LOADER_API_LAYER_VERSION 1 + + +#define XR_CURRENT_LOADER_RUNTIME_VERSION 1 + + +#define XR_LOADER_INFO_STRUCT_VERSION 1 + + +#define XR_API_LAYER_INFO_STRUCT_VERSION 1 + + +#define XR_RUNTIME_INFO_STRUCT_VERSION 1 + + +#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1 + + +#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1 + + +#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512 + + +typedef enum XrLoaderInterfaceStructs { + XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0, + XR_LOADER_INTERFACE_STRUCT_LOADER_INFO = 1, + XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST = 2, + XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST = 3, + XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO = 4, + XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO = 5, + XR_LOADER_INTERFACE_STRUCTS_MAX_ENUM = 0x7FFFFFFF +} XrLoaderInterfaceStructs; +typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance instance, const char* name, PFN_xrVoidFunction* function); + +typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo; +typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)( + const XrInstanceCreateInfo* info, + const XrApiLayerCreateInfo* apiLayerInfo, + XrInstance* instance); + +typedef struct XrApiLayerNextInfo { + XrLoaderInterfaceStructs structType; + uint32_t structVersion; + size_t structSize; + char layerName[XR_MAX_API_LAYER_NAME_SIZE]; + PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; + PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; + struct XrApiLayerNextInfo* next; +} XrApiLayerNextInfo; + +typedef struct XrApiLayerCreateInfo { + XrLoaderInterfaceStructs structType; + uint32_t structVersion; + size_t structSize; + void* XR_MAY_ALIAS loaderInstance; + char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; + XrApiLayerNextInfo* nextInfo; +} XrApiLayerCreateInfo; + +typedef struct XrNegotiateLoaderInfo { + XrLoaderInterfaceStructs structType; + uint32_t structVersion; + size_t structSize; + uint32_t minInterfaceVersion; + uint32_t maxInterfaceVersion; + XrVersion minApiVersion; + XrVersion maxApiVersion; +} XrNegotiateLoaderInfo; + +typedef struct XrNegotiateRuntimeRequest { + XrLoaderInterfaceStructs structType; + uint32_t structVersion; + size_t structSize; + uint32_t runtimeInterfaceVersion; + XrVersion runtimeApiVersion; + PFN_xrGetInstanceProcAddr getInstanceProcAddr; +} XrNegotiateRuntimeRequest; + +typedef struct XrNegotiateApiLayerRequest { + XrLoaderInterfaceStructs structType; + uint32_t structVersion; + size_t structSize; + uint32_t layerInterfaceVersion; + XrVersion layerApiVersion; + PFN_xrGetInstanceProcAddr getInstanceProcAddr; + PFN_xrCreateApiLayerInstance createApiLayerInstance; +} XrNegotiateApiLayerRequest; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo* info, const XrApiLayerCreateInfo* layerInfo, XrInstance* instance); +typedef XrResult (XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo* loaderInfo, XrNegotiateRuntimeRequest* runtimeRequest); +typedef XrResult (XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo* loaderInfo, const char* layerName, XrNegotiateApiLayerRequest* apiLayerRequest); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateApiLayerInstance( + const XrInstanceCreateInfo* info, + const XrApiLayerCreateInfo* layerInfo, + XrInstance* instance); + +XRAPI_ATTR XrResult XRAPI_CALL xrNegotiateLoaderRuntimeInterface( + const XrNegotiateLoaderInfo* loaderInfo, + XrNegotiateRuntimeRequest* runtimeRequest); + +XRAPI_ATTR XrResult XRAPI_CALL xrNegotiateLoaderApiLayerInterface( + const XrNegotiateLoaderInfo* loaderInfo, + const char* layerName, + XrNegotiateApiLayerRequest* apiLayerRequest); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/openxr/include/openxr/openxr_platform.h b/thirdparty/openxr/include/openxr/openxr_platform.h index e4ddfcbb7d..1f47428676 100644 --- a/thirdparty/openxr/include/openxr/openxr_platform.h +++ b/thirdparty/openxr/include/openxr/openxr_platform.h @@ -2,7 +2,7 @@ #define OPENXR_PLATFORM_H_ 1 /* -** Copyright 2017-2023 The Khronos Group Inc. +** Copyright 2017-2024, The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -22,7 +22,7 @@ extern "C" { #ifdef XR_USE_PLATFORM_ANDROID #define XR_KHR_android_thread_settings 1 -#define XR_KHR_android_thread_settings_SPEC_VERSION 5 +#define XR_KHR_android_thread_settings_SPEC_VERSION 6 #define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME "XR_KHR_android_thread_settings" typedef enum XrAndroidThreadTypeKHR { @@ -489,7 +489,7 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirements2KHR( #ifdef XR_USE_PLATFORM_EGL #define XR_MNDX_egl_enable 1 -#define XR_MNDX_egl_enable_SPEC_VERSION 1 +#define XR_MNDX_egl_enable_SPEC_VERSION 2 #define XR_MNDX_EGL_ENABLE_EXTENSION_NAME "XR_MNDX_egl_enable" typedef PFN_xrVoidFunction (*PFN_xrEglGetProcAddressMNDX)(const char *name); // XrGraphicsBindingEGLMNDX extends XrSessionCreateInfo diff --git a/thirdparty/openxr/include/openxr/openxr_platform_defines.h b/thirdparty/openxr/include/openxr/openxr_platform_defines.h index 820b7b3e1e..cd07c91360 100644 --- a/thirdparty/openxr/include/openxr/openxr_platform_defines.h +++ b/thirdparty/openxr/include/openxr/openxr_platform_defines.h @@ -1,5 +1,5 @@ /* -** Copyright (c) 2017-2023, The Khronos Group Inc. +** Copyright (c) 2017-2024, The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ diff --git a/thirdparty/openxr/include/openxr/openxr_reflection.h b/thirdparty/openxr/include/openxr/openxr_reflection.h index 8f49323417..f6d66363bf 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection.h @@ -2,7 +2,7 @@ #define OPENXR_REFLECTION_H_ 1 /* -** Copyright (c) 2017-2023, The Khronos Group Inc. +** Copyright (c) 2017-2024, The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -114,6 +114,18 @@ XR_ENUM_STR(XrResult); _(XR_RENDER_MODEL_UNAVAILABLE_FB, 1000119020) \ _(XR_ERROR_MARKER_NOT_TRACKED_VARJO, -1000124000) \ _(XR_ERROR_MARKER_ID_INVALID_VARJO, -1000124001) \ + _(XR_ERROR_MARKER_DETECTOR_PERMISSION_DENIED_ML, -1000138000) \ + _(XR_ERROR_MARKER_DETECTOR_LOCATE_FAILED_ML, -1000138001) \ + _(XR_ERROR_MARKER_DETECTOR_INVALID_DATA_QUERY_ML, -1000138002) \ + _(XR_ERROR_MARKER_DETECTOR_INVALID_CREATE_INFO_ML, -1000138003) \ + _(XR_ERROR_MARKER_INVALID_ML, -1000138004) \ + _(XR_ERROR_LOCALIZATION_MAP_INCOMPATIBLE_ML, -1000139000) \ + _(XR_ERROR_LOCALIZATION_MAP_UNAVAILABLE_ML, -1000139001) \ + _(XR_ERROR_LOCALIZATION_MAP_FAIL_ML, -1000139002) \ + _(XR_ERROR_LOCALIZATION_MAP_IMPORT_EXPORT_PERMISSION_DENIED_ML, -1000139003) \ + _(XR_ERROR_LOCALIZATION_MAP_PERMISSION_DENIED_ML, -1000139004) \ + _(XR_ERROR_LOCALIZATION_MAP_ALREADY_EXISTS_ML, -1000139005) \ + _(XR_ERROR_LOCALIZATION_MAP_CANNOT_EXPORT_CLOUD_MAP_ML, -1000139006) \ _(XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT, -1000142001) \ _(XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT, -1000142002) \ _(XR_SCENE_MARKER_DATA_NOT_STRING_MSFT, 1000147000) \ @@ -124,6 +136,7 @@ XR_ENUM_STR(XrResult); _(XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB, -1000169004) \ _(XR_ERROR_PASSTHROUGH_COLOR_LUT_BUFFER_SIZE_MISMATCH_META, -1000266000) \ _(XR_ERROR_HINT_ALREADY_SET_QCOM, -1000306000) \ + _(XR_ERROR_NOT_AN_ANCHOR_HTC, -1000319000) \ _(XR_ERROR_SPACE_NOT_LOCATABLE_EXT, -1000429000) \ _(XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT, -1000429001) \ _(XR_RESULT_MAX_ENUM, 0x7FFFFFFF) @@ -340,6 +353,20 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_FRAME_END_INFO_ML, 1000135000) \ _(XR_TYPE_GLOBAL_DIMMER_FRAME_END_INFO_ML, 1000136000) \ _(XR_TYPE_COORDINATE_SPACE_CREATE_INFO_ML, 1000137000) \ + _(XR_TYPE_SYSTEM_MARKER_UNDERSTANDING_PROPERTIES_ML, 1000138000) \ + _(XR_TYPE_MARKER_DETECTOR_CREATE_INFO_ML, 1000138001) \ + _(XR_TYPE_MARKER_DETECTOR_ARUCO_INFO_ML, 1000138002) \ + _(XR_TYPE_MARKER_DETECTOR_SIZE_INFO_ML, 1000138003) \ + _(XR_TYPE_MARKER_DETECTOR_APRIL_TAG_INFO_ML, 1000138004) \ + _(XR_TYPE_MARKER_DETECTOR_CUSTOM_PROFILE_INFO_ML, 1000138005) \ + _(XR_TYPE_MARKER_DETECTOR_SNAPSHOT_INFO_ML, 1000138006) \ + _(XR_TYPE_MARKER_DETECTOR_STATE_ML, 1000138007) \ + _(XR_TYPE_MARKER_SPACE_CREATE_INFO_ML, 1000138008) \ + _(XR_TYPE_LOCALIZATION_MAP_ML, 1000139000) \ + _(XR_TYPE_EVENT_DATA_LOCALIZATION_CHANGED_ML, 1000139001) \ + _(XR_TYPE_MAP_LOCALIZATION_REQUEST_INFO_ML, 1000139002) \ + _(XR_TYPE_LOCALIZATION_MAP_IMPORT_INFO_ML, 1000139003) \ + _(XR_TYPE_LOCALIZATION_ENABLE_EVENTS_INFO_ML, 1000139004) \ _(XR_TYPE_EVENT_DATA_HEADSET_FIT_CHANGED_ML, 1000472000) \ _(XR_TYPE_EVENT_DATA_EYE_CALIBRATION_CHANGED_ML, 1000472001) \ _(XR_TYPE_USER_CALIBRATION_ENABLE_EVENTS_INFO_ML, 1000472002) \ @@ -429,6 +456,8 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_FOVEATION_APPLY_INFO_HTC, 1000318000) \ _(XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC, 1000318001) \ _(XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC, 1000318002) \ + _(XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC, 1000319000) \ + _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC, 1000319001) \ _(XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT, 1000373000) \ _(XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX, 1000375000) \ _(XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX, 1000375001) \ @@ -467,6 +496,7 @@ XR_ENUM_STR(XrResult); _(XR_REFERENCE_SPACE_TYPE_STAGE, 3) \ _(XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT, 1000038000) \ _(XR_REFERENCE_SPACE_TYPE_COMBINED_EYE_VARJO, 1000121000) \ + _(XR_REFERENCE_SPACE_TYPE_LOCALIZATION_MAP_ML, 1000139000) \ _(XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT, 1000426000) \ _(XR_REFERENCE_SPACE_TYPE_MAX_ENUM, 0x7FFFFFFF) @@ -517,6 +547,8 @@ XR_ENUM_STR(XrResult); _(XR_OBJECT_TYPE_PASSTHROUGH_FB, 1000118000) \ _(XR_OBJECT_TYPE_PASSTHROUGH_LAYER_FB, 1000118002) \ _(XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB, 1000118004) \ + _(XR_OBJECT_TYPE_MARKER_DETECTOR_ML, 1000138000) \ + _(XR_OBJECT_TYPE_EXPORTED_LOCALIZATION_MAP_ML, 1000139000) \ _(XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT, 1000142000) \ _(XR_OBJECT_TYPE_FACE_TRACKER_FB, 1000201000) \ _(XR_OBJECT_TYPE_EYE_TRACKER_FB, 1000202000) \ @@ -527,6 +559,15 @@ XR_ENUM_STR(XrResult); _(XR_OBJECT_TYPE_PLANE_DETECTOR_EXT, 1000429000) \ _(XR_OBJECT_TYPE_MAX_ENUM, 0x7FFFFFFF) +#define XR_LIST_ENUM_XrLoaderInterfaceStructs(_) \ + _(XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED, 0) \ + _(XR_LOADER_INTERFACE_STRUCT_LOADER_INFO, 1) \ + _(XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST, 2) \ + _(XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST, 3) \ + _(XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO, 4) \ + _(XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO, 5) \ + _(XR_LOADER_INTERFACE_STRUCTS_MAX_ENUM, 0x7FFFFFFF) + #define XR_LIST_ENUM_XrAndroidThreadTypeKHR(_) \ _(XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, 1) \ _(XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR, 2) \ @@ -877,6 +918,107 @@ XR_ENUM_STR(XrResult); _(XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB, 1000203002) \ _(XR_PASSTHROUGH_LAYER_PURPOSE_MAX_ENUM_FB, 0x7FFFFFFF) +#define XR_LIST_ENUM_XrMarkerDetectorProfileML(_) \ + _(XR_MARKER_DETECTOR_PROFILE_DEFAULT_ML, 0) \ + _(XR_MARKER_DETECTOR_PROFILE_SPEED_ML, 1) \ + _(XR_MARKER_DETECTOR_PROFILE_ACCURACY_ML, 2) \ + _(XR_MARKER_DETECTOR_PROFILE_SMALL_TARGETS_ML, 3) \ + _(XR_MARKER_DETECTOR_PROFILE_LARGE_FOV_ML, 4) \ + _(XR_MARKER_DETECTOR_PROFILE_CUSTOM_ML, 5) \ + _(XR_MARKER_DETECTOR_PROFILE_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerTypeML(_) \ + _(XR_MARKER_TYPE_ARUCO_ML, 0) \ + _(XR_MARKER_TYPE_APRIL_TAG_ML, 1) \ + _(XR_MARKER_TYPE_QR_ML, 2) \ + _(XR_MARKER_TYPE_EAN_13_ML, 3) \ + _(XR_MARKER_TYPE_UPC_A_ML, 4) \ + _(XR_MARKER_TYPE_CODE_128_ML, 5) \ + _(XR_MARKER_TYPE_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerArucoDictML(_) \ + _(XR_MARKER_ARUCO_DICT_4X4_50_ML, 0) \ + _(XR_MARKER_ARUCO_DICT_4X4_100_ML, 1) \ + _(XR_MARKER_ARUCO_DICT_4X4_250_ML, 2) \ + _(XR_MARKER_ARUCO_DICT_4X4_1000_ML, 3) \ + _(XR_MARKER_ARUCO_DICT_5X5_50_ML, 4) \ + _(XR_MARKER_ARUCO_DICT_5X5_100_ML, 5) \ + _(XR_MARKER_ARUCO_DICT_5X5_250_ML, 6) \ + _(XR_MARKER_ARUCO_DICT_5X5_1000_ML, 7) \ + _(XR_MARKER_ARUCO_DICT_6X6_50_ML, 8) \ + _(XR_MARKER_ARUCO_DICT_6X6_100_ML, 9) \ + _(XR_MARKER_ARUCO_DICT_6X6_250_ML, 10) \ + _(XR_MARKER_ARUCO_DICT_6X6_1000_ML, 11) \ + _(XR_MARKER_ARUCO_DICT_7X7_50_ML, 12) \ + _(XR_MARKER_ARUCO_DICT_7X7_100_ML, 13) \ + _(XR_MARKER_ARUCO_DICT_7X7_250_ML, 14) \ + _(XR_MARKER_ARUCO_DICT_7X7_1000_ML, 15) \ + _(XR_MARKER_ARUCO_DICT_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerAprilTagDictML(_) \ + _(XR_MARKER_APRIL_TAG_DICT_16H5_ML, 0) \ + _(XR_MARKER_APRIL_TAG_DICT_25H9_ML, 1) \ + _(XR_MARKER_APRIL_TAG_DICT_36H10_ML, 2) \ + _(XR_MARKER_APRIL_TAG_DICT_36H11_ML, 3) \ + _(XR_MARKER_APRIL_TAG_DICT_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerDetectorFpsML(_) \ + _(XR_MARKER_DETECTOR_FPS_LOW_ML, 0) \ + _(XR_MARKER_DETECTOR_FPS_MEDIUM_ML, 1) \ + _(XR_MARKER_DETECTOR_FPS_HIGH_ML, 2) \ + _(XR_MARKER_DETECTOR_FPS_MAX_ML, 3) \ + _(XR_MARKER_DETECTOR_FPS_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerDetectorResolutionML(_) \ + _(XR_MARKER_DETECTOR_RESOLUTION_LOW_ML, 0) \ + _(XR_MARKER_DETECTOR_RESOLUTION_MEDIUM_ML, 1) \ + _(XR_MARKER_DETECTOR_RESOLUTION_HIGH_ML, 2) \ + _(XR_MARKER_DETECTOR_RESOLUTION_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerDetectorCameraML(_) \ + _(XR_MARKER_DETECTOR_CAMERA_RGB_CAMERA_ML, 0) \ + _(XR_MARKER_DETECTOR_CAMERA_WORLD_CAMERAS_ML, 1) \ + _(XR_MARKER_DETECTOR_CAMERA_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerDetectorCornerRefineMethodML(_) \ + _(XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_NONE_ML, 0) \ + _(XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_SUBPIX_ML, 1) \ + _(XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_CONTOUR_ML, 2) \ + _(XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_APRIL_TAG_ML, 3) \ + _(XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerDetectorFullAnalysisIntervalML(_) \ + _(XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_MAX_ML, 0) \ + _(XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_FAST_ML, 1) \ + _(XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_MEDIUM_ML, 2) \ + _(XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_SLOW_ML, 3) \ + _(XR_MARKER_DETECTOR_FULL_ANALYSIS_INTERVAL_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrMarkerDetectorStatusML(_) \ + _(XR_MARKER_DETECTOR_STATUS_PENDING_ML, 0) \ + _(XR_MARKER_DETECTOR_STATUS_READY_ML, 1) \ + _(XR_MARKER_DETECTOR_STATUS_ERROR_ML, 2) \ + _(XR_MARKER_DETECTOR_STATUS_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrLocalizationMapStateML(_) \ + _(XR_LOCALIZATION_MAP_STATE_NOT_LOCALIZED_ML, 0) \ + _(XR_LOCALIZATION_MAP_STATE_LOCALIZED_ML, 1) \ + _(XR_LOCALIZATION_MAP_STATE_LOCALIZATION_PENDING_ML, 2) \ + _(XR_LOCALIZATION_MAP_STATE_LOCALIZATION_SLEEPING_BEFORE_RETRY_ML, 3) \ + _(XR_LOCALIZATION_MAP_STATE_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrLocalizationMapTypeML(_) \ + _(XR_LOCALIZATION_MAP_TYPE_ON_DEVICE_ML, 0) \ + _(XR_LOCALIZATION_MAP_TYPE_CLOUD_ML, 1) \ + _(XR_LOCALIZATION_MAP_TYPE_MAX_ENUM_ML, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrLocalizationMapConfidenceML(_) \ + _(XR_LOCALIZATION_MAP_CONFIDENCE_POOR_ML, 0) \ + _(XR_LOCALIZATION_MAP_CONFIDENCE_FAIR_ML, 1) \ + _(XR_LOCALIZATION_MAP_CONFIDENCE_GOOD_ML, 2) \ + _(XR_LOCALIZATION_MAP_CONFIDENCE_EXCELLENT_ML, 3) \ + _(XR_LOCALIZATION_MAP_CONFIDENCE_MAX_ENUM_ML, 0x7FFFFFFF) + #define XR_LIST_ENUM_XrSceneMarkerTypeMSFT(_) \ _(XR_SCENE_MARKER_TYPE_QR_CODE_MSFT, 1) \ _(XR_SCENE_MARKER_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF) @@ -1281,6 +1423,14 @@ XR_ENUM_STR(XrResult); #define XR_LIST_BITS_XrGlobalDimmerFrameEndInfoFlagsML(_) \ _(XR_GLOBAL_DIMMER_FRAME_END_INFO_ENABLED_BIT_ML, 0x00000001) \ +#define XR_LIST_BITS_XrLocalizationMapErrorFlagsML(_) \ + _(XR_LOCALIZATION_MAP_ERROR_UNKNOWN_BIT_ML, 0x00000001) \ + _(XR_LOCALIZATION_MAP_ERROR_OUT_OF_MAPPED_AREA_BIT_ML, 0x00000002) \ + _(XR_LOCALIZATION_MAP_ERROR_LOW_FEATURE_COUNT_BIT_ML, 0x00000004) \ + _(XR_LOCALIZATION_MAP_ERROR_EXCESSIVE_MOTION_BIT_ML, 0x00000008) \ + _(XR_LOCALIZATION_MAP_ERROR_LOW_LIGHT_BIT_ML, 0x00000010) \ + _(XR_LOCALIZATION_MAP_ERROR_HEADPOSE_BIT_ML, 0x00000020) \ + #define XR_LIST_BITS_XrCompositionLayerSpaceWarpInfoFlagsFB(_) \ _(XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0x00000001) \ @@ -1851,6 +2001,54 @@ XR_ENUM_STR(XrResult); _(b) \ _(a) \ +/// Calls your macro with the name of each member of XrApiLayerNextInfo, in order. +#define XR_LIST_STRUCT_XrApiLayerNextInfo(_) \ + _(structType) \ + _(structVersion) \ + _(structSize) \ + _(layerName) \ + _(nextGetInstanceProcAddr) \ + _(nextCreateApiLayerInstance) \ + _(next) \ + +/// Calls your macro with the name of each member of XrApiLayerCreateInfo, in order. +#define XR_LIST_STRUCT_XrApiLayerCreateInfo(_) \ + _(structType) \ + _(structVersion) \ + _(structSize) \ + _(loaderInstance) \ + _(settings_file_location) \ + _(nextInfo) \ + +/// Calls your macro with the name of each member of XrNegotiateLoaderInfo, in order. +#define XR_LIST_STRUCT_XrNegotiateLoaderInfo(_) \ + _(structType) \ + _(structVersion) \ + _(structSize) \ + _(minInterfaceVersion) \ + _(maxInterfaceVersion) \ + _(minApiVersion) \ + _(maxApiVersion) \ + +/// Calls your macro with the name of each member of XrNegotiateRuntimeRequest, in order. +#define XR_LIST_STRUCT_XrNegotiateRuntimeRequest(_) \ + _(structType) \ + _(structVersion) \ + _(structSize) \ + _(runtimeInterfaceVersion) \ + _(runtimeApiVersion) \ + _(getInstanceProcAddr) \ + +/// Calls your macro with the name of each member of XrNegotiateApiLayerRequest, in order. +#define XR_LIST_STRUCT_XrNegotiateApiLayerRequest(_) \ + _(structType) \ + _(structVersion) \ + _(structSize) \ + _(layerInterfaceVersion) \ + _(layerApiVersion) \ + _(getInstanceProcAddr) \ + _(createApiLayerInstance) \ + /// Calls your macro with the name of each member of XrCompositionLayerCubeKHR, in order. #define XR_LIST_STRUCT_XrCompositionLayerCubeKHR(_) \ _(type) \ @@ -3212,6 +3410,109 @@ XR_ENUM_STR(XrResult); _(cfuid) \ _(poseInCoordinateSpace) \ +/// Calls your macro with the name of each member of XrSystemMarkerUnderstandingPropertiesML, in order. +#define XR_LIST_STRUCT_XrSystemMarkerUnderstandingPropertiesML(_) \ + _(type) \ + _(next) \ + _(supportsMarkerUnderstanding) \ + +/// Calls your macro with the name of each member of XrMarkerDetectorCreateInfoML, in order. +#define XR_LIST_STRUCT_XrMarkerDetectorCreateInfoML(_) \ + _(type) \ + _(next) \ + _(profile) \ + _(markerType) \ + +/// Calls your macro with the name of each member of XrMarkerDetectorArucoInfoML, in order. +#define XR_LIST_STRUCT_XrMarkerDetectorArucoInfoML(_) \ + _(type) \ + _(next) \ + _(arucoDict) \ + +/// Calls your macro with the name of each member of XrMarkerDetectorSizeInfoML, in order. +#define XR_LIST_STRUCT_XrMarkerDetectorSizeInfoML(_) \ + _(type) \ + _(next) \ + _(markerLength) \ + +/// Calls your macro with the name of each member of XrMarkerDetectorAprilTagInfoML, in order. +#define XR_LIST_STRUCT_XrMarkerDetectorAprilTagInfoML(_) \ + _(type) \ + _(next) \ + _(aprilTagDict) \ + +/// Calls your macro with the name of each member of XrMarkerDetectorCustomProfileInfoML, in order. +#define XR_LIST_STRUCT_XrMarkerDetectorCustomProfileInfoML(_) \ + _(type) \ + _(next) \ + _(fpsHint) \ + _(resolutionHint) \ + _(cameraHint) \ + _(cornerRefineMethod) \ + _(useEdgeRefinement) \ + _(fullAnalysisIntervalHint) \ + +/// Calls your macro with the name of each member of XrMarkerDetectorSnapshotInfoML, in order. +#define XR_LIST_STRUCT_XrMarkerDetectorSnapshotInfoML(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrMarkerDetectorStateML, in order. +#define XR_LIST_STRUCT_XrMarkerDetectorStateML(_) \ + _(type) \ + _(next) \ + _(state) \ + +/// Calls your macro with the name of each member of XrMarkerSpaceCreateInfoML, in order. +#define XR_LIST_STRUCT_XrMarkerSpaceCreateInfoML(_) \ + _(type) \ + _(next) \ + _(markerDetector) \ + _(marker) \ + _(poseInMarkerSpace) \ + +/// Calls your macro with the name of each member of XrLocalizationMapML, in order. +#define XR_LIST_STRUCT_XrLocalizationMapML(_) \ + _(type) \ + _(next) \ + _(name) \ + _(mapUuid) \ + _(mapType) \ + +/// Calls your macro with the name of each member of XrEventDataLocalizationChangedML, in order. +#define XR_LIST_STRUCT_XrEventDataLocalizationChangedML(_) \ + _(type) \ + _(next) \ + _(session) \ + _(state) \ + _(map) \ + _(confidence) \ + _(errorFlags) \ + +/// Calls your macro with the name of each member of XrLocalizationMapQueryInfoBaseHeaderML, in order. +#define XR_LIST_STRUCT_XrLocalizationMapQueryInfoBaseHeaderML(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrMapLocalizationRequestInfoML, in order. +#define XR_LIST_STRUCT_XrMapLocalizationRequestInfoML(_) \ + _(type) \ + _(next) \ + _(mapUuid) \ + +/// Calls your macro with the name of each member of XrLocalizationMapImportInfoML, in order. +#define XR_LIST_STRUCT_XrLocalizationMapImportInfoML(_) \ + _(type) \ + _(next) \ + _(size) \ + _(data) \ + +/// Calls your macro with the name of each member of XrLocalizationEnableEventsInfoML, in order. +#define XR_LIST_STRUCT_XrLocalizationEnableEventsInfoML(_) \ + _(type) \ + _(next) \ + _(enabled) \ + /// Calls your macro with the name of each member of XrSpatialAnchorPersistenceNameMSFT, in order. #define XR_LIST_STRUCT_XrSpatialAnchorPersistenceNameMSFT(_) \ _(name) \ @@ -3941,6 +4242,24 @@ XR_ENUM_STR(XrResult); _(configCount) \ _(configs) \ +/// Calls your macro with the name of each member of XrSystemAnchorPropertiesHTC, in order. +#define XR_LIST_STRUCT_XrSystemAnchorPropertiesHTC(_) \ + _(type) \ + _(next) \ + _(supportsAnchor) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorNameHTC, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorNameHTC(_) \ + _(name) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorCreateInfoHTC, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoHTC(_) \ + _(type) \ + _(next) \ + _(space) \ + _(poseInSpace) \ + _(name) \ + /// Calls your macro with the name of each member of XrActiveActionSetPriorityEXT, in order. #define XR_LIST_STRUCT_XrActiveActionSetPriorityEXT(_) \ _(actionSet) \ @@ -4278,6 +4597,20 @@ XR_ENUM_STR(XrResult); _(XrMarkerSpaceCreateInfoVARJO, XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO) \ _(XrFrameEndInfoML, XR_TYPE_FRAME_END_INFO_ML) \ _(XrGlobalDimmerFrameEndInfoML, XR_TYPE_GLOBAL_DIMMER_FRAME_END_INFO_ML) \ + _(XrSystemMarkerUnderstandingPropertiesML, XR_TYPE_SYSTEM_MARKER_UNDERSTANDING_PROPERTIES_ML) \ + _(XrMarkerDetectorCreateInfoML, XR_TYPE_MARKER_DETECTOR_CREATE_INFO_ML) \ + _(XrMarkerDetectorArucoInfoML, XR_TYPE_MARKER_DETECTOR_ARUCO_INFO_ML) \ + _(XrMarkerDetectorSizeInfoML, XR_TYPE_MARKER_DETECTOR_SIZE_INFO_ML) \ + _(XrMarkerDetectorAprilTagInfoML, XR_TYPE_MARKER_DETECTOR_APRIL_TAG_INFO_ML) \ + _(XrMarkerDetectorCustomProfileInfoML, XR_TYPE_MARKER_DETECTOR_CUSTOM_PROFILE_INFO_ML) \ + _(XrMarkerDetectorSnapshotInfoML, XR_TYPE_MARKER_DETECTOR_SNAPSHOT_INFO_ML) \ + _(XrMarkerDetectorStateML, XR_TYPE_MARKER_DETECTOR_STATE_ML) \ + _(XrMarkerSpaceCreateInfoML, XR_TYPE_MARKER_SPACE_CREATE_INFO_ML) \ + _(XrLocalizationMapML, XR_TYPE_LOCALIZATION_MAP_ML) \ + _(XrEventDataLocalizationChangedML, XR_TYPE_EVENT_DATA_LOCALIZATION_CHANGED_ML) \ + _(XrMapLocalizationRequestInfoML, XR_TYPE_MAP_LOCALIZATION_REQUEST_INFO_ML) \ + _(XrLocalizationMapImportInfoML, XR_TYPE_LOCALIZATION_MAP_IMPORT_INFO_ML) \ + _(XrLocalizationEnableEventsInfoML, XR_TYPE_LOCALIZATION_ENABLE_EVENTS_INFO_ML) \ _(XrSpatialAnchorPersistenceInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT) \ _(XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT) \ _(XrSceneMarkersMSFT, XR_TYPE_SCENE_MARKERS_MSFT) \ @@ -4359,6 +4692,8 @@ XR_ENUM_STR(XrResult); _(XrFoveationApplyInfoHTC, XR_TYPE_FOVEATION_APPLY_INFO_HTC) \ _(XrFoveationDynamicModeInfoHTC, XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC) \ _(XrFoveationCustomModeInfoHTC, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC) \ + _(XrSystemAnchorPropertiesHTC, XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC) \ + _(XrSpatialAnchorCreateInfoHTC, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC) \ _(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \ _(XrSystemForceFeedbackCurlPropertiesMNDX, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX) \ _(XrForceFeedbackCurlApplyLocationsMNDX, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX) \ @@ -4629,6 +4964,8 @@ XR_ENUM_STR(XrResult); _(XR_ML_frame_end_info, 136) \ _(XR_ML_global_dimmer, 137) \ _(XR_ML_compat, 138) \ + _(XR_ML_marker_understanding, 139) \ + _(XR_ML_localization_map, 140) \ _(XR_MSFT_spatial_anchor_persistence, 143) \ _(XR_MSFT_scene_marker, 148) \ _(XR_ULTRALEAP_hand_tracking_forearm, 150) \ @@ -4667,11 +5004,13 @@ XR_ENUM_STR(XrResult); _(XR_FB_spatial_entity_user, 242) \ _(XR_META_headset_id, 246) \ _(XR_META_passthrough_color_lut, 267) \ + _(XR_META_touch_controller_plus, 280) \ _(XR_EXT_uuid, 300) \ _(XR_EXT_hand_interaction, 303) \ _(XR_QCOM_tracking_optimization_settings, 307) \ _(XR_HTC_passthrough, 318) \ _(XR_HTC_foveation, 319) \ + _(XR_HTC_anchor, 320) \ _(XR_EXT_active_action_set_priority, 374) \ _(XR_MNDX_force_feedback_curl, 376) \ _(XR_BD_controller_interaction, 385) \ diff --git a/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h b/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h index f410ddcf79..4241682e0b 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h @@ -2,7 +2,7 @@ #define OPENXR_REFLECTION_PARENT_STRUCTS_H_ 1 /* -** Copyright (c) 2017-2023, The Khronos Group Inc. +** Copyright (c) 2017-2024, The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -58,6 +58,7 @@ This file contains expansion macros (X Macros) for OpenXR structures that have a _avail(XrEventDataSpatialAnchorCreateCompleteFB, XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB) \ _avail(XrEventDataSpaceSetStatusCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) \ _avail(XrEventDataMarkerTrackingUpdateVARJO, XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO) \ + _avail(XrEventDataLocalizationChangedML, XR_TYPE_EVENT_DATA_LOCALIZATION_CHANGED_ML) \ _avail(XrEventDataSpaceQueryResultsAvailableFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) \ _avail(XrEventDataSpaceQueryCompleteFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) \ _avail(XrEventDataSpaceSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB) \ diff --git a/thirdparty/openxr/include/openxr/openxr_reflection_structs.h b/thirdparty/openxr/include/openxr/openxr_reflection_structs.h index 2d23ac15ca..bcc1333e29 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection_structs.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection_structs.h @@ -2,7 +2,7 @@ #define OPENXR_REFLECTION_STRUCTS_H_ 1 /* -** Copyright (c) 2017-2023, The Khronos Group Inc. +** Copyright (c) 2017-2024, The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -225,6 +225,20 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrMarkerSpaceCreateInfoVARJO, XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO) \ _avail(XrFrameEndInfoML, XR_TYPE_FRAME_END_INFO_ML) \ _avail(XrGlobalDimmerFrameEndInfoML, XR_TYPE_GLOBAL_DIMMER_FRAME_END_INFO_ML) \ + _avail(XrSystemMarkerUnderstandingPropertiesML, XR_TYPE_SYSTEM_MARKER_UNDERSTANDING_PROPERTIES_ML) \ + _avail(XrMarkerDetectorCreateInfoML, XR_TYPE_MARKER_DETECTOR_CREATE_INFO_ML) \ + _avail(XrMarkerDetectorArucoInfoML, XR_TYPE_MARKER_DETECTOR_ARUCO_INFO_ML) \ + _avail(XrMarkerDetectorSizeInfoML, XR_TYPE_MARKER_DETECTOR_SIZE_INFO_ML) \ + _avail(XrMarkerDetectorAprilTagInfoML, XR_TYPE_MARKER_DETECTOR_APRIL_TAG_INFO_ML) \ + _avail(XrMarkerDetectorCustomProfileInfoML, XR_TYPE_MARKER_DETECTOR_CUSTOM_PROFILE_INFO_ML) \ + _avail(XrMarkerDetectorSnapshotInfoML, XR_TYPE_MARKER_DETECTOR_SNAPSHOT_INFO_ML) \ + _avail(XrMarkerDetectorStateML, XR_TYPE_MARKER_DETECTOR_STATE_ML) \ + _avail(XrMarkerSpaceCreateInfoML, XR_TYPE_MARKER_SPACE_CREATE_INFO_ML) \ + _avail(XrLocalizationMapML, XR_TYPE_LOCALIZATION_MAP_ML) \ + _avail(XrEventDataLocalizationChangedML, XR_TYPE_EVENT_DATA_LOCALIZATION_CHANGED_ML) \ + _avail(XrMapLocalizationRequestInfoML, XR_TYPE_MAP_LOCALIZATION_REQUEST_INFO_ML) \ + _avail(XrLocalizationMapImportInfoML, XR_TYPE_LOCALIZATION_MAP_IMPORT_INFO_ML) \ + _avail(XrLocalizationEnableEventsInfoML, XR_TYPE_LOCALIZATION_ENABLE_EVENTS_INFO_ML) \ _avail(XrSpatialAnchorPersistenceInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT) \ _avail(XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT) \ _avail(XrSceneMarkersMSFT, XR_TYPE_SCENE_MARKERS_MSFT) \ @@ -306,6 +320,8 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrFoveationApplyInfoHTC, XR_TYPE_FOVEATION_APPLY_INFO_HTC) \ _avail(XrFoveationDynamicModeInfoHTC, XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC) \ _avail(XrFoveationCustomModeInfoHTC, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC) \ + _avail(XrSystemAnchorPropertiesHTC, XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC) \ + _avail(XrSpatialAnchorCreateInfoHTC, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC) \ _avail(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \ _avail(XrSystemForceFeedbackCurlPropertiesMNDX, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX) \ _avail(XrForceFeedbackCurlApplyLocationsMNDX, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX) \ diff --git a/thirdparty/openxr/src/common/extra_algorithms.h b/thirdparty/openxr/src/common/extra_algorithms.h index eec429e12a..bdaa420e9f 100644 --- a/thirdparty/openxr/src/common/extra_algorithms.h +++ b/thirdparty/openxr/src/common/extra_algorithms.h @@ -1,11 +1,11 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // Copyright (c) 2019 Collabora, Ltd. // // SPDX-License-Identifier: Apache-2.0 OR MIT // -// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com> +// Initial Author: Rylie Pavlik <rylie.pavlik@collabora.com> // /*! diff --git a/thirdparty/openxr/src/common/filesystem_utils.cpp b/thirdparty/openxr/src/common/filesystem_utils.cpp index 16e6ff3292..063c4c4cee 100644 --- a/thirdparty/openxr/src/common/filesystem_utils.cpp +++ b/thirdparty/openxr/src/common/filesystem_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017 Valve Corporation // Copyright (c) 2017 LunarG, Inc. // diff --git a/thirdparty/openxr/src/common/filesystem_utils.hpp b/thirdparty/openxr/src/common/filesystem_utils.hpp index 3dea1b2c3e..2a923fac4c 100644 --- a/thirdparty/openxr/src/common/filesystem_utils.hpp +++ b/thirdparty/openxr/src/common/filesystem_utils.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017 Valve Corporation // Copyright (c) 2017 LunarG, Inc. // diff --git a/thirdparty/openxr/src/common/hex_and_handles.h b/thirdparty/openxr/src/common/hex_and_handles.h index 300669033f..12bdb3670c 100644 --- a/thirdparty/openxr/src/common/hex_and_handles.h +++ b/thirdparty/openxr/src/common/hex_and_handles.h @@ -1,11 +1,11 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // Copyright (c) 2019 Collabora, Ltd. // // SPDX-License-Identifier: Apache-2.0 OR MIT // -// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com> +// Initial Author: Rylie Pavlik <rylie.pavlik@collabora.com> // /*! diff --git a/thirdparty/openxr/src/common/loader_interfaces.h b/thirdparty/openxr/src/common/loader_interfaces.h deleted file mode 100644 index 020c3456ea..0000000000 --- a/thirdparty/openxr/src/common/loader_interfaces.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. -// Copyright (c) 2017 Valve Corporation -// Copyright (c) 2017 LunarG, Inc. -// -// SPDX-License-Identifier: Apache-2.0 OR MIT -// -// Initial Author: Mark Young <marky@lunarg.com> -// - -#pragma once - -#include <openxr/openxr.h> - -#ifdef __cplusplus -extern "C" { -#endif - -// Forward declare. -typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo; - -// Function pointer prototype for the xrCreateApiLayerInstance function used in place of xrCreateInstance. -// This function allows us to pass special API layer information to each layer during the process of creating an Instance. -typedef XrResult(XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo *info, - const XrApiLayerCreateInfo *apiLayerInfo, XrInstance *instance); - -// Loader/API Layer Interface versions -// 1 - First version, introduces negotiation structure and functions -#define XR_CURRENT_LOADER_API_LAYER_VERSION 1 - -// Loader/Runtime Interface versions -// 1 - First version, introduces negotiation structure and functions -#define XR_CURRENT_LOADER_RUNTIME_VERSION 1 - -// Version negotiation values -typedef enum XrLoaderInterfaceStructs { - XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0, - XR_LOADER_INTERFACE_STRUCT_LOADER_INFO, - XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST, - XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST, - XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO, - XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO, -} XrLoaderInterfaceStructs; - -#define XR_LOADER_INFO_STRUCT_VERSION 1 -typedef struct XrNegotiateLoaderInfo { - XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_LOADER_INFO - uint32_t structVersion; // XR_LOADER_INFO_STRUCT_VERSION - size_t structSize; // sizeof(XrNegotiateLoaderInfo) - uint32_t minInterfaceVersion; - uint32_t maxInterfaceVersion; - XrVersion minApiVersion; - XrVersion maxApiVersion; -} XrNegotiateLoaderInfo; - -#define XR_API_LAYER_INFO_STRUCT_VERSION 1 -typedef struct XrNegotiateApiLayerRequest { - XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST - uint32_t structVersion; // XR_API_LAYER_INFO_STRUCT_VERSION - size_t structSize; // sizeof(XrNegotiateApiLayerRequest) - uint32_t layerInterfaceVersion; // CURRENT_LOADER_API_LAYER_VERSION - XrVersion layerApiVersion; - PFN_xrGetInstanceProcAddr getInstanceProcAddr; - PFN_xrCreateApiLayerInstance createApiLayerInstance; -} XrNegotiateApiLayerRequest; - -#define XR_RUNTIME_INFO_STRUCT_VERSION 1 -typedef struct XrNegotiateRuntimeRequest { - XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST - uint32_t structVersion; // XR_RUNTIME_INFO_STRUCT_VERSION - size_t structSize; // sizeof(XrNegotiateRuntimeRequest) - uint32_t runtimeInterfaceVersion; // CURRENT_LOADER_RUNTIME_VERSION - XrVersion runtimeApiVersion; - PFN_xrGetInstanceProcAddr getInstanceProcAddr; -} XrNegotiateRuntimeRequest; - -// Function used to negotiate an interface betewen the loader and an API layer. Each library exposing one or -// more API layers needs to expose at least this function. -typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo *loaderInfo, - const char *apiLayerName, - XrNegotiateApiLayerRequest *apiLayerRequest); - -// Function used to negotiate an interface betewen the loader and a runtime. Each runtime should expose -// at least this function. -typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo *loaderInfo, - XrNegotiateRuntimeRequest *runtimeRequest); - -// Forward declare. -typedef struct XrApiLayerNextInfo XrApiLayerNextInfo; - -#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1 -struct XrApiLayerNextInfo { - XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO - uint32_t structVersion; // XR_API_LAYER_NEXT_INFO_STRUCT_VERSION - size_t structSize; // sizeof(XrApiLayerNextInfo) - char layerName[XR_MAX_API_LAYER_NAME_SIZE]; // Name of API layer which should receive this info - PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; // Pointer to next API layer's xrGetInstanceProcAddr - PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; // Pointer to next API layer's xrCreateApiLayerInstance - XrApiLayerNextInfo *next; // Pointer to the next API layer info in the sequence -}; - -#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512 -#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1 -typedef struct XrApiLayerCreateInfo { - XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO - uint32_t structVersion; // XR_API_LAYER_CREATE_INFO_STRUCT_VERSION - size_t structSize; // sizeof(XrApiLayerCreateInfo) - void *loaderInstance; // Pointer to the LoaderInstance class - char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; // Location to the found settings file (or empty '\0') - XrApiLayerNextInfo *nextInfo; // Pointer to the next API layer's Info -} XrApiLayerCreateInfo; - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/thirdparty/openxr/src/common/object_info.cpp b/thirdparty/openxr/src/common/object_info.cpp index 3f8f96bc6e..d45430a609 100644 --- a/thirdparty/openxr/src/common/object_info.cpp +++ b/thirdparty/openxr/src/common/object_info.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // Copyright (c) 2019 Collabora, Ltd. @@ -6,7 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // // Initial Authors: Mark Young <marky@lunarg.com> -// Ryan Pavlik <ryan.pavlik@collabora.com> +// Rylie Pavlik <rylie.pavlik@collabora.com> // Dave Houlton <daveh@lunarg.com> // diff --git a/thirdparty/openxr/src/common/object_info.h b/thirdparty/openxr/src/common/object_info.h index 247ede0dcc..572f06ab15 100644 --- a/thirdparty/openxr/src/common/object_info.h +++ b/thirdparty/openxr/src/common/object_info.h @@ -1,11 +1,11 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // Copyright (c) 2019 Collabora, Ltd. // // SPDX-License-Identifier: Apache-2.0 OR MIT // -// Initial Authors: Mark Young <marky@lunarg.com>, Ryan Pavlik <ryan.pavlik@collabora.com +// Initial Authors: Mark Young <marky@lunarg.com>, Rylie Pavlik <rylie.pavlik@collabora.com // /*! * @file diff --git a/thirdparty/openxr/src/common/platform_utils.hpp b/thirdparty/openxr/src/common/platform_utils.hpp index 0b295f5cc9..c4d75bf259 100644 --- a/thirdparty/openxr/src/common/platform_utils.hpp +++ b/thirdparty/openxr/src/common/platform_utils.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/common/stdfs_conditions.h b/thirdparty/openxr/src/common/stdfs_conditions.h index 0a551f08cd..9e2ba70d42 100644 --- a/thirdparty/openxr/src/common/stdfs_conditions.h +++ b/thirdparty/openxr/src/common/stdfs_conditions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017 Valve Corporation // Copyright (c) 2017 LunarG, Inc. // diff --git a/thirdparty/openxr/src/common/unique_asset.h b/thirdparty/openxr/src/common/unique_asset.h index a8ae8077bc..fd5f8868e3 100644 --- a/thirdparty/openxr/src/common/unique_asset.h +++ b/thirdparty/openxr/src/common/unique_asset.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // // SPDX-License-Identifier: Apache-2.0 OR MIT #pragma once diff --git a/thirdparty/openxr/src/common/vulkan_debug_object_namer.hpp b/thirdparty/openxr/src/common/vulkan_debug_object_namer.hpp index 451219d20f..885389ce8e 100644 --- a/thirdparty/openxr/src/common/vulkan_debug_object_namer.hpp +++ b/thirdparty/openxr/src/common/vulkan_debug_object_namer.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // // SPDX-License-Identifier: Apache-2.0 diff --git a/thirdparty/openxr/src/common/xr_dependencies.h b/thirdparty/openxr/src/common/xr_dependencies.h index 6c9cf2d05f..55d93bfbac 100644 --- a/thirdparty/openxr/src/common/xr_dependencies.h +++ b/thirdparty/openxr/src/common/xr_dependencies.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2023, The Khronos Group Inc. +// Copyright (c) 2018-2024, The Khronos Group Inc. // // SPDX-License-Identifier: Apache-2.0 OR MIT // diff --git a/thirdparty/openxr/src/common/xr_linear.h b/thirdparty/openxr/src/common/xr_linear.h index ce65f8ddfb..2b295ed304 100644 --- a/thirdparty/openxr/src/common/xr_linear.h +++ b/thirdparty/openxr/src/common/xr_linear.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2016, Oculus VR, LLC. // // SPDX-License-Identifier: Apache-2.0 diff --git a/thirdparty/openxr/src/loader/android_utilities.cpp b/thirdparty/openxr/src/loader/android_utilities.cpp index 9a3ad76ce0..5c9b846b5a 100644 --- a/thirdparty/openxr/src/loader/android_utilities.cpp +++ b/thirdparty/openxr/src/loader/android_utilities.cpp @@ -1,9 +1,9 @@ -// Copyright (c) 2020-2023, The Khronos Group Inc. +// Copyright (c) 2020-2024, The Khronos Group Inc. // Copyright (c) 2020-2021, Collabora, Ltd. // // SPDX-License-Identifier: Apache-2.0 OR MIT // -// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com> +// Initial Author: Rylie Pavlik <rylie.pavlik@collabora.com> #include "android_utilities.h" @@ -245,18 +245,38 @@ static int populateFunctions(wrap::android::content::Context const &context, boo return 0; } +// The current file relies on android-jni-wrappers and jnipp, which may throw on failure. +// This is problematic when the loader is compiled with exception handling disabled - the consumers can reasonably +// expect that the compilation with -fno-exceptions will succeed, but the compiler will not accept the code that +// uses `try` & `catch` keywords. We cannot use the `exception_handling.hpp` here since we're not at an ABI boundary, +// so we define helper macros here. This is fine for now since the only occurrence of exception-handling code is in this file. +#ifdef XRLOADER_DISABLE_EXCEPTION_HANDLING + +#define ANDROID_UTILITIES_TRY +#define ANDROID_UTILITIES_CATCH_FALLBACK(...) + +#else + +#define ANDROID_UTILITIES_TRY try +#define ANDROID_UTILITIES_CATCH_FALLBACK(...) \ + catch (const std::exception &e) { \ + __VA_ARGS__ \ + } + +#endif // XRLOADER_DISABLE_EXCEPTION_HANDLING + /// Get cursor for active runtime, parameterized by whether or not we use the system broker static bool getActiveRuntimeCursor(wrap::android::content::Context const &context, jni::Array<std::string> const &projection, bool systemBroker, Cursor &cursor) { auto uri = active_runtime::makeContentUri(systemBroker, XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), ABI); ALOGI("getActiveRuntimeCursor: Querying URI: %s", uri.toString().c_str()); - try { - cursor = context.getContentResolver().query(uri, projection); - } catch (const std::exception &e) { + + ANDROID_UTILITIES_TRY { cursor = context.getContentResolver().query(uri, projection); } + ANDROID_UTILITIES_CATCH_FALLBACK({ ALOGW("Exception when querying %s content resolver: %s", getBrokerTypeName(systemBroker), e.what()); cursor = {}; return false; - } + }) if (cursor.isNull()) { ALOGW("Null cursor when querying %s content resolver.", getBrokerTypeName(systemBroker)); diff --git a/thirdparty/openxr/src/loader/android_utilities.h b/thirdparty/openxr/src/loader/android_utilities.h index f66c9bf1d0..582a65056e 100644 --- a/thirdparty/openxr/src/loader/android_utilities.h +++ b/thirdparty/openxr/src/loader/android_utilities.h @@ -1,9 +1,9 @@ -// Copyright (c) 2020-2023, The Khronos Group Inc. +// Copyright (c) 2020-2024, The Khronos Group Inc. // Copyright (c) 2020-2021, Collabora, Ltd. // // SPDX-License-Identifier: Apache-2.0 OR MIT // -// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com> +// Initial Author: Rylie Pavlik <rylie.pavlik@collabora.com> #pragma once #ifdef __ANDROID__ diff --git a/thirdparty/openxr/src/loader/api_layer_interface.cpp b/thirdparty/openxr/src/loader/api_layer_interface.cpp index c9e24ec40b..fb509de270 100644 --- a/thirdparty/openxr/src/loader/api_layer_interface.cpp +++ b/thirdparty/openxr/src/loader/api_layer_interface.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -9,13 +9,14 @@ #include "api_layer_interface.hpp" -#include "loader_interfaces.h" +#include "loader_init_data.hpp" #include "loader_logger.hpp" #include "loader_platform.hpp" #include "manifest_file.hpp" #include "platform_utils.hpp" #include <openxr/openxr.h> +#include <openxr/openxr_loader_negotiation.h> #include <cstring> #include <memory> @@ -282,6 +283,38 @@ XrResult ApiLayerInterface::LoadApiLayers(const std::string& openxr_command, uin LoaderLogger::LogWarningMessage(openxr_command, warning_message); continue; } +#ifdef XR_KHR_LOADER_INIT_SUPPORT + if (!LoaderInitData::instance().initialized()) { + LoaderLogger::LogErrorMessage(openxr_command, "ApiLayerInterface::LoadApiLayers skipping manifest file " + + manifest_file->Filename() + + " because xrInitializeLoaderKHR was not yet called."); + + LoaderPlatformLibraryClose(layer_library); + return XR_ERROR_VALIDATION_FAILURE; + } + bool forwardedInitLoader = false; + { + // If we have xrInitializeLoaderKHR exposed as an export, forward call to it. + const auto function_name = manifest_file->GetFunctionName("xrInitializeLoaderKHR"); + auto initLoader = + reinterpret_cast<PFN_xrInitializeLoaderKHR>(LoaderPlatformLibraryGetProcAddr(layer_library, function_name)); + if (initLoader != nullptr) { + // we found the entry point one way or another. + LoaderLogger::LogInfoMessage(openxr_command, + "ApiLayerInterface::LoadApiLayers forwarding xrInitializeLoaderKHR call to API layer " + "before calling xrNegotiateLoaderApiLayerInterface."); + XrResult res = initLoader(LoaderInitData::instance().getParam()); + if (!XR_SUCCEEDED(res)) { + LoaderLogger::LogErrorMessage( + openxr_command, "ApiLayerInterface::LoadApiLayers forwarded call to xrInitializeLoaderKHR failed."); + + LoaderPlatformLibraryClose(layer_library); + return res; + } + forwardedInitLoader = true; + } + } +#endif // Get and settle on an layer interface version (using any provided name if required). std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderApiLayerInterface"); @@ -324,6 +357,38 @@ XrResult ApiLayerInterface::LoadApiLayers(const std::string& openxr_command, uin LoaderLogger::LogWarningMessage(openxr_command, warning_message); res = XR_ERROR_FILE_CONTENTS_INVALID; } + +#ifdef XR_KHR_LOADER_INIT_SUPPORT + if (XR_SUCCEEDED(res) && !forwardedInitLoader) { + // Forward initialize loader call, where possible and if we did not do so before. + PFN_xrVoidFunction initializeVoid = nullptr; + PFN_xrInitializeLoaderKHR initialize = nullptr; + + // Now we may try asking xrGetInstanceProcAddr on the API layer + if (XR_SUCCEEDED(api_layer_info.getInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR", &initializeVoid))) { + if (initializeVoid == nullptr) { + LoaderLogger::LogErrorMessage(openxr_command, + "ApiLayerInterface::LoadApiLayers got success from xrGetInstanceProcAddr " + "for xrInitializeLoaderKHR, but output a null pointer."); + res = XR_ERROR_RUNTIME_FAILURE; + } else { + initialize = reinterpret_cast<PFN_xrInitializeLoaderKHR>(initializeVoid); + } + } + if (initialize != nullptr) { + // we found the entry point one way or another. + LoaderLogger::LogInfoMessage(openxr_command, + "ApiLayerInterface::LoadApiLayers forwarding xrInitializeLoaderKHR call to API layer " + "after calling xrNegotiateLoaderApiLayerInterface."); + res = initialize(LoaderInitData::instance().getParam()); + if (!XR_SUCCEEDED(res)) { + LoaderLogger::LogErrorMessage( + openxr_command, "ApiLayerInterface::LoadApiLayers forwarded call to xrInitializeLoaderKHR failed."); + } + } + } +#endif + if (XR_FAILED(res)) { if (!any_loaded) { last_error = res; diff --git a/thirdparty/openxr/src/loader/api_layer_interface.hpp b/thirdparty/openxr/src/loader/api_layer_interface.hpp index 98685b0c32..43758b31a4 100644 --- a/thirdparty/openxr/src/loader/api_layer_interface.hpp +++ b/thirdparty/openxr/src/loader/api_layer_interface.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -14,9 +14,9 @@ #include <memory> #include <openxr/openxr.h> +#include <openxr/openxr_loader_negotiation.h> #include "loader_platform.hpp" -#include "loader_interfaces.h" struct XrGeneratedDispatchTable; diff --git a/thirdparty/openxr/src/loader/exception_handling.hpp b/thirdparty/openxr/src/loader/exception_handling.hpp index bc0d9b65e3..62395fdf69 100644 --- a/thirdparty/openxr/src/loader/exception_handling.hpp +++ b/thirdparty/openxr/src/loader/exception_handling.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2019-2023, The Khronos Group Inc. +// Copyright (c) 2019-2024, The Khronos Group Inc. // // SPDX-License-Identifier: Apache-2.0 OR MIT // -// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com> +// Initial Author: Rylie Pavlik <rylie.pavlik@collabora.com> // // Provides protection for C ABI functions if standard library functions may throw. diff --git a/thirdparty/openxr/src/loader/loader_core.cpp b/thirdparty/openxr/src/loader/loader_core.cpp index 06e6870053..8bf2609a08 100644 --- a/thirdparty/openxr/src/loader/loader_core.cpp +++ b/thirdparty/openxr/src/loader/loader_core.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -14,6 +14,7 @@ #include "api_layer_interface.hpp" #include "exception_handling.hpp" #include "hex_and_handles.h" +#include "loader_init_data.hpp" #include "loader_instance.hpp" #include "loader_logger_recorders.hpp" #include "loader_logger.hpp" @@ -77,7 +78,7 @@ inline bool IsMissingNullTerminator(const char (&str)[max_length]) { #ifdef XR_KHR_LOADER_INIT_SUPPORT // platforms that support XR_KHR_loader_init. XRAPI_ATTR XrResult XRAPI_CALL LoaderXrInitializeLoaderKHR(const XrLoaderInitInfoBaseHeaderKHR *loaderInitInfo) XRLOADER_ABI_TRY { LoaderLogger::LogVerboseMessage("xrInitializeLoaderKHR", "Entering loader trampoline"); - return InitializeLoader(loaderInitInfo); + return InitializeLoaderInitData(loaderInitInfo); } XRLOADER_ABI_CATCH_FALLBACK #endif diff --git a/thirdparty/openxr/src/loader/loader_init_data.cpp b/thirdparty/openxr/src/loader/loader_init_data.cpp new file mode 100644 index 0000000000..11d3c4e77b --- /dev/null +++ b/thirdparty/openxr/src/loader/loader_init_data.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2019 Valve Corporation +// Copyright (c) 2017-2019 LunarG, Inc. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Initial Author: Mark Young <marky@lunarg.com> +// + +#include "loader_init_data.hpp" + +#ifdef XR_KHR_LOADER_INIT_SUPPORT + +#ifdef XR_USE_PLATFORM_ANDROID +// Check and copy the Android-specific init data. +XrResult LoaderInitData::initialize(const XrLoaderInitInfoBaseHeaderKHR* info) { + if (info->type != XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) { + return XR_ERROR_VALIDATION_FAILURE; + } + auto cast_info = reinterpret_cast<XrLoaderInitInfoAndroidKHR const*>(info); + + if (cast_info->applicationVM == nullptr) { + return XR_ERROR_VALIDATION_FAILURE; + } + if (cast_info->applicationContext == nullptr) { + return XR_ERROR_VALIDATION_FAILURE; + } + + // Copy and store the JVM pointer and Android Context, ensuring the JVM is initialised. + _data = *cast_info; + _data.next = nullptr; + jni::init(static_cast<jni::JavaVM*>(_data.applicationVM)); + const jni::Object context = jni::Object{static_cast<jni::jobject>(_data.applicationContext)}; + + // Retrieve a reference to the Android AssetManager. + const auto assetManager = context.call<jni::Object>("getAssets()Landroid/content/res/AssetManager;"); + _android_asset_manager = AAssetManager_fromJava(jni::env(), assetManager.getHandle()); + + // Retrieve the path to the native libraries. + const auto applicationContext = context.call<jni::Object>("getApplicationContext()Landroid/content/Context;"); + const auto applicationInfo = context.call<jni::Object>("getApplicationInfo()Landroid/content/pm/ApplicationInfo;"); + _native_library_path = applicationInfo.get<std::string>("nativeLibraryDir"); + + _initialized = true; + return XR_SUCCESS; +} +#endif // XR_USE_PLATFORM_ANDROID + +XrResult InitializeLoaderInitData(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo) { + return LoaderInitData::instance().initialize(loaderInitInfo); +} + +#ifdef XR_USE_PLATFORM_ANDROID +std::string GetAndroidNativeLibraryDir() { return LoaderInitData::instance()._native_library_path; } + +void* Android_Get_Asset_Manager() { return LoaderInitData::instance()._android_asset_manager; } +#endif // XR_USE_PLATFORM_ANDROID + +#endif // XR_KHR_LOADER_INIT_SUPPORT diff --git a/thirdparty/openxr/src/loader/loader_init_data.hpp b/thirdparty/openxr/src/loader/loader_init_data.hpp new file mode 100644 index 0000000000..fe6bc134d3 --- /dev/null +++ b/thirdparty/openxr/src/loader/loader_init_data.hpp @@ -0,0 +1,92 @@ +// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2019 Valve Corporation +// Copyright (c) 2017-2019 LunarG, Inc. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Initial Author: Mark Young <marky@lunarg.com> +// + +#pragma once + +#include <xr_dependencies.h> +#include <openxr/openxr_platform.h> + +#ifdef XR_USE_PLATFORM_ANDROID +#include <json/value.h> +#include <android/asset_manager_jni.h> +#include "android_utilities.h" +#endif // XR_USE_PLATFORM_ANDROID + +#ifdef XR_KHR_LOADER_INIT_SUPPORT + +/*! + * Stores a copy of the data passed to the xrInitializeLoaderKHR function in a singleton. + */ +class LoaderInitData { + public: + /*! + * Singleton accessor. + */ + static LoaderInitData& instance() { + static LoaderInitData obj; + return obj; + } + +#ifdef XR_USE_PLATFORM_ANDROID + /*! + * Type alias for the platform-specific structure type. + */ + using StructType = XrLoaderInitInfoAndroidKHR; + /*! + * Native library path. + */ + std::string _native_library_path; + /*! + * Android asset manager. + */ + AAssetManager* _android_asset_manager; +#else +#error "Platform specific XR_KHR_loader_init structure is not defined for this platform." +#endif + + /*! + * Get our copy of the data, casted to pass to the runtime's matching method. + */ + const XrLoaderInitInfoBaseHeaderKHR* getParam() const { return reinterpret_cast<const XrLoaderInitInfoBaseHeaderKHR*>(&_data); } + + /*! + * Get the data via its real structure type. + */ + const StructType& getData() const { return _data; } + + /*! + * Has this been correctly initialized? + */ + bool initialized() const noexcept { return _initialized; } + + /*! + * Initialize loader data - called by InitializeLoaderInitData() and thus ultimately by the loader's xrInitializeLoaderKHR + * implementation. Each platform that needs this extension will provide an implementation of this. + */ + XrResult initialize(const XrLoaderInitInfoBaseHeaderKHR* info); + + private: + //! Private constructor, forces use of singleton accessor. + LoaderInitData() = default; + //! Platform-specific init data + StructType _data = {}; + //! Flag for indicating whether _data is valid. + bool _initialized = false; +}; + +//! Initialize loader init data, where required. +XrResult InitializeLoaderInitData(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo); + +#ifdef XR_USE_PLATFORM_ANDROID +XrResult GetPlatformRuntimeVirtualManifest(Json::Value& out_manifest); +std::string GetAndroidNativeLibraryDir(); +void* Android_Get_Asset_Manager(); +#endif // XR_USE_PLATFORM_ANDROID + +#endif // XR_KHR_LOADER_INIT_SUPPORT diff --git a/thirdparty/openxr/src/loader/loader_instance.cpp b/thirdparty/openxr/src/loader/loader_instance.cpp index ce5c205505..f18230087f 100644 --- a/thirdparty/openxr/src/loader/loader_instance.cpp +++ b/thirdparty/openxr/src/loader/loader_instance.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -15,13 +15,13 @@ #include "api_layer_interface.hpp" #include "hex_and_handles.h" -#include "loader_interfaces.h" #include "loader_logger.hpp" #include "runtime_interface.hpp" #include "xr_generated_dispatch_table_core.h" #include "xr_generated_loader.hpp" #include <openxr/openxr.h> +#include <openxr/openxr_loader_negotiation.h> #include <cstring> #include <memory> @@ -60,7 +60,7 @@ XrResult Get(LoaderInstance** loader_instance, const char* log_function_name) { bool IsAvailable() { return GetSetCurrentLoaderInstance() != nullptr; } -void Remove() { GetSetCurrentLoaderInstance().release(); } +void Remove() { GetSetCurrentLoaderInstance().reset(nullptr); } } // namespace ActiveLoaderInstance // Extensions that are supported by the loader, but may not be supported diff --git a/thirdparty/openxr/src/loader/loader_instance.hpp b/thirdparty/openxr/src/loader/loader_instance.hpp index a0268a855c..b99e6b047f 100644 --- a/thirdparty/openxr/src/loader/loader_instance.hpp +++ b/thirdparty/openxr/src/loader/loader_instance.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -10,9 +10,9 @@ #pragma once #include "extra_algorithms.h" -#include "loader_interfaces.h" #include <openxr/openxr.h> +#include <openxr/openxr_loader_negotiation.h> #include <array> #include <cmath> diff --git a/thirdparty/openxr/src/loader/loader_logger.cpp b/thirdparty/openxr/src/loader/loader_logger.cpp index 1c8d64f394..593e19a3ba 100644 --- a/thirdparty/openxr/src/loader/loader_logger.cpp +++ b/thirdparty/openxr/src/loader/loader_logger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_logger.hpp b/thirdparty/openxr/src/loader/loader_logger.hpp index d31fac093a..964aa47962 100644 --- a/thirdparty/openxr/src/loader/loader_logger.hpp +++ b/thirdparty/openxr/src/loader/loader_logger.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_logger_recorders.cpp b/thirdparty/openxr/src/loader/loader_logger_recorders.cpp index 32e4687b2f..00392c27bd 100644 --- a/thirdparty/openxr/src/loader/loader_logger_recorders.cpp +++ b/thirdparty/openxr/src/loader/loader_logger_recorders.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_logger_recorders.hpp b/thirdparty/openxr/src/loader/loader_logger_recorders.hpp index 7b934202d5..b676c37e93 100644 --- a/thirdparty/openxr/src/loader/loader_logger_recorders.hpp +++ b/thirdparty/openxr/src/loader/loader_logger_recorders.hpp @@ -1,10 +1,10 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // // SPDX-License-Identifier: Apache-2.0 OR MIT // -// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com> +// Initial Author: Rylie Pavlik <rylie.pavlik@collabora.com> // #pragma once diff --git a/thirdparty/openxr/src/loader/loader_platform.hpp b/thirdparty/openxr/src/loader/loader_platform.hpp index 0ea80c05b8..964116caa4 100644 --- a/thirdparty/openxr/src/loader/loader_platform.hpp +++ b/thirdparty/openxr/src/loader/loader_platform.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/manifest_file.cpp b/thirdparty/openxr/src/loader/manifest_file.cpp index 0683bc166a..f9699ece40 100644 --- a/thirdparty/openxr/src/loader/manifest_file.cpp +++ b/thirdparty/openxr/src/loader/manifest_file.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -18,6 +18,7 @@ #endif // OPENXR_HAVE_COMMON_CONFIG #include "filesystem_utils.hpp" +#include "loader_init_data.hpp" #include "loader_platform.hpp" #include "platform_utils.hpp" #include "loader_logger.hpp" @@ -666,14 +667,14 @@ XrResult RuntimeManifestFile::FindManifestFiles(std::vector<std::unique_ptr<Runt } #else -#if defined(XR_KHR_LOADER_INIT_SUPPORT) +#if defined(XR_USE_PLATFORM_ANDROID) Json::Value virtualManifest; result = GetPlatformRuntimeVirtualManifest(virtualManifest); if (XR_SUCCESS == result) { RuntimeManifestFile::CreateIfValid(virtualManifest, "", manifest_files); return result; } -#endif // defined(XR_KHR_LOADER_INIT_SUPPORT) +#endif // defined(XR_USE_PLATFORM_ANDROID) if (!PlatformGetGlobalRuntimeFileName(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), filename)) { LoaderLogger::LogErrorMessage( "", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment"); diff --git a/thirdparty/openxr/src/loader/manifest_file.hpp b/thirdparty/openxr/src/loader/manifest_file.hpp index 46b842c663..52fe3134b0 100644 --- a/thirdparty/openxr/src/loader/manifest_file.hpp +++ b/thirdparty/openxr/src/loader/manifest_file.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017 Valve Corporation // Copyright (c) 2017 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/runtime_interface.cpp b/thirdparty/openxr/src/loader/runtime_interface.cpp index 8312b15ba4..7812aca987 100644 --- a/thirdparty/openxr/src/loader/runtime_interface.cpp +++ b/thirdparty/openxr/src/loader/runtime_interface.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -9,14 +9,15 @@ #include "runtime_interface.hpp" +#include <openxr/openxr.h> +#include <openxr/openxr_loader_negotiation.h> + #include "manifest_file.hpp" -#include "loader_interfaces.h" +#include "loader_init_data.hpp" #include "loader_logger.hpp" #include "loader_platform.hpp" #include "xr_generated_dispatch_table_core.h" -#include <openxr/openxr.h> - #include <cstring> #include <memory> #include <mutex> @@ -26,8 +27,6 @@ #include <vector> #ifdef XR_USE_PLATFORM_ANDROID -#include "android_utilities.h" -#include <android/asset_manager_jni.h> #include <json/value.h> // Needed for the loader init struct @@ -35,112 +34,6 @@ #include <openxr/openxr_platform.h> #endif // XR_USE_PLATFORM_ANDROID -#ifdef XR_KHR_LOADER_INIT_SUPPORT -namespace { -/*! - * Stores a copy of the data passed to the xrInitializeLoaderKHR function in a singleton. - */ -class LoaderInitData { - public: - /*! - * Singleton accessor. - */ - static LoaderInitData& instance() { - static LoaderInitData obj; - return obj; - } - -#ifdef XR_USE_PLATFORM_ANDROID - /*! - * Type alias for the platform-specific structure type. - */ - using StructType = XrLoaderInitInfoAndroidKHR; - /*! - * Native library path. - */ - std::string _native_library_path; - /*! - * Android asset manager. - */ - AAssetManager* _android_asset_manager; -#endif - - /*! - * Get our copy of the data, casted to pass to the runtime's matching method. - */ - const XrLoaderInitInfoBaseHeaderKHR* getParam() const { return reinterpret_cast<const XrLoaderInitInfoBaseHeaderKHR*>(&_data); } - - /*! - * Get the data via its real structure type. - */ - const StructType& getData() const { return _data; } - - /*! - * Has this been correctly initialized? - */ - bool initialized() const noexcept { return _initialized; } - - /*! - * Initialize loader data - called by InitializeLoader() and thus ultimately by the loader's xrInitializeLoaderKHR - * implementation. Each platform that needs this extension will provide an implementation of this. - */ - XrResult initialize(const XrLoaderInitInfoBaseHeaderKHR* info); - - private: - //! Private constructor, forces use of singleton accessor. - LoaderInitData() = default; - //! Platform-specific init data - StructType _data = {}; - //! Flag for indicating whether _data is valid. - bool _initialized = false; -}; - -#ifdef XR_USE_PLATFORM_ANDROID -// Check and copy the Android-specific init data. -XrResult LoaderInitData::initialize(const XrLoaderInitInfoBaseHeaderKHR* info) { - if (info->type != XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) { - return XR_ERROR_VALIDATION_FAILURE; - } - auto cast_info = reinterpret_cast<XrLoaderInitInfoAndroidKHR const*>(info); - - if (cast_info->applicationVM == nullptr) { - return XR_ERROR_VALIDATION_FAILURE; - } - if (cast_info->applicationContext == nullptr) { - return XR_ERROR_VALIDATION_FAILURE; - } - - // Copy and store the JVM pointer and Android Context, ensuring the JVM is initialised. - _data = *cast_info; - _data.next = nullptr; - jni::init(static_cast<jni::JavaVM*>(_data.applicationVM)); - const jni::Object context = jni::Object{static_cast<jni::jobject>(_data.applicationContext)}; - - // Retrieve a reference to the Android AssetManager. - const auto assetManager = context.call<jni::Object>("getAssets()Landroid/content/res/AssetManager;"); - _android_asset_manager = AAssetManager_fromJava(jni::env(), assetManager.getHandle()); - - // Retrieve the path to the native libraries. - const auto applicationContext = context.call<jni::Object>("getApplicationContext()Landroid/content/Context;"); - const auto applicationInfo = context.call<jni::Object>("getApplicationInfo()Landroid/content/pm/ApplicationInfo;"); - _native_library_path = applicationInfo.get<std::string>("nativeLibraryDir"); - - _initialized = true; - return XR_SUCCESS; -} -#endif // XR_USE_PLATFORM_ANDROID -} // namespace - -XrResult InitializeLoader(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo) { - return LoaderInitData::instance().initialize(loaderInitInfo); -} - -std::string GetAndroidNativeLibraryDir() { return LoaderInitData::instance()._native_library_path; } - -void* Android_Get_Asset_Manager() { return LoaderInitData::instance()._android_asset_manager; } - -#endif // XR_KHR_LOADER_INIT_SUPPORT - #ifdef XR_USE_PLATFORM_ANDROID XrResult GetPlatformRuntimeVirtualManifest(Json::Value& out_manifest) { using wrap::android::content::Context; diff --git a/thirdparty/openxr/src/loader/runtime_interface.hpp b/thirdparty/openxr/src/loader/runtime_interface.hpp index 8d55ec674a..093f8ba767 100644 --- a/thirdparty/openxr/src/loader/runtime_interface.hpp +++ b/thirdparty/openxr/src/loader/runtime_interface.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -19,22 +19,10 @@ #include <mutex> #include <memory> -#ifdef XR_USE_PLATFORM_ANDROID -#define XR_KHR_LOADER_INIT_SUPPORT -#endif - namespace Json { class Value; } -#ifdef XR_KHR_LOADER_INIT_SUPPORT -//! Initialize loader, where required. -XrResult InitializeLoader(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo); -XrResult GetPlatformRuntimeVirtualManifest(Json::Value& out_manifest); -std::string GetAndroidNativeLibraryDir(); -void* Android_Get_Asset_Manager(); -#endif - class RuntimeManifestFile; struct XrGeneratedDispatchTable; diff --git a/thirdparty/openxr/src/loader/xr_generated_loader.cpp b/thirdparty/openxr/src/loader/xr_generated_loader.cpp index 8c79afddc5..7bddbdc3ea 100644 --- a/thirdparty/openxr/src/loader/xr_generated_loader.cpp +++ b/thirdparty/openxr/src/loader/xr_generated_loader.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // SPDX-License-Identifier: Apache-2.0 OR MIT @@ -6,7 +6,7 @@ // See loader_source_generator.py for modifications // ************************************************************ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/xr_generated_loader.hpp b/thirdparty/openxr/src/loader/xr_generated_loader.hpp index e28e35bbcf..68a6b9470d 100644 --- a/thirdparty/openxr/src/loader/xr_generated_loader.hpp +++ b/thirdparty/openxr/src/loader/xr_generated_loader.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // SPDX-License-Identifier: Apache-2.0 OR MIT @@ -6,7 +6,7 @@ // See loader_source_generator.py for modifications // ************************************************************ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -34,10 +34,9 @@ #include "xr_dependencies.h" #include "openxr/openxr.h" +#include "openxr/openxr_loader_negotiation.h" #include "openxr/openxr_platform.h" -#include "loader_interfaces.h" - #include "loader_instance.hpp" #include "loader_platform.hpp" diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table_core.c b/thirdparty/openxr/src/xr_generated_dispatch_table_core.c index de88ef7e6c..e73e8b2b95 100644 --- a/thirdparty/openxr/src/xr_generated_dispatch_table_core.c +++ b/thirdparty/openxr/src/xr_generated_dispatch_table_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019, Valve Corporation // Copyright (c) 2017-2019, LunarG, Inc. @@ -8,7 +8,7 @@ // See utility_source_generator.py for modifications // ************************************************************ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table_core.h b/thirdparty/openxr/src/xr_generated_dispatch_table_core.h index 0f3e7e0502..5871231267 100644 --- a/thirdparty/openxr/src/xr_generated_dispatch_table_core.h +++ b/thirdparty/openxr/src/xr_generated_dispatch_table_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019, Valve Corporation // Copyright (c) 2017-2019, LunarG, Inc. @@ -8,7 +8,7 @@ // See utility_source_generator.py for modifications // ************************************************************ -// Copyright (c) 2017-2023, The Khronos Group Inc. +// Copyright (c) 2017-2024, The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c index a830ca9ebf..05b6d666a9 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.c +++ b/thirdparty/spirv-reflect/spirv_reflect.c @@ -129,6 +129,9 @@ typedef struct SpvReflectPrvDecorations { bool is_flat; bool is_non_writable; bool is_non_readable; + bool is_patch; + bool is_per_vertex; + bool is_per_task; SpvReflectPrvNumberDecoration set; SpvReflectPrvNumberDecoration binding; SpvReflectPrvNumberDecoration input_attachment_index; @@ -515,6 +518,15 @@ static SpvReflectDecorationFlags ApplyDecorations(const SpvReflectPrvDecorations if (p_decoration_fields->is_non_readable) { decorations |= SPV_REFLECT_DECORATION_NON_READABLE; } + if (p_decoration_fields->is_patch) { + decorations |= SPV_REFLECT_DECORATION_PATCH; + } + if (p_decoration_fields->is_per_vertex) { + decorations |= SPV_REFLECT_DECORATION_PER_VERTEX; + } + if (p_decoration_fields->is_per_task) { + decorations |= SPV_REFLECT_DECORATION_PER_TASK; + } return decorations; } @@ -528,6 +540,10 @@ static void ApplyArrayTraits(const SpvReflectTypeDescription* p_type, SpvReflect memcpy(p_array_traits, &p_type->traits.array, sizeof(p_type->traits.array)); } +static bool IsSpecConstant(const SpvReflectPrvNode* p_node) { + return (p_node->op == SpvOpSpecConstant || p_node->op == SpvOpSpecConstantOp); +} + static SpvReflectPrvNode* FindNode( SpvReflectPrvParser* p_parser, uint32_t result_id) @@ -599,6 +615,9 @@ static uint32_t FindBaseId(SpvReflectPrvParser* p_parser, } base_id = base_ac->base_id; base_node = FindNode(p_parser, base_id); + if (IsNull(base_node)) { + return 0; + } } return base_id; } @@ -618,12 +637,15 @@ static SpvReflectBlockVariable* GetRefBlkVar(SpvReflectPrvParser* p_parser, bool IsPointerToPointer(SpvReflectPrvParser* p_parser, uint32_t type_id) { SpvReflectPrvNode* ptr_node = FindNode(p_parser, type_id); - if (ptr_node->op != SpvOpTypePointer) { + if (IsNull(ptr_node) || (ptr_node->op != SpvOpTypePointer)) { return false; } uint32_t pte_id = 0; UNCHECKED_READU32(p_parser, ptr_node->word_offset + 3, pte_id); SpvReflectPrvNode* pte_node = FindNode(p_parser, pte_id); + if (IsNull(pte_node)) { + return false; + } return pte_node->op == SpvOpTypePointer; } @@ -1493,6 +1515,9 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) case SpvDecorationFlat: case SpvDecorationNonWritable: case SpvDecorationNonReadable: + case SpvDecorationPatch: + case SpvDecorationPerVertexKHR: + case SpvDecorationPerTaskNV: case SpvDecorationLocation: case SpvDecorationComponent: case SpvDecorationBinding: @@ -1597,6 +1622,18 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) } break; + case SpvDecorationPatch: { + p_target_decorations->is_patch = true; + } break; + + case SpvDecorationPerVertexKHR: { + p_target_decorations->is_per_vertex = true; + } break; + + case SpvDecorationPerTaskNV: { + p_target_decorations->is_per_task = true; + } break; + case SpvDecorationLocation: { uint32_t word_offset = p_node->word_offset + member_offset + 3; CHECKED_READU32(p_parser, word_offset, p_target_decorations->location.value); @@ -1846,8 +1883,7 @@ static SpvReflectResult ParseType( SpvReflectPrvNode* p_length_node = FindNode(p_parser, length_id); if (IsNotNull(p_length_node)) { uint32_t dim_index = p_type->traits.array.dims_count; - if (p_length_node->op == SpvOpSpecConstant || - p_length_node->op == SpvOpSpecConstantOp) { + if (IsSpecConstant(p_length_node)) { p_type->traits.array.dims[dim_index] = (uint32_t)SPV_REFLECT_ARRAY_DIM_SPEC_CONSTANT; p_type->traits.array.spec_constant_op_ids[dim_index] = length_id; @@ -3131,7 +3167,7 @@ static SpvReflectResult ParseInterfaceVariables( } SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id); - if (IsNull(p_node)) { + if (IsNull(p_node) || IsNull(p_type)) { return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; } // If the type is a pointer, resolve it @@ -3533,7 +3569,8 @@ static SpvReflectResult ParseExecutionModes( if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) { for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) { SpvReflectPrvNode* p_node = &(p_parser->nodes[node_idx]); - if (p_node->op != SpvOpExecutionMode) { + if (p_node->op != SpvOpExecutionMode && + p_node->op != SpvOpExecutionModeId) { continue; } @@ -3560,41 +3597,55 @@ static SpvReflectResult ParseExecutionModes( // Parse execution mode switch (execution_mode) { - default: { - return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_EXECUTION_MODE; - } - break; - case SpvExecutionModeInvocations: { CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->invocations); } break; - case SpvExecutionModeSpacingEqual: - case SpvExecutionModeSpacingFractionalEven: - case SpvExecutionModeSpacingFractionalOdd: - case SpvExecutionModeVertexOrderCw: - case SpvExecutionModeVertexOrderCcw: - case SpvExecutionModePixelCenterInteger: - case SpvExecutionModeOriginUpperLeft: - case SpvExecutionModeOriginLowerLeft: - case SpvExecutionModeEarlyFragmentTests: - case SpvExecutionModePointMode: - case SpvExecutionModeXfb: - case SpvExecutionModeDepthReplacing: - case SpvExecutionModeDepthGreater: - case SpvExecutionModeDepthLess: - case SpvExecutionModeDepthUnchanged: - break; - case SpvExecutionModeLocalSize: { CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->local_size.x); CHECKED_READU32(p_parser, p_node->word_offset + 4, p_entry_point->local_size.y); CHECKED_READU32(p_parser, p_node->word_offset + 5, p_entry_point->local_size.z); } break; + case SpvExecutionModeLocalSizeId: { + uint32_t local_size_x_id = 0; + uint32_t local_size_y_id = 0; + uint32_t local_size_z_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + 3, local_size_x_id); + CHECKED_READU32(p_parser, p_node->word_offset + 4, local_size_y_id); + CHECKED_READU32(p_parser, p_node->word_offset + 5, local_size_z_id); + + SpvReflectPrvNode* x_node = FindNode(p_parser, local_size_x_id); + SpvReflectPrvNode* y_node = FindNode(p_parser, local_size_y_id); + SpvReflectPrvNode* z_node = FindNode(p_parser, local_size_z_id); + if (IsNotNull(x_node) && IsNotNull(y_node) && IsNotNull(z_node)) { + if (IsSpecConstant(x_node)) { + p_entry_point->local_size.x = + (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT; + } else { + CHECKED_READU32(p_parser, x_node->word_offset + 3, + p_entry_point->local_size.x); + } + + if (IsSpecConstant(y_node)) { + p_entry_point->local_size.y = + (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT; + } else { + CHECKED_READU32(p_parser, y_node->word_offset + 3, + p_entry_point->local_size.y); + } + + if (IsSpecConstant(z_node)) { + p_entry_point->local_size.z = + (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT; + } else { + CHECKED_READU32(p_parser, z_node->word_offset + 3, + p_entry_point->local_size.z); + } + } + } break; - case SpvExecutionModeLocalSizeHint: case SpvExecutionModeInputPoints: case SpvExecutionModeInputLines: case SpvExecutionModeInputLinesAdjacency: @@ -3607,32 +3658,7 @@ static SpvReflectResult ParseExecutionModes( } break; - case SpvExecutionModeOutputPoints: - case SpvExecutionModeOutputLineStrip: - case SpvExecutionModeOutputTriangleStrip: - case SpvExecutionModeVecTypeHint: - case SpvExecutionModeContractionOff: - case SpvExecutionModeInitializer: - case SpvExecutionModeFinalizer: - case SpvExecutionModeSubgroupSize: - case SpvExecutionModeSubgroupsPerWorkgroup: - case SpvExecutionModeSubgroupsPerWorkgroupId: - case SpvExecutionModeLocalSizeId: - case SpvExecutionModeLocalSizeHintId: - case SpvExecutionModePostDepthCoverage: - case SpvExecutionModeDenormPreserve: - case SpvExecutionModeDenormFlushToZero: - case SpvExecutionModeSignedZeroInfNanPreserve: - case SpvExecutionModeRoundingModeRTE: - case SpvExecutionModeRoundingModeRTZ: - case SpvExecutionModeStencilRefReplacingEXT: - case SpvExecutionModeOutputLinesNV: - case SpvExecutionModeOutputPrimitivesNV: - case SpvExecutionModeOutputTrianglesNV: - case SpvExecutionModePixelInterlockOrderedEXT: - case SpvExecutionModePixelInterlockUnorderedEXT: - case SpvExecutionModeSampleInterlockOrderedEXT: - case SpvExecutionModeSampleInterlockUnorderedEXT: + default: break; } p_entry_point->execution_mode_count++; @@ -3777,7 +3803,7 @@ static SpvReflectResult ParsePushConstantBlocks( } SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id); - if (IsNull(p_node)) { + if (IsNull(p_node) || IsNull(p_type)) { return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; } // If the type is a pointer, resolve it diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h index 759db682f4..3395f6ce62 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.h +++ b/thirdparty/spirv-reflect/spirv_reflect.h @@ -134,6 +134,9 @@ NOTE: HLSL row_major and column_major decorations are reversed SPIRV-Reflect reads the data as is and does not make any attempt to correct it to match what's in the source. + The Patch, PerVertex, and PerTask are used for Interface + variables that can have array + */ typedef enum SpvReflectDecorationFlagBits { SPV_REFLECT_DECORATION_NONE = 0x00000000, @@ -147,6 +150,9 @@ typedef enum SpvReflectDecorationFlagBits { SPV_REFLECT_DECORATION_NON_WRITABLE = 0x00000080, SPV_REFLECT_DECORATION_RELAXED_PRECISION = 0x00000100, SPV_REFLECT_DECORATION_NON_READABLE = 0x00000200, + SPV_REFLECT_DECORATION_PATCH = 0x00000400, + SPV_REFLECT_DECORATION_PER_VERTEX = 0x00000800, + SPV_REFLECT_DECORATION_PER_TASK = 0x00001000, } SpvReflectDecorationFlagBits; typedef uint32_t SpvReflectDecorationFlags; @@ -478,6 +484,10 @@ typedef struct SpvReflectDescriptorSet { SpvReflectDescriptorBinding** bindings; } SpvReflectDescriptorSet; +typedef enum SpvReflectExecutionModeValue { + SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT = 0xFFFFFFFF // specialization constant +} SpvReflectExecutionModeValue; + /*! @struct SpvReflectEntryPoint */ diff --git a/thirdparty/thorvg/AUTHORS b/thirdparty/thorvg/AUTHORS index 3a459e9bb4..d5d5e9be97 100644 --- a/thirdparty/thorvg/AUTHORS +++ b/thirdparty/thorvg/AUTHORS @@ -23,3 +23,5 @@ Rafał Mikrut <mikrutrafal@protonmail.com> Martin Capitanio <capnm@capitanio.org> RuiwenTang <tangruiwen1989@gmail.com> YouJin Lee <ol-of@naver.com> +SergeyLebedkin <sergii@lottiefiles.com> +Jinny You <jinny@lottiefiles.com> diff --git a/thirdparty/thorvg/LICENSE b/thirdparty/thorvg/LICENSE index d056ff6cbf..f97be65005 100644 --- a/thirdparty/thorvg/LICENSE +++ b/thirdparty/thorvg/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020 - 2023 notice for the ThorVG Project (see AUTHORS) +Copyright (c) 2020 - 2024 notice for the ThorVG Project (see AUTHORS) 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: diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index 818739b113..73e72c74a7 100644 --- a/thirdparty/thorvg/inc/config.h +++ b/thirdparty/thorvg/inc/config.h @@ -9,5 +9,5 @@ // For internal debugging: //#define THORVG_LOG_ENABLED -#define THORVG_VERSION_STRING "0.11.2" +#define THORVG_VERSION_STRING "0.12.1" #endif diff --git a/thirdparty/thorvg/inc/thorvg.h b/thirdparty/thorvg/inc/thorvg.h index 1b9c2d70d3..6aee53f7e0 100644 --- a/thirdparty/thorvg/inc/thorvg.h +++ b/thirdparty/thorvg/inc/thorvg.h @@ -1,17 +1,3 @@ -/*! - * @file thorvg.h - * - * The main APIs enabling the TVG initialization, preparation of the canvas and provisioning of its content: - * - drawing shapes: line, arc, curve, path, polygon... - * - drawing pictures: tvg, svg, png, jpg, bitmap... - * - drawing fillings: solid, linear and radial gradient... - * - drawing stroking: continuous stroking with arbitrary width, join, cap, dash styles. - * - drawing composition: blending, masking, path clipping... - * - drawing scene graph & affine transformation (translation, rotation, scale, ...) - * and finally drawing the canvas and TVG termination. - */ - - #ifndef _THORVG_H_ #define _THORVG_H_ @@ -172,10 +158,10 @@ enum class CompositeMethod InvAlphaMask, ///< Alpha Masking using the complement to the compositing target's pixels as an alpha value. LumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the compositing target's pixels. @since 0.9 InvLumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the complement to the compositing target's pixels. - AddMask, ///< Combines the target and source objects pixels using target alpha. (T * TA) + (S * (255 - TA)) @BETA_API - SubtractMask, ///< Subtracts the source color from the target color while considering their respective target alpha. (T * TA) - (S * (255 - TA)) @BETA_API - IntersectMask, ///< Computes the result by taking the minimum value between the target alpha and the source alpha and multiplies it with the target color. (T * min(TA, SA)) @BETA_API - DifferenceMask ///< Calculates the absolute difference between the target color and the source color multiplied by the complement of the target alpha. abs(T - S * (255 - TA)) @BETA_API + AddMask, ///< Combines the target and source objects pixels using target alpha. (T * TA) + (S * (255 - TA)) (Experimental API) + SubtractMask, ///< Subtracts the source color from the target color while considering their respective target alpha. (T * TA) - (S * (255 - TA)) (Experimental API) + IntersectMask, ///< Computes the result by taking the minimum value between the target alpha and the source alpha and multiplies it with the target color. (T * min(TA, SA)) (Experimental API) + DifferenceMask ///< Calculates the absolute difference between the target color and the source color multiplied by the complement of the target alpha. abs(T - S * (255 - TA)) (Experimental API) }; @@ -186,7 +172,7 @@ enum class CompositeMethod * * @see Paint::blend() * - * @BETA_API + * @note Experimental API */ enum class BlendMethod : uint8_t { @@ -213,7 +199,8 @@ enum class BlendMethod : uint8_t enum class CanvasEngine { Sw = (1 << 1), ///< CPU rasterizer. - Gl = (1 << 2) ///< OpenGL rasterizer. + Gl = (1 << 2), ///< OpenGL rasterizer. + Wg = (1 << 3), ///< WebGPU rasterizer. (Experimental API) }; @@ -247,7 +234,7 @@ struct Matrix * @param pt The vertex coordinate * @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0) * - * @BETA_API + * @note Experimental API */ struct Vertex { @@ -261,7 +248,7 @@ struct Vertex * * @param vertex The three vertices that make up the polygon * - * @BETA_API + * @note Experimental API */ struct Polygon { @@ -291,7 +278,7 @@ public: * * @param[in] degree The value of the angle in degrees. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result rotate(float degree) noexcept; @@ -300,7 +287,7 @@ public: * * @param[in] factor The value of the scaling factor. The default value is 1. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result scale(float factor) noexcept; @@ -313,7 +300,7 @@ public: * @param[in] x The value of the horizontal shift. * @param[in] y The value of the vertical shift. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result translate(float x, float y) noexcept; @@ -324,7 +311,7 @@ public: * * @param[in] m The 3x3 augmented matrix. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result transform(const Matrix& m) noexcept; @@ -345,7 +332,7 @@ public: * * @param[in] o The opacity value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note Setting the opacity with this API may require multiple render pass for composition. It is recommended to avoid changing the opacity if possible. * @note ClipPath won't use the opacity value. (see: enum class CompositeMethod::ClipPath) @@ -358,7 +345,7 @@ public: * @param[in] target The paint of the target object. * @param[in] method The method used to composite the source object with the target. * - * @return Result::Success when succeed, Result::InvalidArguments otherwise. + * @retval Result::Success when succeed, Result::InvalidArguments otherwise. */ Result composite(std::unique_ptr<Paint> target, CompositeMethod method) noexcept; @@ -371,9 +358,9 @@ public: * * @param[in] method The blending method to be set. * - * @return Result::Success when the blending method is successfully set. + * @retval Result::Success when the blending method is successfully set. * - * @BETA_API + * @note Experimental API */ Result blend(BlendMethod method) const noexcept; @@ -404,7 +391,7 @@ public: * @param[out] h The height of the object. * @param[in] transformed If @c true, the paint's transformations are taken into account, otherwise they aren't. * - * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. * * @note The bounding box doesn't indicate the actual drawing region. It's the smallest rectangle that encloses the object. */ @@ -442,7 +429,7 @@ public: * * @return The blending method * - * @BETA_API + * @note Experimental API */ BlendMethod blend() const noexcept; @@ -493,7 +480,7 @@ public: * @param[in] colorStops An array of ColorStop data structure. * @param[in] cnt The count of the @p colorStops array equal to the colors number used in the gradient. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. */ Result colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept; @@ -502,7 +489,7 @@ public: * * @param[in] s The FillSpread value. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. */ Result spread(FillSpread s) noexcept; @@ -513,7 +500,7 @@ public: * * @param[in] m The 3x3 augmented matrix. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result transform(const Matrix& m) noexcept; @@ -538,7 +525,7 @@ public: * * In case no transformation was applied, the identity matrix is returned. * - * @retval The augmented transformation matrix. + * @return The augmented transformation matrix. */ Matrix transform() const noexcept; @@ -600,7 +587,7 @@ public: * @warning Please avoid accessing the paints during Canvas update/draw. You can access them after calling sync(). * @see Canvas::sync() * - * @BETA_API + * @note Experimental API */ std::list<Paint*>& paints() noexcept; @@ -631,7 +618,7 @@ public: * * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. * - * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. * * @see Canvas::push() * @see Canvas::paints() @@ -646,7 +633,7 @@ public: * * @param[in] paint A pointer to the Paint object or @c nullptr. * - * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. * * @note The Update behavior can be asynchronous if the assigned thread number is greater than zero. */ @@ -655,7 +642,7 @@ public: /** * @brief Requests the canvas to draw the Paint objects. * - * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. * * @note Drawing can be asynchronous if the assigned thread number is greater than zero. To guarantee the drawing is done, call sync() afterwards. * @see Canvas::sync() @@ -668,7 +655,7 @@ public: * The Canvas rendering can be performed asynchronously. To make sure that rendering is finished, * the sync() must be called after the draw() regardless of threading. * - * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. * @see Canvas::draw() */ virtual Result sync() noexcept; @@ -702,7 +689,7 @@ public: * @param[in] x2 The horizontal coordinate of the second point used to determine the gradient bounds. * @param[in] y2 The vertical coordinate of the second point used to determine the gradient bounds. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note In case the first and the second points are equal, an object filled with such a gradient fill is not rendered. */ @@ -720,7 +707,7 @@ public: * @param[out] x2 The horizontal coordinate of the second point used to determine the gradient bounds. * @param[out] y2 The vertical coordinate of the second point used to determine the gradient bounds. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. */ Result linear(float* x1, float* y1, float* x2, float* y2) const noexcept; @@ -764,7 +751,7 @@ public: * @param[in] cy The vertical coordinate of the center of the bounding circle. * @param[in] radius The radius of the bounding circle. * - * @return Result::Success when succeed, Result::InvalidArguments in case the @p radius value is zero or less. + * @retval Result::Success when succeed, Result::InvalidArguments in case the @p radius value is zero or less. */ Result radial(float cx, float cy, float radius) noexcept; @@ -777,7 +764,7 @@ public: * @param[out] cy The vertical coordinate of the center of the bounding circle. * @param[out] radius The radius of the bounding circle. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. */ Result radial(float* cx, float* cy, float* radius) const noexcept; @@ -823,7 +810,7 @@ public: * * The transformation matrix, the color, the fill and the stroke properties are retained. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note The memory, where the path data is stored, is not deallocated at this stage for caching effect. */ @@ -837,7 +824,7 @@ public: * @param[in] x The horizontal coordinate of the initial point of the sub-path. * @param[in] y The vertical coordinate of the initial point of the sub-path. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. */ Result moveTo(float x, float y) noexcept; @@ -849,7 +836,7 @@ public: * @param[in] x The horizontal coordinate of the end-point of the line. * @param[in] y The vertical coordinate of the end-point of the line. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note In case this is the first command in the path, it corresponds to the moveTo() call. */ @@ -868,7 +855,7 @@ public: * @param[in] x The horizontal coordinate of the end-point of the curve. * @param[in] y The vertical coordinate of the end-point of the curve. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note In case this is the first command in the path, no data from the path are rendered. */ @@ -879,7 +866,7 @@ public: * * The value of the current point is set to the initial point of the closed sub-path. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note In case the sub-path does not contain any points, this function has no effect. */ @@ -905,7 +892,7 @@ public: * @param[in] rx The x-axis radius of the ellipse defining the rounded corners of the rectangle. * @param[in] ry The y-axis radius of the ellipse defining the rounded corners of the rectangle. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note For @p rx and @p ry greater than or equal to the half of @p w and the half of @p h, respectively, the shape become an ellipse. */ @@ -925,7 +912,7 @@ public: * @param[in] rx The x-axis radius of the ellipse. * @param[in] ry The y-axis radius of the ellipse. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. */ Result appendCircle(float cx, float cy, float rx, float ry) noexcept; @@ -942,7 +929,7 @@ public: * @param[in] sweep The central angle of the arc given in degrees, measured counter-clockwise from @p startAngle. * @param[in] pie Specifies whether to draw radii from the arc's center to both of its end-point - drawn if @c true. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note Setting @p sweep value greater than 360 degrees, is equivalent to calling appendCircle(cx, cy, radius, radius). */ @@ -960,7 +947,7 @@ public: * @param[in] pts The array of the two-dimensional points. * @param[in] ptsCnt The number of the points in the @p pts array. * - * @return Result::Success when succeed, Result::InvalidArguments otherwise. + * @retval Result::Success when succeed, Result::InvalidArguments otherwise. * * @note The interface is designed for optimal path setting if the caller has a completed path commands already. */ @@ -971,7 +958,7 @@ public: * * @param[in] width The width of the stroke. The default value is 0. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result stroke(float width) noexcept; @@ -983,7 +970,7 @@ public: * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. * @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept; @@ -1018,7 +1005,7 @@ public: * * @param[in] cap The cap style value. The default value is @c StrokeCap::Square. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result stroke(StrokeCap cap) noexcept; @@ -1029,7 +1016,7 @@ public: * * @param[in] join The join style value. The default value is @c StrokeJoin::Bevel. * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result stroke(StrokeJoin join) noexcept; @@ -1039,7 +1026,7 @@ public: * * @param[in] miterlimit The miterlimit imposes a limit on the extent of the stroke join, when the @c StrokeJoin::Miter join style is set. The default value is 4. * - * @return Result::Success when succeed, Result::NonSupport unsupported value, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::NonSupport unsupported value, Result::FailedAllocation otherwise. * * @since 0.11 */ @@ -1055,7 +1042,7 @@ public: * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. * @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. * * @note Either a solid color or a gradient fill is applied, depending on what was set as last. * @note ClipPath won't use the fill values. (see: enum class CompositeMethod::ClipPath) @@ -1069,7 +1056,7 @@ public: * * @param[in] f The unique pointer to the gradient fill. * - * @return Result::Success when succeed, Result::MemoryCorruption otherwise. + * @retval Result::Success when succeed, Result::MemoryCorruption otherwise. * * @note Either a solid color or a gradient fill is applied, depending on what was set as last. */ @@ -1080,7 +1067,7 @@ public: * * @param[in] r The fill rule value. The default value is @c FillRule::Winding. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. */ Result fill(FillRule r) noexcept; @@ -1090,7 +1077,7 @@ public: * * @param[in] strokeFirst If @c true the stroke is rendered before the fill, otherwise the stroke is rendered as the second one (the default option). * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * @retval Result::Success when succeed, Result::FailedAllocation otherwise. * * @since 0.10 */ @@ -1156,7 +1143,7 @@ public: * @param[out] b The blue color channel value in the range [0 ~ 255]. * @param[out] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. * - * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. */ Result strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a = nullptr) const noexcept; @@ -1295,7 +1282,7 @@ public: * @param[in] w A new width of the image in pixels. * @param[in] h A new height of the image in pixels. * - * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. */ Result size(float w, float h) noexcept; @@ -1305,13 +1292,20 @@ public: * @param[out] w The width of the image in pixels. * @param[out] h The height of the image in pixels. * - * @return Result::Success when succeed. + * @retval Result::Success when succeed. */ Result size(float* w, float* h) const noexcept; /** * @brief Loads a raw data from a memory block with a given size. * + * @param[in] paint A Tvg_Paint pointer to the picture object. + * @param[in] data A pointer to a memory location where the content of the picture raw data is stored. + * @param[in] w The width of the image @p data in pixels. + * @param[in] h The height of the image @p data in pixels. + * @param[in] premultiplied If @c true, the given image data is alpha-premultiplied. + * @param[in] copy If @c true the data are copied into the engine local buffer, otherwise they are not. + * * @retval Result::Success When succeed, Result::InsufficientCondition otherwise. * @retval Result::FailedAllocation An internal error possibly with memory allocation. * @@ -1339,7 +1333,7 @@ public: * @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect. * @warning Please do not use it, this API is not official one. It could be modified in the next version. * - * @BETA_API + * @note Experimental API */ Result mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept; @@ -1348,12 +1342,12 @@ public: * * @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh. * - * @return uint32_t The number of polygons in the array. + * @return The number of polygons in the array. * * @note Modifying the triangles returned by this method will modify them directly within the mesh. * @warning Please do not use it, this API is not official one. It could be modified in the next version. * - * @BETA_API + * @note Experimental API */ uint32_t mesh(const Polygon** triangles) const noexcept; @@ -1402,7 +1396,7 @@ public: * * @param[in] paint A Paint object to be drawn. * - * @return Result::Success when succeed, Result::MemoryCorruption otherwise. + * @retval Result::Success when succeed, Result::MemoryCorruption otherwise. * * @note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering. * @see Scene::paints() @@ -1432,7 +1426,7 @@ public: * @see Scene::push() * @see Scene::clear() * - * @BETA_API + * @note Experimental API */ std::list<Paint*>& paints() noexcept; @@ -1442,7 +1436,7 @@ public: * * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. * - * @return Result::Success when succeed + * @retval Result::Success when succeed * * @warning If you don't free the paints they become dangled. They are supposed to be reused, otherwise you are responsible for their lives. Thus please use the @p free argument only when you know how it works, otherwise it's not recommended. * @@ -1471,6 +1465,138 @@ public: /** + * @class Text + * + * @brief A class to represent text objects in a graphical context, allowing for rendering and manipulation of unicode text. + * + * @note Experimental API + */ +class TVG_API Text final : public Paint +{ +public: + ~Text(); + + /** + * @brief Sets the font properties for the text. + * + * This function allows you to define the font characteristics used for text rendering. + * It sets the font name, size and optionally the style. + * + * @param[in] name The name of the font. This should correspond to a font available in the canvas. + * @param[in] size The size of the font in points. This determines how large the text will appear. + * @param[in] style The style of the font. It can be used to set the font to 'italic'. + * If not specified, the default style is used. Only 'italic' style is supported currently. + * + * @retval Result::Success when the font properties are set successfully. + * @retval Result::InsufficientCondition when the specified @p name cannot be found. + * + * @note Experimental API + */ + Result font(const char* name, float size, const char* style = nullptr) noexcept; + + /** + * @brief Assigns the given unicode text to be rendered. + * + * This function sets the unicode string that will be displayed by the rendering system. + * The text is set according to the specified UTF encoding method, which defaults to UTF-8. + * + * @param[in] text The multi-byte text encoded with utf8 string to be rendered. + * + * @retval Result::Success when succeed. + * + * @note Experimental API + */ + Result text(const char* text) noexcept; + + /** + * @brief Sets the text color. + * + * @param[in] r The red color channel value in the range [0 ~ 255]. The default value is 0. + * @param[in] g The green color channel value in the range [0 ~ 255]. The default value is 0. + * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. + * + * @retval Result::Success when succeed. + * @retval Result::InsufficientCondition when the font has not been set up prior to this operation. + * + * @see Text::font() + * + * @note Experimental API + */ + Result fill(uint8_t r, uint8_t g, uint8_t b) noexcept; + + /** + * @brief Sets the gradient fill for all of the figures from the text. + * + * The parts of the text defined as inner are filled. + * + * @param[in] f The unique pointer to the gradient fill. + * + * @retval Result::Success when succeed, Result::MemoryCorruption otherwise. + * @retval Result::InsufficientCondition when the font has not been set up prior to this operation. + * + * @note Either a solid color or a gradient fill is applied, depending on what was set as last. + * @note Experimental API + * + * @see Text::font() + */ + Result fill(std::unique_ptr<Fill> f) noexcept; + + /** + * @brief Loads a scalable font data(ttf) from a file. + * + * @param[in] path The path to the font file. + * + * @retval Result::Success When succeed. + * @retval Result::InvalidArguments In case the @p path is invalid. + * @retval Result::NonSupport When trying to load a file with an unknown extension. + * @retval Result::Unknown If an error occurs at a later stage. + * + * @note Experimental API + * + * @see Text::unload(const std::string& path) + */ + static Result load(const std::string& path) noexcept; + + /** + * @brief Unloads the specified scalable font data (TTF) that was previously loaded. + * + * This function is used to release resources associated with a font file that has been loaded into memory. + * + * @param[in] path The file path of the loaded font. + * + * @retval Result::Success Successfully unloads the font data. + * @retval Result::InsufficientCondition Fails if the loader is not initialized. + * + * @note If the font data is currently in use, it will not be immediately unloaded. + * @note Experimental API + * + * @see Text::load(const std::string& path) + */ + static Result unload(const std::string& path) noexcept; + + /** + * @brief Creates a new Text object. + * + * @return A new Text object. + * + * @note Experimental API + */ + static std::unique_ptr<Text> gen() noexcept; + + /** + * @brief Return the unique id value of this class. + * + * This method can be referred for identifying the Text class type. + * + * @return The type id of the Text class. + */ + static uint32_t identifier() noexcept; + + _TVG_DECLARE_PRIVATE(Text); +}; + + +/** * @class SwCanvas * * @brief A class for the rendering graphical elements with a software raster engine. @@ -1487,8 +1613,8 @@ public: { ABGR8888 = 0, ///< The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied. (a << 24 | b << 16 | g << 8 | r) ARGB8888, ///< The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied. (a << 24 | r << 16 | g << 8 | b) - ABGR8888S, ///< @BETA_API The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. - ARGB8888S, ///< @BETA_API The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. + ABGR8888S, ///< The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. @since 0.12 + ARGB8888S, ///< The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. @since 0.12 }; /** @@ -1564,7 +1690,7 @@ public: * * @warning Please do not use it. This class is not fully supported yet. * - * @BETA_API + * @note Experimental API */ class TVG_API GlCanvas final : public Canvas { @@ -1576,7 +1702,7 @@ public: * * @warning Please do not use it, this API is not official one. It could be modified in the next version. * - * @BETA_API + * @note Experimental API */ Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept; @@ -1585,7 +1711,7 @@ public: * * @return A new GlCanvas object. * - * @BETA_API + * @note Experimental API */ static std::unique_ptr<GlCanvas> gen() noexcept; @@ -1594,6 +1720,42 @@ public: /** + * @class WgCanvas + * + * @brief A class for the rendering graphic elements with a WebGPU raster engine. + * + * @warning Please do not use it. This class is not fully supported yet. + * + * @note Experimental API + */ +class TVG_API WgCanvas final : public Canvas +{ +public: + ~WgCanvas(); + + /** + * @brief Sets the target window for the rasterization. + * + * @warning Please do not use it, this API is not official one. It could be modified in the next version. + * + * @note Experimental API + */ + Result target(void* window, uint32_t w, uint32_t h) noexcept; + + /** + * @brief Creates a new WgCanvas object. + * + * @return A new WgCanvas object. + * + * @note Experimental API + */ + static std::unique_ptr<WgCanvas> gen() noexcept; + + _TVG_DECLARE_PRIVATE(WgCanvas); +}; + + +/** * @class Initializer * * @brief A class that enables initialization and termination of the TVG engines. @@ -1650,7 +1812,7 @@ public: * * This class supports the display and control of animation frames. * - * @BETA_API + * @note Experimental API */ class TVG_API Animation @@ -1664,14 +1826,14 @@ public: * @param[in] no The index of the animation frame to be displayed. The index should be less than the totalFrame(). * * @retval Result::Success Successfully set the frame. - * @retval Result::InsufficientCondition No animatable data loaded from the Picture. - * @retval Result::NonSupport The Picture data does not support animations. + * @retval Result::InsufficientCondition if the given @p no is the same as the current frame value. + * @retval Result::NonSupport The current Picture data does not support animations. * * @see totalFrame() * - * @BETA_API + * @note Experimental API */ - Result frame(uint32_t no) noexcept; + Result frame(float no) noexcept; /** * @brief Retrieves a picture instance associated with this animation instance. @@ -1684,7 +1846,7 @@ public: * * @warning The picture instance is owned by Animation. It should not be deleted manually. * - * @BETA_API + * @note Experimental API */ Picture* picture() const noexcept; @@ -1695,12 +1857,12 @@ public: * * @note If the Picture is not properly configured, this function will return 0. * - * @see Animation::frame(uint32_t no) + * @see Animation::frame(float no) * @see Animation::totalFrame() * - * @BETA_API + * @note Experimental API */ - uint32_t curFrame() const noexcept; + float curFrame() const noexcept; /** * @brief Retrieves the total number of frames in the animation. @@ -1710,9 +1872,9 @@ public: * @note Frame numbering starts from 0. * @note If the Picture is not properly configured, this function will return 0. * - * @BETA_API + * @note Experimental API */ - uint32_t totalFrame() const noexcept; + float totalFrame() const noexcept; /** * @brief Retrieves the duration of the animation in seconds. @@ -1721,7 +1883,7 @@ public: * * @note If the Picture is not properly configured, this function will return 0. * - * @BETA_API + * @% Experimental API */ float duration() const noexcept; @@ -1730,7 +1892,7 @@ public: * * @return A new Animation object. * - * @BETA_API + * @note Experimental API */ static std::unique_ptr<Animation> gen() noexcept; @@ -1761,6 +1923,15 @@ public: ~Saver(); /** + * @brief Sets the base background content for the saved image. + * + * @param[in] paint The paint to be drawn as the background image for the saving paint. + * + * @note Experimental API + */ + Result background(std::unique_ptr<Paint> paint) noexcept; + + /** * @brief Exports the given @p paint data to the given @p path * * If the saver module supports any compression mechanism, it will optimize the data size. @@ -1785,6 +1956,31 @@ public: Result save(std::unique_ptr<Paint> paint, const std::string& path, bool compress = true) noexcept; /** + * @brief Export the provided animation data to the specified file path. + * + * This function exports the given animation data to the provided file path. You can also specify the desired frame rate in frames per second (FPS) by providing the fps parameter. + * + * @param[in] animation The animation to be saved, including all associated properties. + * @param[in] path The path to the file where the animation will be saved. + * @param[in] quality The encoded quality level. @c 0 is the minimum, @c 100 is the maximum value(recommended). + * @param[in] fps The desired frames per second (FPS). For example, to encode data at 60 FPS, pass 60. Pass 0 to keep the original frame data. + * + * @retval Result::Success if the export succeeds. + * @retval Result::InsufficientCondition if there are ongoing resource-saving operations. + * @retval Result::NonSupport if an attempt is made to save the file with an unknown extension or in an unsupported format. + * @retval Result::MemoryCorruption in case of an internal error. + * @retval Result::Unknown if attempting to save an empty paint. + * + * @note A higher frames per second (FPS) would result in a larger file size. It is recommended to use the default value. + * @note Saving can be asynchronous if the assigned thread number is greater than zero. To guarantee the saving is done, call sync() afterwards. + * + * @see Saver::sync() + * + * @note Experimental API + */ + Result save(std::unique_ptr<Animation> animation, const std::string& path, uint32_t quality = 100, uint32_t fps = 0) noexcept; + + /** * @brief Guarantees that the saving task is finished. * * The behavior of the Saver works on a sync/async basis, depending on the threading setting of the Initializer. @@ -1857,7 +2053,7 @@ public: * @brief The cast() function is a utility function used to cast a 'Paint' to type 'T'. * @since 0.11 */ -template<typename T> +template<typename T = tvg::Paint> std::unique_ptr<T> cast(Paint* paint) { return std::unique_ptr<T>(static_cast<T*>(paint)); @@ -1868,7 +2064,7 @@ std::unique_ptr<T> cast(Paint* paint) * @brief The cast() function is a utility function used to cast a 'Fill' to type 'T'. * @since 0.11 */ -template<typename T> +template<typename T = tvg::Fill> std::unique_ptr<T> cast(Fill* fill) { return std::unique_ptr<T>(static_cast<T*>(fill)); diff --git a/thirdparty/thorvg/src/common/tvgArray.h b/thirdparty/thorvg/src/common/tvgArray.h index 08eb25329c..acb3a41b97 100644 --- a/thirdparty/thorvg/src/common/tvgArray.h +++ b/thirdparty/thorvg/src/common/tvgArray.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,7 @@ #include <memory.h> #include <cstdint> +#include <cstdlib> namespace tvg { @@ -38,6 +39,11 @@ struct Array Array(){} + Array(int32_t size) + { + reserve(size); + } + Array(const Array& rhs) { reset(); diff --git a/thirdparty/thorvg/src/common/tvgBezier.cpp b/thirdparty/thorvg/src/common/tvgBezier.cpp index f9daf07b84..5fb501721e 100644 --- a/thirdparty/thorvg/src/common/tvgBezier.cpp +++ b/thirdparty/thorvg/src/common/tvgBezier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/common/tvgBezier.h b/thirdparty/thorvg/src/common/tvgBezier.h index 539a63bdd3..cb2766c505 100644 --- a/thirdparty/thorvg/src/common/tvgBezier.h +++ b/thirdparty/thorvg/src/common/tvgBezier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/common/tvgCompressor.cpp b/thirdparty/thorvg/src/common/tvgCompressor.cpp index e38940f3d0..778fc4d0a2 100644 --- a/thirdparty/thorvg/src/common/tvgCompressor.cpp +++ b/thirdparty/thorvg/src/common/tvgCompressor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/common/tvgCompressor.h b/thirdparty/thorvg/src/common/tvgCompressor.h index 05d23f4293..0756127ec6 100644 --- a/thirdparty/thorvg/src/common/tvgCompressor.h +++ b/thirdparty/thorvg/src/common/tvgCompressor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/common/tvgInlist.h b/thirdparty/thorvg/src/common/tvgInlist.h new file mode 100644 index 0000000000..ff28cfd48e --- /dev/null +++ b/thirdparty/thorvg/src/common/tvgInlist.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved. + + * 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 _TVG_INLIST_H_ +#define _TVG_INLIST_H_ + +namespace tvg { + +//NOTE: declare this in your list item +#define INLIST_ITEM(T) \ + T* prev; \ + T* next + +template<typename T> +struct Inlist +{ + T* head = nullptr; + T* tail = nullptr; + + void free() + { + while (head) { + auto t = head; + head = t->next; + delete(t); + } + head = tail = nullptr; + } + + void back(T* element) + { + if (tail) { + tail->next = element; + element->prev = tail; + element->next = nullptr; + tail = element; + } else { + head = tail = element; + element->prev = nullptr; + element->next = nullptr; + } + } + + void front(T* element) + { + if (head) { + head->prev = element; + element->prev = nullptr; + element->next = head; + head = element; + } else { + head = tail = element; + element->prev = nullptr; + element->next = nullptr; + } + } + + T* back() + { + if (!tail) return nullptr; + auto t = tail; + tail = t->prev; + if (!tail) head = nullptr; + return t; + } + + T* front() + { + if (!head) return nullptr; + auto t = head; + head = t->next; + if (!head) tail = nullptr; + return t; + } + + void remove(T* element) + { + if (element->prev) element->prev->next = element->next; + if (element->next) element->next->prev = element->prev; + if (element == head) head = element->next; + if (element == tail) tail = element->prev; + } + + bool empty() + { + return head ? false : true; + } +}; + +} + +#endif // _TVG_INLIST_H_ diff --git a/thirdparty/thorvg/src/common/tvgList.h b/thirdparty/thorvg/src/common/tvgList.h deleted file mode 100644 index 01e87a840f..0000000000 --- a/thirdparty/thorvg/src/common/tvgList.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * 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 _TVG_LIST_H_ -#define _TVG_LIST_H_ - -namespace tvg { - -template<typename T> -struct LinkedList -{ - T *head = nullptr; - T *tail = nullptr; - - LinkedList() = default; - LinkedList(T *head, T *tail) : head(head), tail(tail) - { - } - - template<T *T::*Prev, T *T::*Next> - static void insert(T *t, T *prev, T *next, T **head, T **tail) - { - t->*Prev = prev; - t->*Next = next; - - if (prev) { - prev->*Next = t; - } else if (head) { - *head = t; - } - - if (next) { - next->*Prev = t; - } else if (tail) { - *tail = t; - } - } - - template<T *T::*Prev, T *T::*Next> - static void remove(T *t, T **head, T **tail) - { - if (t->*Prev) { - t->*Prev->*Next = t->*Next; - } else if (head) { - *head = t->*Next; - } - - if (t->*Next) { - t->*Next->*Prev = t->*Prev; - } else if (tail) { - *tail = t->*Prev; - } - - t->*Prev = t->*Next = nullptr; - } - - template <T* T::*Next> - static bool contains(T *t, T **head, T **tail) { - for (T *it = *head; it; it = it->*Next) { - if (it == t) { - return true; - } - } - - return false; - } -}; - -} - -#endif // _TVG_LIST_H_ diff --git a/thirdparty/thorvg/src/common/tvgMath.cpp b/thirdparty/thorvg/src/common/tvgMath.cpp index a9463c8077..42bc2cf4aa 100644 --- a/thirdparty/thorvg/src/common/tvgMath.cpp +++ b/thirdparty/thorvg/src/common/tvgMath.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/common/tvgMath.h b/thirdparty/thorvg/src/common/tvgMath.h index 004fff1e7b..50c3458efc 100644 --- a/thirdparty/thorvg/src/common/tvgMath.h +++ b/thirdparty/thorvg/src/common/tvgMath.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -174,6 +174,18 @@ static inline Point operator*(const Point& lhs, float rhs) } +static inline Point operator*(const float& lhs, const Point& rhs) +{ + return {lhs * rhs.x, lhs * rhs.y}; +} + + +static inline Point operator/(const Point& lhs, const float rhs) +{ + return {lhs.x / rhs, lhs.y / rhs}; +} + + template <typename T> static inline T mathLerp(const T &start, const T &end, float t) { diff --git a/thirdparty/thorvg/src/common/tvgStr.cpp b/thirdparty/thorvg/src/common/tvgStr.cpp index eeed4fc404..311b986511 100644 --- a/thirdparty/thorvg/src/common/tvgStr.cpp +++ b/thirdparty/thorvg/src/common/tvgStr.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/common/tvgStr.h b/thirdparty/thorvg/src/common/tvgStr.h index 448cc69336..9e5f9ba9b5 100644 --- a/thirdparty/thorvg/src/common/tvgStr.h +++ b/thirdparty/thorvg/src/common/tvgStr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp index b0a9fdd579..10277f846d 100644 --- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp +++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,19 +20,25 @@ * SOFTWARE. */ -#include "tvgLoader.h" #include "tvgPngLoader.h" /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ +void PngLoader::clear() +{ + png_image_free(image); + free(image); + image = nullptr; +} + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -PngLoader::PngLoader() +PngLoader::PngLoader() : ImageLoader(FileType::Png) { image = static_cast<png_imagep>(calloc(1, sizeof(png_image))); image->version = PNG_IMAGE_VERSION; @@ -41,13 +47,11 @@ PngLoader::PngLoader() PngLoader::~PngLoader() { - if (content) { - free((void*)content); - content = nullptr; - } - free(image); + clear(); + free((void*)surface.buf32); } + bool PngLoader::open(const string& path) { image->opaque = NULL; @@ -56,11 +60,11 @@ bool PngLoader::open(const string& path) w = (float)image->width; h = (float)image->height; - cs = ColorSpace::ARGB8888; return true; } + bool PngLoader::open(const char* data, uint32_t size, bool copy) { image->opaque = NULL; @@ -69,7 +73,6 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy) w = (float)image->width; h = (float)image->height; - cs = ColorSpace::ARGB8888; return true; } @@ -77,6 +80,10 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy) bool PngLoader::read() { + if (!LoadModule::read()) return true; + + if (w == 0 || h == 0) return false; + png_bytep buffer; image->format = PNG_FORMAT_BGRA; buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image)))); @@ -89,32 +96,17 @@ bool PngLoader::read() free(buffer); return false; } - content = reinterpret_cast<uint32_t*>(buffer); - return true; -} + //setup the surface + surface.buf32 = reinterpret_cast<uint32_t*>(buffer); + surface.stride = (uint32_t)w; + surface.w = (uint32_t)w; + surface.h = (uint32_t)h; + surface.channelSize = sizeof(uint32_t); + surface.cs = ColorSpace::ARGB8888; + surface.premultiplied = false; -bool PngLoader::close() -{ - png_image_free(image); - return true; -} + clear(); -unique_ptr<Surface> PngLoader::bitmap() -{ - if (!content) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf32 = content; - surface->stride = w; - surface->w = w; - surface->h = h; - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->owner = true; - surface->premultiplied = false; - - return unique_ptr<Surface>(surface); + return true; } - diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h index 5354e1bdd6..c45544eb07 100644 --- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h +++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,24 +24,22 @@ #define _TVG_PNG_LOADER_H_ #include <png.h> +#include "tvgLoader.h" -class PngLoader : public LoadModule +class PngLoader : public ImageLoader { public: PngLoader(); ~PngLoader(); - using LoadModule::open; bool open(const string& path) override; bool open(const char* data, uint32_t size, bool copy) override; bool read() override; - bool close() override; - - unique_ptr<Surface> bitmap() override; private: + void clear(); + png_imagep image = nullptr; - uint32_t* content = nullptr; }; #endif //_TVG_PNG_LOADER_H_ diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp index 6edda86cc1..86a46245d9 100644 --- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,7 +21,6 @@ */ #include <memory.h> -#include "tvgLoader.h" #include "tvgJpgLoader.h" /************************************************************************/ @@ -38,30 +37,45 @@ void JpgLoader::clear() } +void JpgLoader::run(unsigned tid) +{ + surface.buf8 = jpgdDecompress(decoder); + surface.stride = static_cast<uint32_t>(w); + surface.w = static_cast<uint32_t>(w); + surface.h = static_cast<uint32_t>(h); + surface.cs = ColorSpace::ARGB8888; + surface.channelSize = sizeof(uint32_t); + surface.premultiplied = true; + + clear(); +} + + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ +JpgLoader::JpgLoader() : ImageLoader(FileType::Jpg) +{ + +} + JpgLoader::~JpgLoader() { - jpgdDelete(decoder); - if (freeData) free(data); - free(image); + clear(); + free(surface.buf8); } bool JpgLoader::open(const string& path) { - clear(); - int width, height; decoder = jpgdHeader(path.c_str(), &width, &height); if (!decoder) return false; w = static_cast<float>(width); h = static_cast<float>(height); - cs = ColorSpace::ARGB8888; return true; } @@ -69,8 +83,6 @@ bool JpgLoader::open(const string& path) bool JpgLoader::open(const char* data, uint32_t size, bool copy) { - clear(); - if (copy) { this->data = (char *) malloc(size); if (!this->data) return false; @@ -87,7 +99,6 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy) w = static_cast<float>(width); h = static_cast<float>(height); - cs = ColorSpace::ARGB8888; return true; } @@ -96,7 +107,9 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy) bool JpgLoader::read() { - if (!decoder || w <= 0 || h <= 0) return false; + if (!LoadModule::read()) return true; + + if (!decoder || w == 0 || h == 0) return false; TaskScheduler::request(this); @@ -106,38 +119,14 @@ bool JpgLoader::read() bool JpgLoader::close() { + if (!LoadModule::close()) return false; this->done(); - clear(); return true; } -unique_ptr<Surface> JpgLoader::bitmap() +Surface* JpgLoader::bitmap() { this->done(); - - if (!image) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf8 = image; - surface->stride = static_cast<uint32_t>(w); - surface->w = static_cast<uint32_t>(w); - surface->h = static_cast<uint32_t>(h); - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->premultiplied = true; - surface->owner = true; - - return unique_ptr<Surface>(surface); -} - - -void JpgLoader::run(unsigned tid) -{ - if (image) { - free(image); - image = nullptr; - } - image = jpgdDecompress(decoder); + return ImageLoader::bitmap(); } diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h index 6d2febe94f..05cbb54c85 100644 --- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h +++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,30 +23,30 @@ #ifndef _TVG_JPG_LOADER_H_ #define _TVG_JPG_LOADER_H_ +#include "tvgLoader.h" #include "tvgTaskScheduler.h" #include "tvgJpgd.h" -class JpgLoader : public LoadModule, public Task +class JpgLoader : public ImageLoader, public Task { private: jpeg_decoder* decoder = nullptr; char* data = nullptr; - unsigned char *image = nullptr; bool freeData = false; void clear(); + void run(unsigned tid) override; public: + JpgLoader(); ~JpgLoader(); - using LoadModule::open; bool open(const string& path) override; bool open(const char* data, uint32_t size, bool copy) override; bool read() override; bool close() override; - unique_ptr<Surface> bitmap() override; - void run(unsigned tid) override; + Surface* bitmap() override; }; #endif //_TVG_JPG_LOADER_H_ diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp index 61a5dc1c0f..6f2bd916d5 100644 --- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp +++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -1456,7 +1456,11 @@ void jpeg_decoder::locate_sof_marker() int c = process_markers(); switch (c) { - case M_SOF2: m_progressive_flag = true; + case M_SOF2: { + m_progressive_flag = true; + read_sof_marker(); + break; + } case M_SOF0: /* baseline DCT */ case M_SOF1: { /* extended sequential DCT */ read_sof_marker(); diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h index 030fdc2946..e1fe35f488 100644 --- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h +++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp b/thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp index fc4cce4061..fb7527f045 100644 --- a/thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp +++ b/thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/png/tvgLodePng.h b/thirdparty/thorvg/src/loaders/png/tvgLodePng.h index 7254a55477..cd3efacf98 100644 --- a/thirdparty/thorvg/src/loaders/png/tvgLodePng.h +++ b/thirdparty/thorvg/src/loaders/png/tvgLodePng.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp index 32ff57c5c3..111180b657 100644 --- a/thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp +++ b/thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,14 +29,22 @@ /* Internal Class Implementation */ /************************************************************************/ -void PngLoader::clear() + +void PngLoader::run(unsigned tid) { - lodepng_state_cleanup(&state); + auto width = static_cast<unsigned>(w); + auto height = static_cast<unsigned>(h); - if (freeData) free(data); - data = nullptr; - size = 0; - freeData = false; + if (lodepng_decode(&surface.buf8, &width, &height, &state, data, size)) { + TVGERR("PNG", "Failed to decode image"); + } + + //setup the surface + surface.stride = width; + surface.w = width; + surface.h = height; + surface.channelSize = sizeof(uint32_t); + surface.premultiplied = false; } @@ -44,7 +52,7 @@ void PngLoader::clear() /* External Class Implementation */ /************************************************************************/ -PngLoader::PngLoader() +PngLoader::PngLoader() : ImageLoader(FileType::Png) { lodepng_state_init(&state); } @@ -53,14 +61,13 @@ PngLoader::PngLoader() PngLoader::~PngLoader() { if (freeData) free(data); - free(image); + free(surface.buf8); + lodepng_state_cleanup(&state); } bool PngLoader::open(const string& path) { - clear(); - auto pngFile = fopen(path.c_str(), "rb"); if (!pngFile) return false; @@ -76,26 +83,23 @@ bool PngLoader::open(const string& path) freeData = true; - if (fread(data, size, 1, pngFile) < 1) goto failure; + if (fread(data, size, 1, pngFile) < 1) goto finalize; lodepng_state_init(&state); unsigned int width, height; - if (lodepng_inspect(&width, &height, &state, data, size) > 0) goto failure; + if (lodepng_inspect(&width, &height, &state, data, size) > 0) goto finalize; w = static_cast<float>(width); h = static_cast<float>(height); - if (state.info_png.color.colortype == LCT_RGBA) cs = ColorSpace::ABGR8888; - else cs = ColorSpace::ARGB8888; + if (state.info_png.color.colortype == LCT_RGBA) surface.cs = ColorSpace::ABGR8888; + else surface.cs = ColorSpace::ARGB8888; ret = true; goto finalize; -failure: - clear(); - finalize: fclose(pngFile); return ret; @@ -104,10 +108,6 @@ finalize: bool PngLoader::open(const char* data, uint32_t size, bool copy) { - clear(); - - lodepng_state_init(&state); - unsigned int width, height; if (lodepng_inspect(&width, &height, &state, (unsigned char*)(data), size) > 0) return false; @@ -125,7 +125,7 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy) h = static_cast<float>(height); this->size = size; - cs = ColorSpace::ABGR8888; + surface.cs = ColorSpace::ABGR8888; return true; } @@ -133,53 +133,18 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy) bool PngLoader::read() { - if (!data || w <= 0 || h <= 0) return false; - - TaskScheduler::request(this); + if (!data || w == 0 || h == 0) return false; - return true; -} + if (!LoadModule::read()) return true; + TaskScheduler::request(this); -bool PngLoader::close() -{ - this->done(); - clear(); return true; } -unique_ptr<Surface> PngLoader::bitmap() +Surface* PngLoader::bitmap() { this->done(); - - if (!image) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf8 = image; - surface->stride = static_cast<uint32_t>(w); - surface->w = static_cast<uint32_t>(w); - surface->h = static_cast<uint32_t>(h); - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->premultiplied = false; - surface->owner = true; - - return unique_ptr<Surface>(surface); -} - - -void PngLoader::run(unsigned tid) -{ - if (image) { - free(image); - image = nullptr; - } - auto width = static_cast<unsigned>(w); - auto height = static_cast<unsigned>(h); - - if (lodepng_decode(&image, &width, &height, &state, data, size)) { - TVGERR("PNG", "Failed to decode image"); - } + return ImageLoader::bitmap(); } diff --git a/thirdparty/thorvg/src/loaders/png/tvgPngLoader.h b/thirdparty/thorvg/src/loaders/png/tvgPngLoader.h index 579d197ad6..06fbbf7349 100644 --- a/thirdparty/thorvg/src/loaders/png/tvgPngLoader.h +++ b/thirdparty/thorvg/src/loaders/png/tvgPngLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,29 +27,25 @@ #include "tvgTaskScheduler.h" -class PngLoader : public LoadModule, public Task +class PngLoader : public ImageLoader, public Task { private: LodePNGState state; unsigned char* data = nullptr; - unsigned char *image = nullptr; unsigned long size = 0; bool freeData = false; - void clear(); + void run(unsigned tid) override; public: PngLoader(); ~PngLoader(); - using LoadModule::open; bool open(const string& path) override; bool open(const char* data, uint32_t size, bool copy) override; bool read() override; - bool close() override; - unique_ptr<Surface> bitmap() override; - void run(unsigned tid) override; + Surface* bitmap() override; }; #endif //_TVG_PNG_LOADER_H_ diff --git a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp index 5f5e72b0dd..b797f98218 100644 --- a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp +++ b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,17 +34,21 @@ /* External Class Implementation */ /************************************************************************/ +RawLoader::RawLoader() : ImageLoader(FileType::Raw) +{ +} + + RawLoader::~RawLoader() { - if (copy && content) { - free((void*)content); - content = nullptr; - } + if (copy) free(surface.buf32); } bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { + if (!LoadModule::read()) return true; + if (!data || w == 0 || h == 0) return false; this->w = (float)w; @@ -52,13 +56,19 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) this->copy = copy; if (copy) { - content = (uint32_t*)malloc(sizeof(uint32_t) * w * h); - if (!content) return false; - memcpy((void*)content, data, sizeof(uint32_t) * w * h); + surface.buf32 = (uint32_t*)malloc(sizeof(uint32_t) * w * h); + if (!surface.buf32) return false; + memcpy((void*)surface.buf32, data, sizeof(uint32_t) * w * h); } - else content = const_cast<uint32_t*>(data); + else surface.buf32 = const_cast<uint32_t*>(data); - cs = ColorSpace::ARGB8888; + //setup the surface + surface.stride = w; + surface.w = w; + surface.h = h; + surface.cs = ColorSpace::ARGB8888; + surface.channelSize = sizeof(uint32_t); + surface.premultiplied = true; return true; } @@ -66,30 +76,7 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) bool RawLoader::read() { - return true; -} - + LoadModule::read(); -bool RawLoader::close() -{ return true; } - - -unique_ptr<Surface> RawLoader::bitmap() -{ - if (!content) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf32 = content; - surface->stride = static_cast<uint32_t>(w); - surface->w = static_cast<uint32_t>(w); - surface->h = static_cast<uint32_t>(h); - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->premultiplied = true; - surface->owner = true; - - return unique_ptr<Surface>(surface); -} diff --git a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h index 69f9bdc47a..970cdd9c83 100644 --- a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h +++ b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +23,17 @@ #ifndef _TVG_RAW_LOADER_H_ #define _TVG_RAW_LOADER_H_ -class RawLoader : public LoadModule +class RawLoader : public ImageLoader { public: - uint32_t* content = nullptr; bool copy = false; + RawLoader(); ~RawLoader(); using LoadModule::open; - bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) override; + bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy); bool read() override; - bool close() override; - - unique_ptr<Surface> bitmap() override; }; diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp index c3c477a263..2826dc9134 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2022 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h index 228c5996da..7d8dcfa94a 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2022 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index be99ec085c..74f9871a08 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -3528,6 +3528,10 @@ void SvgLoader::clear(bool all) loaderData.images.reset(); if (copy) free((char*)content); + + delete(root); + root = nullptr; + size = 0; content = nullptr; copy = false; @@ -3538,14 +3542,15 @@ void SvgLoader::clear(bool all) /* External Class Implementation */ /************************************************************************/ -SvgLoader::SvgLoader() +SvgLoader::SvgLoader() : ImageLoader(FileType::Svg) { } SvgLoader::~SvgLoader() { - close(); + this->done(); + clear(); } @@ -3554,7 +3559,7 @@ void SvgLoader::run(unsigned tid) //According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vw) <= FLT_EPSILON || fabsf(vh) <= FLT_EPSILON)) { TVGLOG("SVG", "The <viewBox> width and/or height set to 0 - rendering disabled."); - root = Scene::gen(); + root = Scene::gen().release(); return; } @@ -3728,7 +3733,7 @@ bool SvgLoader::read() if (!content || size == 0) return false; //the loading has been already completed in header() - if (root) return true; + if (root || !LoadModule::read()) return true; TaskScheduler::request(this); @@ -3738,16 +3743,17 @@ bool SvgLoader::read() bool SvgLoader::close() { + if (!LoadModule::close()) return false; this->done(); - clear(); - return true; } -unique_ptr<Paint> SvgLoader::paint() +Paint* SvgLoader::paint() { this->done(); - return std::move(root); + auto ret = root; + root = nullptr; + return ret; } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h index 4bac52e0b9..e0cba8b11e 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,7 @@ #include "tvgTaskScheduler.h" #include "tvgSvgLoaderCommon.h" -class SvgLoader : public LoadModule, public Task +class SvgLoader : public ImageLoader, public Task { public: string filePath; @@ -35,21 +35,20 @@ public: uint32_t size = 0; SvgLoaderData loaderData; - unique_ptr<Scene> root; + Scene* root = nullptr; bool copy = false; SvgLoader(); ~SvgLoader(); - using LoadModule::open; bool open(const string& path) override; bool open(const char* data, uint32_t size, bool copy) override; bool resize(Paint* paint, float w, float h) override; bool read() override; bool close() override; - unique_ptr<Paint> paint() override; + Paint* paint() override; private: SvgViewFlag viewFlag = SvgViewFlag::None; diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h index b4ee3e8e0d..d6febd6825 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp index 79a9c0771d..f618a3c827 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -53,6 +53,7 @@ #include <cstring> #include <math.h> #include <ctype.h> +#include "tvgShape.h" #include "tvgSvgLoaderCommon.h" #include "tvgSvgPath.h" #include "tvgStr.h" @@ -534,7 +535,7 @@ static char* _nextCommand(char* path, char* cmd, float* arr, int* count) /************************************************************************/ -bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point>& pts) +bool svgPathToShape(const char* svgPath, Shape* shape) { float numberArray[7]; int numberCount = 0; @@ -545,11 +546,16 @@ bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point bool isQuadratic = false; char* path = (char*)svgPath; + auto& pts = P(shape)->rs.path.pts; + auto& cmds = P(shape)->rs.path.cmds; + auto lastCmds = cmds.count; + while ((path[0] != '\0')) { path = _nextCommand(path, &cmd, numberArray, &numberCount); if (!path) break; if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic)) break; } + if (cmds.count > lastCmds && cmds[lastCmds] != PathCommand::MoveTo) return false; return true; } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h index 4199088dc1..b8641dd165 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,6 @@ #include <tvgCommon.h> -bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point>& pts); +bool svgPathToShape(const char* svgPath, Shape* shape); #endif //_TVG_SVG_PATH_H_ diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp index 1791df57f0..674c30f5bd 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -396,10 +396,9 @@ static bool _recognizeShape(SvgNode* node, Shape* shape) switch (node->type) { case SvgNodeType::Path: { if (node->node.path.path) { - Array<PathCommand> cmds; - Array<Point> pts; - if (svgPathToTvgPath(node->node.path.path, cmds, pts)) { - shape->appendPath(cmds.data, cmds.count, pts.data, pts.count); + if (!svgPathToShape(node->node.path.path, shape)) { + TVGERR("SVG", "Invalid path information."); + return false; } } break; @@ -845,7 +844,7 @@ static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, floa /* External Class Implementation */ /************************************************************************/ -unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag) +Scene* svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag) { //TODO: aspect ratio is valid only if viewBox was set @@ -863,8 +862,7 @@ unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, fl } auto viewBoxClip = Shape::gen(); - viewBoxClip->appendRect(0, 0, w, h, 0, 0); - viewBoxClip->fill(0, 0, 0); + viewBoxClip->appendRect(0, 0, w, h); auto compositeLayer = Scene::gen(); compositeLayer->composite(std::move(viewBoxClip), CompositeMethod::ClipPath); @@ -880,5 +878,5 @@ unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, fl loaderData.doc->node.doc.w = w; loaderData.doc->node.doc.h = h; - return root; + return root.release(); } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h index f6a60f850d..0663a37f05 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,6 @@ #include "tvgCommon.h" -unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag); +Scene* svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag); #endif //_TVG_SVG_SCENE_BUILDER_H_ diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp index 7940188ade..32affd04c6 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h index ee0e3f8861..220a4b3e55 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp index dbc3b17b70..6530d52259 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -171,10 +171,11 @@ static const char* _simpleXmlFindStartTag(const char* itr, const char* itrEnd) static const char* _simpleXmlFindEndTag(const char* itr, const char* itrEnd) { - bool insideQuote = false; + bool insideQuote[2] = {false, false}; // 0: ", 1: ' for (; itr < itrEnd; itr++) { - if (*itr == '"') insideQuote = !insideQuote; - if (!insideQuote) { + if (*itr == '"' && !insideQuote[1]) insideQuote[0] = !insideQuote[0]; + if (*itr == '\'' && !insideQuote[0]) insideQuote[1] = !insideQuote[1]; + if (!insideQuote[0] && !insideQuote[1]) { if ((*itr == '>') || (*itr == '<')) return itr; } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h index 7333bb09fb..30ca23b565 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h index c6dcf79a48..3d73075a4a 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,11 +43,16 @@ static double timeStamp() #define SW_ANGLE_PI (180L << 16) #define SW_ANGLE_2PI (SW_ANGLE_PI << 1) #define SW_ANGLE_PI2 (SW_ANGLE_PI >> 1) -#define SW_ANGLE_PI4 (SW_ANGLE_PI >> 2) using SwCoord = signed long; using SwFixed = signed long long; + +static inline float TO_FLOAT(SwCoord val) +{ + return static_cast<float>(val) / 64.0f; +} + struct SwPoint { SwCoord x, y; @@ -92,6 +97,10 @@ struct SwPoint else return false; } + Point toPoint() const + { + return {TO_FLOAT(x), TO_FLOAT(y)}; + } }; struct SwSize @@ -252,13 +261,26 @@ struct SwSurface : Surface SwAlpha alphas[4]; //Alpha:2, InvAlpha:3, Luma:4, InvLuma:5 SwBlender blender = nullptr; //blender (optional) SwCompositor* compositor = nullptr; //compositor (optional) - BlendMethod blendMethod; //blending method (uint8_t) + BlendMethod blendMethod; //blending method (uint8_t) SwAlpha alpha(CompositeMethod method) { auto idx = (int)(method) - 2; //0: None, 1: ClipPath return alphas[idx > 3 ? 0 : idx]; //CompositeMethod has only four Matting methods. } + + SwSurface() + { + } + + SwSurface(const SwSurface* rhs) : Surface(rhs) + { + join = rhs->join; + memcpy(alphas, rhs->alphas, sizeof(alphas)); + blender = rhs->blender; + compositor = rhs->compositor; + blendMethod = rhs->blendMethod; + } }; struct SwCompositor : Compositor diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwFill.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwFill.cpp index cede9e6eb7..8956cd9f24 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwFill.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwFill.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -167,7 +167,6 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr fill->linear.dy = dx * invTransform.e12 + fill->linear.dy * invTransform.e22; fill->linear.len = fill->linear.dx * fill->linear.dx + fill->linear.dy * fill->linear.dy; - if (fill->linear.len < FLT_EPSILON) return true; } return true; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwImage.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwImage.cpp index b1624037bc..c162945501 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwImage.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwImage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp index dbcfa754f3..42e405195e 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,7 +20,7 @@ * SOFTWARE. */ -#include <math.h> +#include "tvgMath.h" #include "tvgSwCommon.h" @@ -28,173 +28,9 @@ /* Internal Class Implementation */ /************************************************************************/ -//clz: count leading zero’s -#if defined(_MSC_VER) && !defined(__clang__) - #include <intrin.h> - static uint32_t __inline _clz(uint32_t value) - { - unsigned long leadingZero = 0; - if (_BitScanReverse(&leadingZero, value)) return 31 - leadingZero; - else return 32; - } -#else - #define _clz(x) __builtin_clz((x)) -#endif - - -constexpr SwFixed CORDIC_FACTOR = 0xDBD95B16UL; //the Cordic shrink factor 0.858785336480436 * 2^32 - -//this table was generated for SW_FT_PI = 180L << 16, i.e. degrees -constexpr static auto ATAN_MAX = 23; -constexpr static SwFixed ATAN_TBL[] = { - 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, - 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, - 57L, 29L, 14L, 7L, 4L, 2L, 1L}; - -static inline SwCoord SATURATE(const SwCoord x) -{ - return (x >> (sizeof(SwCoord) * 8 - 1)); -} - - -static inline SwFixed PAD_ROUND(const SwFixed x, int32_t n) -{ - return (((x) + ((n)/2)) & ~((n)-1)); -} - - -static SwCoord _downscale(SwFixed x) +static float TO_RADIAN(SwFixed angle) { - //multiply a give value by the CORDIC shrink factor - auto s = abs(x); - int64_t t = (s * static_cast<int64_t>(CORDIC_FACTOR)) + 0x100000000UL; - s = static_cast<SwFixed>(t >> 32); - if (x < 0) s = -s; - return s; -} - - -static int32_t _normalize(SwPoint& pt) -{ - /* the highest bit in overflow-safe vector components - MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */ - constexpr auto SAFE_MSB = 29; - - auto v = pt; - - //High order bit(MSB) - int32_t shift = 31 - _clz(abs(v.x) | abs(v.y)); - - if (shift <= SAFE_MSB) { - shift = SAFE_MSB - shift; - pt.x = static_cast<SwCoord>((unsigned long)v.x << shift); - pt.y = static_cast<SwCoord>((unsigned long)v.y << shift); - } else { - shift -= SAFE_MSB; - pt.x = v.x >> shift; - pt.y = v.y >> shift; - shift = -shift; - } - return shift; -} - - -static void _polarize(SwPoint& pt) -{ - auto v = pt; - SwFixed theta; - - //Get the vector into [-PI/4, PI/4] sector - if (v.y > v.x) { - if (v.y > -v.x) { - auto tmp = v.y; - v.y = -v.x; - v.x = tmp; - theta = SW_ANGLE_PI2; - } else { - theta = v.y > 0 ? SW_ANGLE_PI : -SW_ANGLE_PI; - v.x = -v.x; - v.y = -v.y; - } - } else { - if (v.y < -v.x) { - theta = -SW_ANGLE_PI2; - auto tmp = -v.y; - v.y = v.x; - v.x = tmp; - } else { - theta = 0; - } - } - - auto atan = ATAN_TBL; - uint32_t i; - SwFixed j; - - //Pseudorotations. with right shifts - for (i = 1, j = 1; i < ATAN_MAX; j <<= 1, ++i) { - if (v.y > 0) { - auto tmp = v.x + ((v.y + j) >> i); - v.y = v.y - ((v.x + j) >> i); - v.x = tmp; - theta += *atan++; - } else { - auto tmp = v.x - ((v.y + j) >> i); - v.y = v.y + ((v.x + j) >> i); - v.x = tmp; - theta -= *atan++; - } - } - - //round theta - if (theta >= 0) theta = PAD_ROUND(theta, 32); - else theta = -PAD_ROUND(-theta, 32); - - pt.x = v.x; - pt.y = theta; -} - - -static void _rotate(SwPoint& pt, SwFixed theta) -{ - SwFixed x = pt.x; - SwFixed y = pt.y; - - //Rotate inside [-PI/4, PI/4] sector - while (theta < -SW_ANGLE_PI4) { - auto tmp = y; - y = -x; - x = tmp; - theta += SW_ANGLE_PI2; - } - - while (theta > SW_ANGLE_PI4) { - auto tmp = -y; - y = x; - x = tmp; - theta -= SW_ANGLE_PI2; - } - - auto atan = ATAN_TBL; - uint32_t i; - SwFixed j; - - for (i = 1, j = 1; i < ATAN_MAX; j <<= 1, ++i) { - if (theta < 0) { - auto tmp = x + ((y + j) >> i); - y = y - ((x + j) >> i); - x = tmp; - theta += *atan++; - } else { - auto tmp = x - ((y + j) >> i); - y = y + ((x + j) >> i); - x = tmp; - theta -= *atan++; - } - } - - pt.x = static_cast<SwCoord>(x); - pt.y = static_cast<SwCoord>(y); + return (float(angle) / 65536.0f) * (MATH_PI / 180.0f); } @@ -214,11 +50,17 @@ bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, Sw auto d2 = base[1] - base[2]; auto d3 = base[0] - base[1]; + if (d1 == d2 || d2 == d3) { + if (d3.small()) angleIn = angleMid = angleOut = 0; + else angleIn = angleMid = angleOut = mathAtan(d3); + return true; + } + if (d1.small()) { if (d2.small()) { if (d3.small()) { - //basically a point. - //do nothing to retain original direction + angleIn = angleMid = angleOut = 0; + return true; } else { angleIn = angleMid = angleOut = mathAtan(d3); } @@ -320,77 +162,63 @@ int64_t mathMulDiv(int64_t a, int64_t b, int64_t c) void mathRotate(SwPoint& pt, SwFixed angle) { - if (angle == 0 || (pt.x == 0 && pt.y == 0)) return; - - auto v = pt; - auto shift = _normalize(v); + if (angle == 0 || pt.zero()) return; - auto theta = angle; - _rotate(v, theta); + Point v = pt.toPoint(); - v.x = _downscale(v.x); - v.y = _downscale(v.y); + auto radian = TO_RADIAN(angle); + auto cosv = cosf(radian); + auto sinv = sinf(radian); - if (shift > 0) { - auto half = static_cast<int32_t>(1L << (shift - 1)); - pt.x = (v.x + half + SATURATE(v.x)) >> shift; - pt.y = (v.y + half + SATURATE(v.y)) >> shift; - } else { - shift = -shift; - pt.x = static_cast<SwCoord>((unsigned long)v.x << shift); - pt.y = static_cast<SwCoord>((unsigned long)v.y << shift); - } + pt.x = SwCoord(roundf((v.x * cosv - v.y * sinv) * 64.0f)); + pt.y = SwCoord(roundf((v.x * sinv + v.y * cosv) * 64.0f)); } + SwFixed mathTan(SwFixed angle) { - SwPoint v = {CORDIC_FACTOR >> 8, 0}; - _rotate(v, angle); - return mathDivide(v.y, v.x); + if (angle == 0) return 0; + return SwFixed(tanf(TO_RADIAN(angle)) * 65536.0f); } SwFixed mathAtan(const SwPoint& pt) { - if (pt.x == 0 && pt.y == 0) return 0; - - auto v = pt; - _normalize(v); - _polarize(v); - - return v.y; + if (pt.zero()) return 0; + return SwFixed(atan2f(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f); } SwFixed mathSin(SwFixed angle) { + if (angle == 0) return 0; return mathCos(SW_ANGLE_PI2 - angle); } SwFixed mathCos(SwFixed angle) { - SwPoint v = {CORDIC_FACTOR >> 8, 0}; - _rotate(v, angle); - return (v.x + 0x80L) >> 8; + return SwFixed(cosf(TO_RADIAN(angle)) * 65536.0f); } SwFixed mathLength(const SwPoint& pt) { - auto v = pt; + if (pt.zero()) return 0; //trivial case - if (v.x == 0) return abs(v.y); - if (v.y == 0) return abs(v.x); - - //general case - auto shift = _normalize(v); - _polarize(v); - v.x = _downscale(v.x); - - if (shift > 0) return (v.x + (static_cast<SwFixed>(1) << (shift -1))) >> shift; - return static_cast<SwFixed>((uint32_t)v.x << -shift); + if (pt.x == 0) return abs(pt.y); + if (pt.y == 0) return abs(pt.x); + + auto v = pt.toPoint(); + //return static_cast<SwFixed>(sqrtf(v.x * v.x + v.y * v.y) * 65536.0f); + + /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. + With alpha = 1, beta = 3/8, giving results with the largest error less + than 7% compared to the exact value. */ + if (v.x < 0) v.x = -v.x; + if (v.y < 0) v.y = -v.y; + return static_cast<SwFixed>((v.x > v.y) ? (v.x + v.y * 0.375f) : (v.y + v.x * 0.375f)); } @@ -401,22 +229,22 @@ void mathSplitCubic(SwPoint* base) base[6].x = base[3].x; c = base[1].x; d = base[2].x; - base[1].x = a = (base[0].x + c) / 2; - base[5].x = b = (base[3].x + d) / 2; - c = (c + d) / 2; - base[2].x = a = (a + c) / 2; - base[4].x = b = (b + c) / 2; - base[3].x = (a + b) / 2; + base[1].x = a = (base[0].x + c) >> 1; + base[5].x = b = (base[3].x + d) >> 1; + c = (c + d) >> 1; + base[2].x = a = (a + c) >> 1; + base[4].x = b = (b + c) >> 1; + base[3].x = (a + b) >> 1; base[6].y = base[3].y; c = base[1].y; d = base[2].y; - base[1].y = a = (base[0].y + c) / 2; - base[5].y = b = (base[3].y + d) / 2; - c = (c + d) / 2; - base[2].y = a = (a + c) / 2; - base[4].y = b = (b + c) / 2; - base[3].y = (a + b) / 2; + base[1].y = a = (base[0].y + c) >> 1; + base[5].y = b = (base[3].y + d) >> 1; + c = (c + d) >> 1; + base[2].y = a = (a + c) >> 1; + base[4].y = b = (b + c) >> 1; + base[3].y = (a + b) >> 1; } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMemPool.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMemPool.cpp index 54ae594bff..b85d943873 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMemPool.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMemPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -77,7 +77,7 @@ void mpoolRetDashOutline(SwMpool* mpool, unsigned idx) } -SwMpool* mpoolInit(unsigned threads) +SwMpool* mpoolInit(uint32_t threads) { auto allocSize = threads + 1; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp index 4b1ba59100..9a6dc45950 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -248,17 +248,17 @@ static inline uint32_t _sampleSize(float scale) //Bilinear Interpolation //OPTIMIZE_ME: Skip the function pointer access -static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, TVG_UNUSED uint32_t n, TVG_UNUSED uint32_t n2) +static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, TVG_UNUSED int32_t miny, TVG_UNUSED int32_t maxy, TVG_UNUSED int32_t n) { - auto rx = (uint32_t)(sx); - auto ry = (uint32_t)(sy); + auto rx = (size_t)(sx); + auto ry = (size_t)(sy); auto rx2 = rx + 1; if (rx2 >= w) rx2 = w - 1; auto ry2 = ry + 1; if (ry2 >= h) ry2 = h - 1; - auto dx = static_cast<uint32_t>((sx - rx) * 255.0f); - auto dy = static_cast<uint32_t>((sy - ry) * 255.0f); + auto dx = static_cast<size_t>((sx - rx) * 255.0f); + auto dy = static_cast<size_t>((sy - ry) * 255.0f); auto c1 = img[rx + ry * w]; auto c2 = img[rx2 + ry * w]; @@ -271,18 +271,21 @@ static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, //2n x 2n Mean Kernel //OPTIMIZE_ME: Skip the function pointer access -static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, uint32_t n, uint32_t n2) +static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, float sx, TVG_UNUSED float sy, int32_t miny, int32_t maxy, int32_t n) { - uint32_t rx = lroundf(sx); - uint32_t ry = lroundf(sy); - uint32_t c[4] = {0, 0, 0, 0}; - auto src = img + rx - n + (ry - n) * stride; + size_t c[4] = {0, 0, 0, 0}; - for (auto y = ry - n; y < ry + n; ++y) { - if (y >= h) continue; + int32_t minx = (int32_t)sx - n; + if (minx < 0) minx = 0; + + int32_t maxx = (int32_t)sx + n; + if (maxx >= (int32_t)w) maxx = w; + + auto src = img + minx + miny * stride; + + for (auto y = miny; y < maxy; ++y) { auto p = src; - for (auto x = rx - n; x < rx + n; ++x, ++p) { - if (x >= w) continue; + for (auto x = minx; x < maxx; ++x, ++p) { c[0] += *p >> 24; c[1] += (*p >> 16) & 0xff; c[2] += (*p >> 8) & 0xff; @@ -290,9 +293,14 @@ static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t } src += stride; } - for (auto i = 0; i < 4; ++i) { - c[i] = (c[i] >> 2) / n2; - } + + n = (maxy - miny) * (maxx - minx); + + c[0] /= n; + c[1] /= n; + c[2] /= n; + c[3] /= n; + return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; } @@ -660,34 +668,39 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, /* RLE Scaled Image */ /************************************************************************/ +#define SCALED_IMAGE_RANGE_Y(y) \ + auto sy = (y) * itransform->e22 + itransform->e23; \ + auto my = (int32_t)round(sy); \ + if (my < 0 || (uint32_t)sy >= image->h) continue; \ + if (scaleMethod == _interpDownScaler) { \ + miny = my - (int32_t)sampleSize; \ + if (miny < 0) miny = 0; \ + maxy = my + (int32_t)sampleSize; \ + if (maxy >= (int32_t)image->h) maxy = (int32_t)image->h; \ + } + +#define SCALED_IMAGE_RANGE_X \ + auto sx = x * itransform->e11 + itransform->e13; \ + if ((int32_t)round(sx) < 0 || (uint32_t) sx >= image->w) continue; + + #if 0 //Enable it when GRAYSCALE image is supported static bool _rasterCompositeScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; auto span = image->rle->spans; + int32_t miny = 0, maxy = 0; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = span->y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(span->y) auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x]; auto a = MULTIPLY(span->coverage, opacity); - if (a == 255) { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = maskOp(src, *cmp, ~src); - } - } else { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = MULTIPLY(src, a); - *cmp = maskOp(tmp, *cmp, ~tmp); - } + for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (a < 255) src = MULTIPLY(src, a); + *cmp = maskOp(src, *cmp, ~src); } } return true; @@ -698,31 +711,20 @@ static bool _rasterDirectScaledMaskedRleImage(SwSurface* surface, const SwImage* { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; auto span = image->rle->spans; + int32_t miny = 0, maxy = 0; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = span->y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + SCALED_IMAGE_RANGE_Y(span->y) auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x]; auto dst = &surface->buf8[span->y * surface->stride + span->x]; auto a = MULTIPLY(span->coverage, opacity); - if (a == 255) { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = maskOp(src, *cmp, 0); //not use alpha - *dst = tmp + MULTIPLY(*dst, ~tmp); - } - } else { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = maskOp(MULTIPLY(src, a), *cmp, 0); //not use alpha - *dst = tmp + MULTIPLY(*dst, ~tmp); - } + for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (a < 255) src = MULTIPLY(src, a); + src = maskOp(src, *cmp, 0); //not use alpha + *dst = src + MULTIPLY(*dst, ~src); } } return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); @@ -752,32 +754,20 @@ static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image auto span = image->rle->spans; auto csize = surface->compositor->image.channelSize; auto alpha = surface->alpha(surface->compositor->method); - auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; + int32_t miny = 0, maxy = 0; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = span->y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize]; auto a = MULTIPLY(span->coverage, opacity); - if (a == 255) { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto tmp = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), alpha(cmp)); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); - } - } else { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = ALPHA_BLEND(src, MULTIPLY(alpha(cmp), a)); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); - } + for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + src = ALPHA_BLEND(src, (a == 255) ? alpha(cmp) : MULTIPLY(alpha(cmp), a)); + *dst = src + ALPHA_BLEND(*dst, IA(src)); } } @@ -790,34 +780,24 @@ static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* ima auto span = image->rle->spans; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; + int32_t miny = 0, maxy = 0; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = span->y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); if (alpha == 255) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); auto tmp = surface->blender(src, *dst, 255); *dst = INTERPOLATE(tmp, *dst, A(src)); } - } else if (opacity == 255) { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = surface->blender(src, *dst, 255); - *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src))); - } } else { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity); + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) src = ALPHA_BLEND(src, opacity); auto tmp = surface->blender(src, *dst, 255); *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src))); } @@ -832,27 +812,17 @@ static bool _rasterScaledRleImage(SwSurface* surface, const SwImage* image, cons auto span = image->rle->spans; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; + int32_t miny = 0, maxy = 0; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = span->y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); - if (alpha == 255) { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *dst = src + ALPHA_BLEND(*dst, IA(src)); - } - } else { - for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), alpha); - *dst = src + ALPHA_BLEND(*dst, IA(src)); - } + for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (alpha < 255) src = ALPHA_BLEND(src, alpha); + *dst = src + ALPHA_BLEND(*dst, IA(src)); } } return true; @@ -1067,29 +1037,18 @@ static bool _rasterCompositeScaledMaskedImage(SwSurface* surface, const SwImage* { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; auto cstride = surface->compositor->image.stride; auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); + int32_t miny = 0, maxy = 0; for (auto y = region.min.y; y < region.max.y; ++y) { - auto sy = y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(y) auto cmp = cbuffer; - if (opacity == 255) { - for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = maskOp(src, *cmp, ~src); - } - } else { - for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = MULTIPLY(src, opacity); - *cmp = maskOp(tmp, *cmp, ~tmp); - } + for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) src = MULTIPLY(src, opacity); + *cmp = maskOp(src, *cmp, ~src); } cbuffer += cstride; } @@ -1101,33 +1060,21 @@ static bool _rasterDirectScaledMaskedImage(SwSurface* surface, const SwImage* im { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; auto cstride = surface->compositor->image.stride; auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); + int32_t miny = 0, maxy = 0; for (auto y = region.min.y; y < region.max.y; ++y) { - auto sy = y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(y) auto cmp = cbuffer; auto dst = dbuffer; - if (opacity == 255) { - for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = maskOp(src, *cmp, 0); //not use alpha - *dst = tmp + MULTIPLY(*dst, ~tmp); - } - } else { - for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = MULTIPLY(src, opacity); - auto tmp2 = maskOp(tmp, *cmp, 0); //not use alpha - *dst = tmp2 + MULTIPLY(*dst, ~tmp2); - } + for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) src = MULTIPLY(src, opacity); + src = maskOp(src, *cmp, 0); //not use alpha + *dst = src + MULTIPLY(*dst, ~src); } cbuffer += cstride; dbuffer += surface->stride; @@ -1160,29 +1107,17 @@ static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage* image, c auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; + int32_t miny = 0, maxy = 0; for (auto y = region.min.y; y < region.max.y; ++y) { - auto sy = y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(y) auto dst = dbuffer; auto cmp = cbuffer; - if (opacity == 255) { - for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto temp = ALPHA_BLEND(src, alpha(cmp)); - *dst = temp + ALPHA_BLEND(*dst, IA(temp)); - } - } else { - for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto temp = ALPHA_BLEND(src, MULTIPLY(opacity, alpha(cmp))); - *dst = temp + ALPHA_BLEND(*dst, IA(temp)); - } + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto tmp = ALPHA_BLEND(src, opacity == 255 ? alpha(cmp) : MULTIPLY(opacity, alpha(cmp))); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); } dbuffer += surface->stride; cbuffer += surface->compositor->image.stride * csize; @@ -1196,28 +1131,17 @@ static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image, auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; + int32_t miny = 0, maxy = 0; for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { - auto sy = y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(y) auto dst = dbuffer; - if (opacity == 255) { - for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - auto tmp = surface->blender(src, *dst, 255); - *dst = INTERPOLATE(tmp, *dst, A(src)); - } - } else { - for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity); - auto tmp = surface->blender(src, *dst, 255); - *dst = INTERPOLATE(tmp, *dst, A(src)); - } + for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) ALPHA_BLEND(src, opacity); + auto tmp = surface->blender(src, *dst, 255); + *dst = INTERPOLATE(tmp, *dst, A(src)); } } return true; @@ -1229,26 +1153,16 @@ static bool _rasterScaledImage(SwSurface* surface, const SwImage* image, const M auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); - auto sampleSize2 = sampleSize * sampleSize; + int32_t miny = 0, maxy = 0; for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { - auto sy = y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; + SCALED_IMAGE_RANGE_Y(y) auto dst = dbuffer; - if (opacity == 255) { - for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *dst = src + ALPHA_BLEND(*dst, IA(src)); - } - } else { - for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { - auto sx = x * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity); - *dst = src + ALPHA_BLEND(*dst, IA(src)); - } + for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) src = ALPHA_BLEND(src, opacity); + *dst = src + ALPHA_BLEND(*dst, IA(src)); } } return true; @@ -1800,7 +1714,7 @@ static bool _rasterSolidGradientRle(SwSurface* surface, const SwRleData* rle, co static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) { - if (!rle || fill->linear.len < FLT_EPSILON) return false; + if (!rle) return false; if (_compositing(surface)) { if (_matting(surface)) return _rasterGradientMattedRle<FillLinear>(surface, rle, fill); @@ -1941,7 +1855,9 @@ void rasterUnpremultiply(Surface* surface) void rasterPremultiply(Surface* surface) { - if (surface->channelSize != sizeof(uint32_t)) return; + unique_lock<mutex> lock{surface->mtx}; + if (surface->premultiplied || (surface->channelSize != sizeof(uint32_t))) return; + surface->premultiplied = true; TVGLOG("SW_ENGINE", "Premultiply [Size: %d x %d]", surface->w, surface->h); @@ -1955,7 +1871,6 @@ void rasterPremultiply(Surface* surface) *dst = (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff); } } - surface->premultiplied = true; } @@ -2021,6 +1936,9 @@ bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, con bool rasterConvertCS(Surface* surface, ColorSpace to) { + unique_lock<mutex> lock{surface->mtx}; + if (surface->cs == to) return true; + //TOOD: Support SIMD accelerations auto from = surface->cs; @@ -2032,6 +1950,5 @@ bool rasterConvertCS(Surface* surface, ColorSpace to) surface->cs = to; return cRasterARGBtoABGR(surface); } - return false; } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterAvx.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterAvx.h index 090fa29a7a..177c7b847f 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterAvx.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterAvx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterC.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterC.h index da3c7077e8..6d0bd9383d 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterC.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterC.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterNeon.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterNeon.h index ba77ed53cf..cfbeb0caca 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterNeon.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterNeon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h index 698ab37da2..8d604a3c9d 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -821,8 +821,8 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const static AASpans* _AASpans(float ymin, float ymax, const SwImage* image, const SwBBox* region) { - auto yStart = static_cast<int32_t>(ymin); - auto yEnd = static_cast<int32_t>(ymax); + auto yStart = static_cast<int>(ymin); + auto yEnd = static_cast<int>(ymax); if (!_arrange(image, region, yStart, yEnd)) return nullptr; @@ -1108,8 +1108,7 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const float ys = FLT_MAX, ye = -1.0f; for (int i = 0; i < 4; i++) { - mathMultiply(&vertices[i].pt, transform); - + if (transform) mathMultiply(&vertices[i].pt, transform); if (vertices[i].pt.y < ys) ys = vertices[i].pt.y; if (vertices[i].pt.y > ye) ye = vertices[i].pt.y; } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp index 049aa3d1d0..c9c543fbb5 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -45,8 +45,11 @@ struct SwTask : Task bool pushed = false; //Pushed into task list? bool disposed = false; //Disposed task? - RenderRegion bounds() const + RenderRegion bounds() { + //Can we skip the synchronization? + done(); + RenderRegion region; //Range over? @@ -139,7 +142,9 @@ struct SwShapeTask : SwTask visibleFill = (alpha > 0 || rshape->fill); if (visibleFill || clipper) { shapeReset(&shape); - if (!shapePrepare(&shape, rshape, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err; + if (!shapePrepare(&shape, rshape, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) { + visibleFill = false; + } } } //Fill @@ -276,10 +281,8 @@ struct SwImageTask : SwTask auto clipRegion = bbox; //Convert colorspace if it's not aligned. - if (source->owner) { - if (source->cs != surface->cs) rasterConvertCS(source, surface->cs); - if (!source->premultiplied) rasterPremultiply(source); - } + rasterConvertCS(source, surface->cs); + rasterPremultiply(source); image.data = source->data; image.w = source->w; @@ -431,7 +434,6 @@ bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, surface->cs = cs; surface->channelSize = CHANNEL_SIZE(cs); surface->premultiplied = true; - surface->owner = true; vport.x = vport.y = 0; vport.w = surface->w; @@ -633,11 +635,8 @@ Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs) //New Composition if (!cmp) { - cmp = new SwSurface; - //Inherits attributes from main surface - *cmp = *surface; - + cmp = new SwSurface(surface); cmp->compositor = new SwCompositor; //TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h) diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h index 4393740bd9..83d942388f 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp index a4a7fabdee..33c94e1063 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp index 4f66cdacc0..e001ced2a8 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -558,11 +558,15 @@ void shapeReset(SwShape* shape) void shapeFree(SwShape* shape) { rleFree(shape->rle); + shape->rle = nullptr; + shapeDelFill(shape); if (shape->stroke) { rleFree(shape->strokeRle); + shape->strokeRle = nullptr; strokeFree(shape->stroke); + shape->stroke = nullptr; } } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp index 75c5fa5667..8f44cf3616 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/tvgAccessor.cpp b/thirdparty/thorvg/src/renderer/tvgAccessor.cpp index 0c636979b5..903437f29d 100644 --- a/thirdparty/thorvg/src/renderer/tvgAccessor.cpp +++ b/thirdparty/thorvg/src/renderer/tvgAccessor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/tvgAnimation.cpp b/thirdparty/thorvg/src/renderer/tvgAnimation.cpp index 7a29ecf973..995eca7f41 100644 --- a/thirdparty/thorvg/src/renderer/tvgAnimation.cpp +++ b/thirdparty/thorvg/src/renderer/tvgAnimation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -62,9 +62,9 @@ Animation::Animation() : pImpl(new Impl) } -Result Animation::frame(uint32_t no) noexcept +Result Animation::frame(float no) noexcept { - auto loader = pImpl->picture->pImpl->loader.get(); + auto loader = pImpl->picture->pImpl->loader; if (!loader) return Result::InsufficientCondition; if (!loader->animatable()) return Result::NonSupport; @@ -80,9 +80,9 @@ Picture* Animation::picture() const noexcept } -uint32_t Animation::curFrame() const noexcept +float Animation::curFrame() const noexcept { - auto loader = pImpl->picture->pImpl->loader.get(); + auto loader = pImpl->picture->pImpl->loader; if (!loader) return 0; if (!loader->animatable()) return 0; @@ -91,9 +91,9 @@ uint32_t Animation::curFrame() const noexcept } -uint32_t Animation::totalFrame() const noexcept +float Animation::totalFrame() const noexcept { - auto loader = pImpl->picture->pImpl->loader.get(); + auto loader = pImpl->picture->pImpl->loader; if (!loader) return 0; if (!loader->animatable()) return 0; @@ -104,7 +104,7 @@ uint32_t Animation::totalFrame() const noexcept float Animation::duration() const noexcept { - auto loader = pImpl->picture->pImpl->loader.get(); + auto loader = pImpl->picture->pImpl->loader; if (!loader) return 0; if (!loader->animatable()) return 0; diff --git a/thirdparty/thorvg/src/renderer/tvgBinaryDesc.h b/thirdparty/thorvg/src/renderer/tvgBinaryDesc.h index b1468148d6..29f84eb82a 100644 --- a/thirdparty/thorvg/src/renderer/tvgBinaryDesc.h +++ b/thirdparty/thorvg/src/renderer/tvgBinaryDesc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,7 +36,7 @@ using TvgBinFlag = TvgBinByte; #define TVG_HEADER_SIZE 33 //TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH + 2*SIZE(float) + TVG_HEADER_RESERVED_LENGTH + TVG_HEADER_COMPRESS_SIZE #define TVG_HEADER_SIGNATURE "ThorVG" #define TVG_HEADER_SIGNATURE_LENGTH 6 -#define TVG_HEADER_VERSION "001100" //Major 00, Minor 11, Micro 00 +#define TVG_HEADER_VERSION "001200" //Major 00, Minor 12, Micro 00 #define TVG_HEADER_VERSION_LENGTH 6 #define TVG_HEADER_RESERVED_LENGTH 1 //Storing flags for extensions #define TVG_HEADER_COMPRESS_SIZE 12 //TVG_HEADER_UNCOMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE_BITS diff --git a/thirdparty/thorvg/src/renderer/tvgCanvas.cpp b/thirdparty/thorvg/src/renderer/tvgCanvas.cpp index 2d4cbd048f..11d6b778f7 100644 --- a/thirdparty/thorvg/src/renderer/tvgCanvas.cpp +++ b/thirdparty/thorvg/src/renderer/tvgCanvas.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -63,9 +63,9 @@ Result Canvas::clear(bool free) noexcept Result Canvas::draw() noexcept { - TVGLOG("COMMON", "Draw S. -------------------------------- Canvas(%p)", this); + TVGLOG("RENDERER", "Draw S. -------------------------------- Canvas(%p)", this); auto ret = pImpl->draw(); - TVGLOG("COMMON", "Draw E. -------------------------------- Canvas(%p)", this); + TVGLOG("RENDERER", "Draw E. -------------------------------- Canvas(%p)", this); return ret; } @@ -73,9 +73,9 @@ Result Canvas::draw() noexcept Result Canvas::update(Paint* paint) noexcept { - TVGLOG("COMMON", "Update S. ------------------------------ Canvas(%p)", this); + TVGLOG("RENDERER", "Update S. ------------------------------ Canvas(%p)", this); auto ret = pImpl->update(paint, false); - TVGLOG("COMMON", "Update E. ------------------------------ Canvas(%p)", this); + TVGLOG("RENDERER", "Update E. ------------------------------ Canvas(%p)", this); return ret; } diff --git a/thirdparty/thorvg/src/renderer/tvgCanvas.h b/thirdparty/thorvg/src/renderer/tvgCanvas.h index f893f9f7c0..25181de47e 100644 --- a/thirdparty/thorvg/src/renderer/tvgCanvas.h +++ b/thirdparty/thorvg/src/renderer/tvgCanvas.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,14 +20,11 @@ * SOFTWARE. */ -#ifndef _TVG_CANVAS_IMPL_H_ -#define _TVG_CANVAS_IMPL_H_ +#ifndef _TVG_CANVAS_H_ +#define _TVG_CANVAS_H_ #include "tvgPaint.h" -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ struct Canvas::Impl { @@ -143,4 +140,4 @@ struct Canvas::Impl } }; -#endif /* _TVG_CANVAS_IMPL_H_ */ +#endif /* _TVG_CANVAS_H_ */ diff --git a/thirdparty/thorvg/src/renderer/tvgCommon.h b/thirdparty/thorvg/src/renderer/tvgCommon.h index f36b4b9b30..deb419bc65 100644 --- a/thirdparty/thorvg/src/renderer/tvgCommon.h +++ b/thirdparty/thorvg/src/renderer/tvgCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -61,8 +61,9 @@ using namespace tvg; #define TVG_CLASS_ID_PICTURE 3 #define TVG_CLASS_ID_LINEAR 4 #define TVG_CLASS_ID_RADIAL 5 +#define TVG_CLASS_ID_TEXT 6 -enum class FileType { Tvg = 0, Svg, Lottie, Raw, Png, Jpg, Webp, Unknown }; +enum class FileType { Tvg = 0, Svg, Ttf, Lottie, Raw, Png, Jpg, Webp, Gif, Unknown }; using Size = Point; diff --git a/thirdparty/thorvg/src/renderer/tvgFill.cpp b/thirdparty/thorvg/src/renderer/tvgFill.cpp index 9215882c8d..ea1010051e 100644 --- a/thirdparty/thorvg/src/renderer/tvgFill.cpp +++ b/thirdparty/thorvg/src/renderer/tvgFill.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/tvgFill.h b/thirdparty/thorvg/src/renderer/tvgFill.h index ff3dd48c49..47f0c051c0 100644 --- a/thirdparty/thorvg/src/renderer/tvgFill.h +++ b/thirdparty/thorvg/src/renderer/tvgFill.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/tvgFrameModule.h b/thirdparty/thorvg/src/renderer/tvgFrameModule.h index 857c6caeb9..df97ccb894 100644 --- a/thirdparty/thorvg/src/renderer/tvgFrameModule.h +++ b/thirdparty/thorvg/src/renderer/tvgFrameModule.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,15 +28,15 @@ namespace tvg { -class FrameModule: public LoadModule +class FrameModule: public ImageLoader { public: + FrameModule(FileType type) : ImageLoader(type) {} virtual ~FrameModule() {} - virtual bool frame(uint32_t frameNo) = 0; //set the current frame number - - virtual uint32_t totalFrame() = 0; //return the total frame count - virtual uint32_t curFrame() = 0; //return the current frame number + virtual bool frame(float no) = 0; //set the current frame number + virtual float totalFrame() = 0; //return the total frame count + virtual float curFrame() = 0; //return the current frame number virtual float duration() = 0; //return the animation duration in seconds virtual bool animatable() override { return true; } diff --git a/thirdparty/thorvg/src/renderer/tvgGlCanvas.cpp b/thirdparty/thorvg/src/renderer/tvgGlCanvas.cpp index aa7f8dbe2a..f6f0d354d1 100644 --- a/thirdparty/thorvg/src/renderer/tvgGlCanvas.cpp +++ b/thirdparty/thorvg/src/renderer/tvgGlCanvas.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/tvgInitializer.cpp b/thirdparty/thorvg/src/renderer/tvgInitializer.cpp index b7326a9fbc..76d89b40ed 100644 --- a/thirdparty/thorvg/src/renderer/tvgInitializer.cpp +++ b/thirdparty/thorvg/src/renderer/tvgInitializer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,6 +36,10 @@ #include "tvgGlRenderer.h" #endif +#ifdef THORVG_WG_RASTER_SUPPORT + #include "tvgWgRenderer.h" +#endif + /************************************************************************/ /* Internal Class Implementation */ @@ -91,19 +95,27 @@ static bool _buildVersionInfo() Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept { auto nonSupport = true; + if (static_cast<int>(engine) == 0) return Result::InvalidArguments; if (engine & CanvasEngine::Sw) { #ifdef THORVG_SW_RASTER_SUPPORT if (!SwRenderer::init(threads)) return Result::FailedAllocation; nonSupport = false; #endif - } else if (engine & CanvasEngine::Gl) { + } + + if (engine & CanvasEngine::Gl) { #ifdef THORVG_GL_RASTER_SUPPORT if (!GlRenderer::init(threads)) return Result::FailedAllocation; nonSupport = false; #endif - } else { - return Result::InvalidArguments; + } + + if (engine & CanvasEngine::Wg) { + #ifdef THORVG_WG_RASTER_SUPPORT + if (!WgRenderer::init(threads)) return Result::FailedAllocation; + nonSupport = false; + #endif } if (nonSupport) return Result::NonSupport; @@ -125,19 +137,27 @@ Result Initializer::term(CanvasEngine engine) noexcept if (_initCnt == 0) return Result::InsufficientCondition; auto nonSupport = true; + if (static_cast<int>(engine) == 0) return Result::InvalidArguments; if (engine & CanvasEngine::Sw) { #ifdef THORVG_SW_RASTER_SUPPORT if (!SwRenderer::term()) return Result::InsufficientCondition; nonSupport = false; #endif - } else if (engine & CanvasEngine::Gl) { + } + + if (engine & CanvasEngine::Gl) { #ifdef THORVG_GL_RASTER_SUPPORT if (!GlRenderer::term()) return Result::InsufficientCondition; nonSupport = false; #endif - } else { - return Result::InvalidArguments; + } + + if (engine & CanvasEngine::Wg) { + #ifdef THORVG_WG_RASTER_SUPPORT + if (!WgRenderer::term()) return Result::InsufficientCondition; + nonSupport = false; + #endif } if (nonSupport) return Result::NonSupport; @@ -156,3 +176,4 @@ uint16_t THORVG_VERSION_NUMBER() { return _version; } + diff --git a/thirdparty/thorvg/src/renderer/tvgIteratorAccessor.h b/thirdparty/thorvg/src/renderer/tvgIteratorAccessor.h index 2347613ed8..46e900a582 100644 --- a/thirdparty/thorvg/src/renderer/tvgIteratorAccessor.h +++ b/thirdparty/thorvg/src/renderer/tvgIteratorAccessor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/tvgLoadModule.h b/thirdparty/thorvg/src/renderer/tvgLoadModule.h index 29ceba3fcc..0ea766395e 100644 --- a/thirdparty/thorvg/src/renderer/tvgLoadModule.h +++ b/thirdparty/thorvg/src/renderer/tvgLoadModule.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,35 +24,73 @@ #define _TVG_LOAD_MODULE_H_ #include "tvgRender.h" +#include "tvgInlist.h" -namespace tvg -{ -class LoadModule +struct LoadModule { -public: - float w = 0, h = 0; //default image size - ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open() + INLIST_ITEM(LoadModule); + + //Use either hashkey(data) or hashpath(path) + uint64_t hashkey; + char* hashpath = nullptr; - virtual ~LoadModule() {} + FileType type; //current loader file type + uint16_t sharing = 0; //reference count + bool readied = false; //read done already. + + LoadModule(FileType type) : type(type) {} + virtual ~LoadModule() + { + free(hashpath); + } virtual bool open(const string& path) { return false; } virtual bool open(const char* data, uint32_t size, bool copy) { return false; } - virtual bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { return false; } - - //Override this if the vector-format has own resizing policy. virtual bool resize(Paint* paint, float w, float h) { return false; } - - virtual bool animatable() { return false; } //true if this loader supports animation. virtual void sync() {}; //finish immediately if any async update jobs. - virtual bool read() = 0; - virtual bool close() = 0; + virtual bool read() + { + if (readied) return false; + readied = true; + return true; + } - virtual unique_ptr<Surface> bitmap() { return nullptr; } - virtual unique_ptr<Paint> paint() { return nullptr; } + virtual bool close() + { + if (sharing == 0) return true; + --sharing; + return false; + } }; -} + +struct ImageLoader : LoadModule +{ + float w = 0, h = 0; //default image size + Surface surface; + + ImageLoader(FileType type) : LoadModule(type) {} + + virtual bool animatable() { return false; } //true if this loader supports animation. + virtual Paint* paint() { return nullptr; } + + virtual Surface* bitmap() + { + if (surface.data) return &surface; + return nullptr; + } +}; + + +struct FontLoader : LoadModule +{ + float scale = 1.0f; + + FontLoader(FileType type) : LoadModule(type) {} + + virtual bool request(Shape* shape, char* text, bool italic = false) = 0; +}; #endif //_TVG_LOAD_MODULE_H_ diff --git a/thirdparty/thorvg/src/renderer/tvgLoader.cpp b/thirdparty/thorvg/src/renderer/tvgLoader.cpp index 52bdb91d6a..628b0fa17f 100644 --- a/thirdparty/thorvg/src/renderer/tvgLoader.cpp +++ b/thirdparty/thorvg/src/renderer/tvgLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,6 +20,9 @@ * SOFTWARE. */ +#include <string.h> + +#include "tvgInlist.h" #include "tvgLoader.h" #ifdef THORVG_SVG_LOADER_SUPPORT @@ -42,16 +45,30 @@ #include "tvgWebpLoader.h" #endif +#ifdef THORVG_TTF_LOADER_SUPPORT + #include "tvgTtfLoader.h" +#endif + #ifdef THORVG_LOTTIE_LOADER_SUPPORT #include "tvgLottieLoader.h" #endif #include "tvgRawLoader.h" + +uint64_t HASH_KEY(const char* data, uint64_t size) +{ + return (((uint64_t) data) << 32) | size; +} + /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ +static mutex mtx; +static Inlist<LoadModule> _activeLoaders; + + static LoadModule* _find(FileType type) { switch(type) { @@ -67,6 +84,12 @@ static LoadModule* _find(FileType type) #endif break; } + case FileType::Ttf: { +#ifdef THORVG_TTF_LOADER_SUPPORT + return new TtfLoader; +#endif + break; + } case FileType::Lottie: { #ifdef THORVG_LOTTIE_LOADER_SUPPORT return new LottieLoader; @@ -111,6 +134,10 @@ static LoadModule* _find(FileType type) format = "SVG"; break; } + case FileType::Ttf: { + format = "TTF"; + break; + } case FileType::Lottie: { format = "lottie(json)"; break; @@ -136,7 +163,7 @@ static LoadModule* _find(FileType type) break; } } - TVGLOG("LOADER", "%s format is not supported", format); + TVGLOG("RENDERER", "%s format is not supported", format); #endif return nullptr; } @@ -152,29 +179,71 @@ static LoadModule* _findByPath(const string& path) if (!ext.compare("png")) return _find(FileType::Png); if (!ext.compare("jpg")) return _find(FileType::Jpg); if (!ext.compare("webp")) return _find(FileType::Webp); + if (!ext.compare("ttf") || !ext.compare("ttc")) return _find(FileType::Ttf); + if (!ext.compare("otf") || !ext.compare("otc")) return _find(FileType::Ttf); return nullptr; } -static LoadModule* _findByType(const string& mimeType) +static FileType _convert(const string& mimeType) { - if (mimeType.empty()) return nullptr; - auto type = FileType::Unknown; if (mimeType == "tvg") type = FileType::Tvg; else if (mimeType == "svg" || mimeType == "svg+xml") type = FileType::Svg; + else if (mimeType == "ttf" || mimeType == "otf") type = FileType::Ttf; else if (mimeType == "lottie") type = FileType::Lottie; else if (mimeType == "raw") type = FileType::Raw; else if (mimeType == "png") type = FileType::Png; else if (mimeType == "jpg" || mimeType == "jpeg") type = FileType::Jpg; else if (mimeType == "webp") type = FileType::Webp; - else { - TVGLOG("LOADER", "Given mimetype is unknown = \"%s\".", mimeType.c_str()); - return nullptr; + else TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType.c_str()); + + return type; +} + + +static LoadModule* _findByType(const string& mimeType) +{ + return _find(_convert(mimeType)); +} + + +static LoadModule* _findFromCache(const string& path) +{ + unique_lock<mutex> lock{mtx}; + + auto loader = _activeLoaders.head; + + while (loader) { + if (loader->hashpath && !strcmp(loader->hashpath, path.c_str())) { + ++loader->sharing; + return loader; + } + loader = loader->next; } + return nullptr; +} + + +static LoadModule* _findFromCache(const char* data, uint32_t size, const string& mimeType) +{ + auto type = _convert(mimeType); + if (type == FileType::Unknown) return nullptr; - return _find(type); + unique_lock<mutex> lock{mtx}; + auto loader = _activeLoaders.head; + + auto key = HASH_KEY(data, size); + + while (loader) { + if (loader->type == type && loader->hashkey == key) { + ++loader->sharing; + return loader; + } + loader = loader->next; + } + return nullptr; } @@ -185,40 +254,95 @@ static LoadModule* _findByType(const string& mimeType) bool LoaderMgr::init() { - //TODO: - return true; } bool LoaderMgr::term() { - //TODO: + auto loader = _activeLoaders.head; + + //clean up the remained font loaders which is globally used. + while (loader && loader->type == FileType::Ttf) { + auto ret = loader->close(); + auto tmp = loader; + loader = loader->next; + _activeLoaders.remove(tmp); + if (ret) delete(loader); + } + return true; +} + +bool LoaderMgr::retrieve(LoadModule* loader) +{ + if (!loader) return false; + if (loader->close()) { + { + unique_lock<mutex> lock{mtx}; + _activeLoaders.remove(loader); + } + delete(loader); + } return true; } -shared_ptr<LoadModule> LoaderMgr::loader(const string& path, bool* invalid) +LoadModule* LoaderMgr::loader(const string& path, bool* invalid) { *invalid = false; + if (auto loader = _findFromCache(path)) return loader; + if (auto loader = _findByPath(path)) { - if (loader->open(path)) return shared_ptr<LoadModule>(loader); - else delete(loader); + if (loader->open(path)) { + loader->hashpath = strdup(path.c_str()); + { + unique_lock<mutex> lock{mtx}; + _activeLoaders.back(loader); + } + return loader; + } + delete(loader); *invalid = true; } return nullptr; } -shared_ptr<LoadModule> LoaderMgr::loader(const char* data, uint32_t size, const string& mimeType, bool copy) +bool LoaderMgr::retrieve(const string& path) +{ + return retrieve(_findFromCache(path)); +} + + +LoadModule* LoaderMgr::loader(const char* key) +{ + auto loader = _activeLoaders.head; + + while (loader) { + if (loader->hashpath && strstr(loader->hashpath, key)) { + ++loader->sharing; + return loader; + } + loader = loader->next; + } + return nullptr; +} + + +LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mimeType, bool copy) { + if (auto loader = _findFromCache(data, size, mimeType)) return loader; + //Try with the given MimeType if (!mimeType.empty()) { if (auto loader = _findByType(mimeType)) { if (loader->open(data, size, copy)) { - return shared_ptr<LoadModule>(loader); + loader->hashkey = HASH_KEY(data, size); + unique_lock<mutex> lock{mtx}; + _activeLoaders.back(loader); + return loader; } else { TVGLOG("LOADER", "Given mimetype \"%s\" seems incorrect or not supported.", mimeType.c_str()); delete(loader); @@ -229,8 +353,15 @@ shared_ptr<LoadModule> LoaderMgr::loader(const char* data, uint32_t size, const for (int i = 0; i < static_cast<int>(FileType::Unknown); i++) { auto loader = _find(static_cast<FileType>(i)); if (loader) { - if (loader->open(data, size, copy)) return shared_ptr<LoadModule>(loader); - else delete(loader); + if (loader->open(data, size, copy)) { + loader->hashkey = HASH_KEY(data, size); + { + unique_lock<mutex> lock{mtx}; + _activeLoaders.back(loader); + } + return loader; + } + delete(loader); } } } @@ -238,12 +369,21 @@ shared_ptr<LoadModule> LoaderMgr::loader(const char* data, uint32_t size, const } -shared_ptr<LoadModule> LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool copy) +LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool copy) { + //TODO: should we check premultiplied?? + if (auto loader = _findFromCache((const char*)(data), w * h, "raw")) return loader; + //function is dedicated for raw images only auto loader = new RawLoader; - if (loader->open(data, w, h, copy)) return shared_ptr<LoadModule>(loader); - else delete(loader); - + if (loader->open(data, w, h, copy)) { + loader->hashkey = HASH_KEY((const char*)data, w * h); + { + unique_lock<mutex> lock{mtx}; + _activeLoaders.back(loader); + } + return loader; + } + delete(loader); return nullptr; } diff --git a/thirdparty/thorvg/src/renderer/tvgLoader.h b/thirdparty/thorvg/src/renderer/tvgLoader.h index 17ff9e2637..b15032df27 100644 --- a/thirdparty/thorvg/src/renderer/tvgLoader.h +++ b/thirdparty/thorvg/src/renderer/tvgLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,9 +29,12 @@ struct LoaderMgr { static bool init(); static bool term(); - static shared_ptr<LoadModule> loader(const string& path, bool* invalid); - static shared_ptr<LoadModule> loader(const char* data, uint32_t size, const string& mimeType, bool copy); - static shared_ptr<LoadModule> loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy); + static LoadModule* loader(const string& path, bool* invalid); + static LoadModule* loader(const char* data, uint32_t size, const string& mimeType, bool copy); + static LoadModule* loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy); + static LoadModule* loader(const char* key); + static bool retrieve(const string& path); + static bool retrieve(LoadModule* loader); }; #endif //_TVG_LOADER_H_ diff --git a/thirdparty/thorvg/src/renderer/tvgPaint.cpp b/thirdparty/thorvg/src/renderer/tvgPaint.cpp index 37df906dac..563db3b44a 100644 --- a/thirdparty/thorvg/src/renderer/tvgPaint.cpp +++ b/thirdparty/thorvg/src/renderer/tvgPaint.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,11 +22,24 @@ #include "tvgMath.h" #include "tvgPaint.h" +#include "tvgShape.h" +#include "tvgPicture.h" +#include "tvgScene.h" +#include "tvgText.h" /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ +#define PAINT_METHOD(ret, METHOD) \ + switch (id) { \ + case TVG_CLASS_ID_SHAPE: ret = P((Shape*)paint)->METHOD; break; \ + case TVG_CLASS_ID_SCENE: ret = P((Scene*)paint)->METHOD; break; \ + case TVG_CLASS_ID_PICTURE: ret = P((Picture*)paint)->METHOD; break; \ + case TVG_CLASS_ID_TEXT: ret = P((Text*)paint)->METHOD; break; \ + default: ret = {}; \ + } + static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport) { @@ -93,9 +106,36 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, } +RenderRegion Paint::Impl::bounds(RenderMethod& renderer) const +{ + RenderRegion ret; + PAINT_METHOD(ret, bounds(renderer)); + return ret; +} + + +bool Paint::Impl::dispose(RenderMethod& renderer) +{ + if (compData) compData->target->pImpl->dispose(renderer); + + bool ret; + PAINT_METHOD(ret, dispose(renderer)); + return ret; +} + + +Iterator* Paint::Impl::iterator() +{ + Iterator* ret; + PAINT_METHOD(ret, iterator()); + return ret; +} + + Paint* Paint::Impl::duplicate() { - auto ret = smethod->duplicate(); + Paint* ret; + PAINT_METHOD(ret, duplicate()); //duplicate Transform if (rTransform) { @@ -165,8 +205,10 @@ bool Paint::Impl::render(RenderMethod& renderer) /* Note: only ClipPath is processed in update() step. Create a composition image. */ if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) { - auto region = smethod->bounds(renderer); - if (MASK_REGION_MERGING(compData->method)) region.add(compData->target->pImpl->smethod->bounds(renderer)); + RenderRegion region; + PAINT_METHOD(region, bounds(renderer)); + + if (MASK_REGION_MERGING(compData->method)) region.add(P(compData->target)->bounds(renderer)); if (region.w == 0 || region.h == 0) return true; cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method)); if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) { @@ -177,7 +219,9 @@ bool Paint::Impl::render(RenderMethod& renderer) if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity); renderer.blend(blendMethod); - auto ret = smethod->render(renderer); + + bool ret; + PAINT_METHOD(ret, render(renderer)); if (cmp) renderer.endComposite(cmp); @@ -189,10 +233,7 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT { if (renderFlag & RenderUpdateFlag::Transform) { if (!rTransform) return nullptr; - if (!rTransform->update()) { - delete(rTransform); - rTransform = nullptr; - } + rTransform->update(); } /* 1. Composition Pre Processing */ @@ -239,18 +280,13 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT } /* 2. Main Update */ - RenderData rd = nullptr; auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag); renderFlag = RenderUpdateFlag::None; opacity = MULTIPLY(opacity, this->opacity); - if (rTransform && pTransform) { - RenderTransform outTransform(pTransform, rTransform); - rd = smethod->update(renderer, &outTransform, clips, opacity, newFlag, clipper); - } else { - auto outTransform = pTransform ? pTransform : rTransform; - rd = smethod->update(renderer, outTransform, clips, opacity, newFlag, clipper); - } + RenderData rd = nullptr; + RenderTransform outTransform(pTransform, rTransform); + PAINT_METHOD(rd, update(renderer, &outTransform, clips, opacity, newFlag, clipper)); /* 3. Composition Post Processing */ if (compFastTrack) renderer.viewport(viewport); @@ -263,9 +299,13 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transformed, bool stroking) { Matrix* m = nullptr; + bool ret; //Case: No transformed, quick return! - if (!transformed || !(m = this->transform())) return smethod->bounds(x, y, w, h, stroking); + if (!transformed || !(m = this->transform())) { + PAINT_METHOD(ret, bounds(x, y, w, h, stroking)); + return ret; + } //Case: Transformed auto tx = 0.0f; @@ -273,7 +313,7 @@ bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transforme auto tw = 0.0f; auto th = 0.0f; - auto ret = smethod->bounds(&tx, &ty, &tw, &th, stroking); + PAINT_METHOD(ret, bounds(&tx, &ty, &tw, &th, stroking)); //Get vertices Point pt[4] = {{tx, ty}, {tx + tw, ty}, {tx + tw, ty + th}, {tx, ty + th}}; @@ -307,7 +347,7 @@ bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transforme /* External Class Implementation */ /************************************************************************/ -Paint :: Paint() : pImpl(new Impl()) +Paint :: Paint() : pImpl(new Impl(this)) { } @@ -419,7 +459,10 @@ uint32_t Paint::identifier() const noexcept Result Paint::blend(BlendMethod method) const noexcept { - pImpl->blendMethod = method; + if (pImpl->blendMethod != method) { + pImpl->blendMethod = method; + pImpl->renderFlag |= RenderUpdateFlag::Blend; + } return Result::Success; } diff --git a/thirdparty/thorvg/src/renderer/tvgPaint.h b/thirdparty/thorvg/src/renderer/tvgPaint.h index 0ee07fedff..4ec9fa7f7e 100644 --- a/thirdparty/thorvg/src/renderer/tvgPaint.h +++ b/thirdparty/thorvg/src/renderer/tvgPaint.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,19 +38,6 @@ namespace tvg virtual void begin() = 0; }; - struct StrategyMethod - { - virtual ~StrategyMethod() {} - - virtual bool dispose(RenderMethod& renderer) = 0; //return true if the deletion is allowed. - virtual void* update(RenderMethod& renderer, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) = 0; //Return engine data if it has. - virtual bool render(RenderMethod& renderer) = 0; - virtual bool bounds(float* x, float* y, float* w, float* h, bool stroking) = 0; - virtual RenderRegion bounds(RenderMethod& renderer) const = 0; - virtual Paint* duplicate() = 0; - virtual Iterator* iterator() = 0; - }; - struct Composite { Paint* target; @@ -60,7 +47,7 @@ namespace tvg struct Paint::Impl { - StrategyMethod* smethod = nullptr; + Paint* paint = nullptr; RenderTransform* rTransform = nullptr; Composite* compData = nullptr; BlendMethod blendMethod = BlendMethod::Normal; //uint8_t @@ -70,13 +57,16 @@ namespace tvg uint8_t opacity = 255; uint8_t refCnt = 0; + Impl(Paint* pnt) : paint(pnt) + { + } + ~Impl() { if (compData) { - delete(compData->target); + if (P(compData->target)->unref() == 0) delete(compData->target); free(compData); } - delete(smethod); delete(rTransform); } @@ -92,11 +82,6 @@ namespace tvg return (--refCnt); } - void method(StrategyMethod* method) - { - smethod = method; - } - bool transform(const Matrix& m) { if (!rTransform) { @@ -119,29 +104,16 @@ namespace tvg return nullptr; } - RenderRegion bounds(RenderMethod& renderer) const - { - return smethod->bounds(renderer); - } - - bool dispose(RenderMethod& renderer) - { - if (compData) compData->target->pImpl->dispose(renderer); - return smethod->dispose(renderer); - } - - Iterator* iterator() - { - return smethod->iterator(); - } - bool composite(Paint* source, Paint* target, CompositeMethod method) { //Invalid case if ((!target && method != CompositeMethod::None) || (target && method == CompositeMethod::None)) return false; if (compData) { - delete(compData->target); + P(compData->target)->unref(); + if ((compData->target != target) && P(compData->target)->refCnt == 0) { + delete(compData->target); + } //Reset scenario if (!target && method == CompositeMethod::None) { free(compData); @@ -152,12 +124,16 @@ namespace tvg if (!target && method == CompositeMethod::None) return true; compData = static_cast<Composite*>(calloc(1, sizeof(Composite))); } + P(target)->ref(); compData->target = target; compData->source = source; compData->method = method; return true; } + RenderRegion bounds(RenderMethod& renderer) const; + bool dispose(RenderMethod& renderer); + Iterator* iterator(); bool rotate(float degree); bool scale(float factor); bool translate(float x, float y); @@ -166,51 +142,6 @@ namespace tvg bool render(RenderMethod& renderer); Paint* duplicate(); }; - - - template<class T> - struct PaintMethod : StrategyMethod - { - T* inst = nullptr; - - PaintMethod(T* _inst) : inst(_inst) {} - ~PaintMethod() {} - - bool bounds(float* x, float* y, float* w, float* h, bool stroking) override - { - return inst->bounds(x, y, w, h, stroking); - } - - RenderRegion bounds(RenderMethod& renderer) const override - { - return inst->bounds(renderer); - } - - bool dispose(RenderMethod& renderer) override - { - return inst->dispose(renderer); - } - - RenderData update(RenderMethod& renderer, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag renderFlag, bool clipper) override - { - return inst->update(renderer, transform, clips, opacity, renderFlag, clipper); - } - - bool render(RenderMethod& renderer) override - { - return inst->render(renderer); - } - - Paint* duplicate() override - { - return inst->duplicate(); - } - - Iterator* iterator() override - { - return inst->iterator(); - } - }; } #endif //_TVG_PAINT_H_ diff --git a/thirdparty/thorvg/src/renderer/tvgPicture.cpp b/thirdparty/thorvg/src/renderer/tvgPicture.cpp index 07877b92de..7f120593f4 100644 --- a/thirdparty/thorvg/src/renderer/tvgPicture.cpp +++ b/thirdparty/thorvg/src/renderer/tvgPicture.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,9 +30,8 @@ RenderUpdateFlag Picture::Impl::load() { if (loader) { if (!paint) { - if (auto p = loader->paint()) { - paint = p.release(); - loader->close(); + paint = loader->paint(); + if (paint) { if (w != loader->w || h != loader->h) { if (!resizing) { w = loader->w; @@ -41,13 +40,12 @@ RenderUpdateFlag Picture::Impl::load() loader->resize(paint, w, h); resizing = false; } - if (paint) return RenderUpdateFlag::None; + return RenderUpdateFlag::None; } } else loader->sync(); if (!surface) { - if ((surface = loader->bitmap().release())) { - loader->close(); + if ((surface = loader->bitmap())) { return RenderUpdateFlag::Image; } } @@ -55,6 +53,93 @@ RenderUpdateFlag Picture::Impl::load() return RenderUpdateFlag::None; } + +bool Picture::Impl::needComposition(uint8_t opacity) +{ + //In this case, paint(scene) would try composition itself. + if (opacity < 255) return false; + + //Composition test + const Paint* target; + auto method = picture->composite(&target); + if (!target || method == tvg::CompositeMethod::ClipPath) return false; + if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false; + + return true; +} + + +bool Picture::Impl::render(RenderMethod &renderer) +{ + bool ret = false; + if (surface) return renderer.renderImage(rd); + else if (paint) { + Compositor* cmp = nullptr; + if (needComp) { + cmp = renderer.target(bounds(renderer), renderer.colorSpace()); + renderer.beginComposite(cmp, CompositeMethod::None, 255); + } + ret = paint->pImpl->render(renderer); + if (cmp) renderer.endComposite(cmp); + } + return ret; +} + + +bool Picture::Impl::size(float w, float h) +{ + this->w = w; + this->h = h; + resizing = true; + return true; +} + + +RenderRegion Picture::Impl::bounds(RenderMethod& renderer) +{ + if (rd) return renderer.region(rd); + if (paint) return paint->pImpl->bounds(renderer); + return {0, 0, 0, 0}; +} + + +RenderTransform Picture::Impl::resizeTransform(const RenderTransform* pTransform) +{ + //Overriding Transformation by the desired image size + auto sx = w / loader->w; + auto sy = h / loader->h; + auto scale = sx < sy ? sx : sy; + + RenderTransform tmp; + tmp.m = {scale, 0, 0, 0, scale, 0, 0, 0, 1}; + + if (!pTransform) return tmp; + else return RenderTransform(pTransform, &tmp); +} + + +Result Picture::Impl::load(ImageLoader* loader) +{ + //Same resource has been loaded. + if (this->loader == loader) { + this->loader->sharing--; //make it sure the reference counting. + return Result::Success; + } else if (this->loader) { + LoaderMgr::retrieve(this->loader); + } + + this->loader = loader; + + if (!loader->read()) return Result::Unknown; + + this->w = loader->w; + this->h = loader->h; + + return Result::Success; +} + + + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -62,7 +147,6 @@ RenderUpdateFlag Picture::Impl::load() Picture::Picture() : pImpl(new Impl(this)) { Paint::pImpl->id = TVG_CLASS_ID_PICTURE; - Paint::pImpl->method(new PaintMethod<Picture::Impl>(pImpl)); } diff --git a/thirdparty/thorvg/src/renderer/tvgPicture.h b/thirdparty/thorvg/src/renderer/tvgPicture.h index 447f56ecb7..26a171ba66 100644 --- a/thirdparty/thorvg/src/renderer/tvgPicture.h +++ b/thirdparty/thorvg/src/renderer/tvgPicture.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,16 +20,13 @@ * SOFTWARE. */ -#ifndef _TVG_PICTURE_IMPL_H_ -#define _TVG_PICTURE_IMPL_H_ +#ifndef _TVG_PICTURE_H_ +#define _TVG_PICTURE_H_ #include <string> #include "tvgPaint.h" #include "tvgLoader.h" -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ struct PictureIterator : Iterator { @@ -60,7 +57,7 @@ struct PictureIterator : Iterator struct Picture::Impl { - shared_ptr<LoadModule> loader = nullptr; + ImageLoader* loader = nullptr; Paint* paint = nullptr; //vector picture uses Surface* surface = nullptr; //bitmap picture uses @@ -71,14 +68,21 @@ struct Picture::Impl bool resizing = false; bool needComp = false; //need composition + RenderTransform resizeTransform(const RenderTransform* pTransform); + bool needComposition(uint8_t opacity); + bool render(RenderMethod &renderer); + bool size(float w, float h); + RenderRegion bounds(RenderMethod& renderer); + Result load(ImageLoader* ploader); + Impl(Picture* p) : picture(p) { } ~Impl() { + LoaderMgr::retrieve(loader); delete(paint); - delete(surface); } bool dispose(RenderMethod& renderer) @@ -89,34 +93,6 @@ struct Picture::Impl return true; } - RenderTransform resizeTransform(const RenderTransform* pTransform) - { - //Overriding Transformation by the desired image size - auto sx = w / loader->w; - auto sy = h / loader->h; - auto scale = sx < sy ? sx : sy; - - RenderTransform tmp; - tmp.m = {scale, 0, 0, 0, scale, 0, 0, 0, 1}; - - if (!pTransform) return tmp; - else return RenderTransform(pTransform, &tmp); - } - - bool needComposition(uint8_t opacity) - { - //In this case, paint(scene) would try composition itself. - if (opacity < 255) return false; - - //Composition test - const Paint* target; - auto method = picture->composite(&target); - if (!target || method == tvg::CompositeMethod::ClipPath) return false; - if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false; - - return true; - } - RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) { auto flag = load(); @@ -135,30 +111,6 @@ struct Picture::Impl return rd; } - bool render(RenderMethod &renderer) - { - bool ret = false; - if (surface) return renderer.renderImage(rd); - else if (paint) { - Compositor* cmp = nullptr; - if (needComp) { - cmp = renderer.target(bounds(renderer), renderer.colorSpace()); - renderer.beginComposite(cmp, CompositeMethod::None, 255); - } - ret = paint->pImpl->render(renderer); - if (cmp) renderer.endComposite(cmp); - } - return ret; - } - - bool size(float w, float h) - { - this->w = w; - this->h = h; - resizing = true; - return true; - } - bool bounds(float* x, float* y, float* w, float* h, bool stroking) { if (rm.triangleCnt > 0) { @@ -195,50 +147,35 @@ struct Picture::Impl return true; } - RenderRegion bounds(RenderMethod& renderer) - { - if (rd) return renderer.region(rd); - if (paint) return paint->pImpl->bounds(renderer); - return {0, 0, 0, 0}; - } - Result load(const string& path) { if (paint || surface) return Result::InsufficientCondition; - if (loader) loader->close(); + bool invalid; //Invalid Path - loader = LoaderMgr::loader(path, &invalid); + auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(path, &invalid)); if (!loader) { if (invalid) return Result::InvalidArguments; return Result::NonSupport; } - if (!loader->read()) return Result::Unknown; - w = loader->w; - h = loader->h; - return Result::Success; + return load(loader); } Result load(const char* data, uint32_t size, const string& mimeType, bool copy) { if (paint || surface) return Result::InsufficientCondition; - if (loader) loader->close(); - loader = LoaderMgr::loader(data, size, mimeType, copy); + auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(data, size, mimeType, copy)); if (!loader) return Result::NonSupport; - if (!loader->read()) return Result::Unknown; - w = loader->w; - h = loader->h; - return Result::Success; + return load(loader); } Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) { if (paint || surface) return Result::InsufficientCondition; - if (loader) loader->close(); - loader = LoaderMgr::loader(data, w, h, copy); + + auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(data, w, h, copy)); if (!loader) return Result::FailedAllocation; - this->w = loader->w; - this->h = loader->h; - return Result::Success; + + return load(loader); } void mesh(const Polygon* triangles, const uint32_t triangleCnt) @@ -258,18 +195,17 @@ struct Picture::Impl { load(); - auto ret = Picture::gen(); + auto ret = Picture::gen().release(); + auto dup = ret->pImpl; - auto dup = ret.get()->pImpl; if (paint) dup->paint = paint->duplicate(); - dup->loader = loader; - if (surface) { - dup->surface = new Surface; - *dup->surface = *surface; - //TODO: A dupilcation is not a proxy... it needs copy of the pixel data? - dup->surface->owner = false; + if (loader) { + dup->loader = loader; + ++dup->loader->sharing; } + + dup->surface = surface; dup->w = w; dup->h = h; dup->resizing = resizing; @@ -280,7 +216,7 @@ struct Picture::Impl memcpy(dup->rm.triangles, rm.triangles, sizeof(Polygon) * rm.triangleCnt); } - return ret.release(); + return ret; } Iterator* iterator() @@ -308,4 +244,4 @@ struct Picture::Impl RenderUpdateFlag load(); }; -#endif //_TVG_PICTURE_IMPL_H_ +#endif //_TVG_PICTURE_H_ diff --git a/thirdparty/thorvg/src/renderer/tvgRender.cpp b/thirdparty/thorvg/src/renderer/tvgRender.cpp index 9768b5ede0..bdfb9f322e 100644 --- a/thirdparty/thorvg/src/renderer/tvgRender.cpp +++ b/thirdparty/thorvg/src/renderer/tvgRender.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,12 +39,9 @@ void RenderTransform::override(const Matrix& m) } -bool RenderTransform::update() +void RenderTransform::update() { - if (overriding) return true; - - //Init Status - if (mathZero(x) && mathZero(y) && mathZero(degree) && mathEqual(scale, 1)) return false; + if (overriding) return; mathIdentity(&m); @@ -53,17 +50,13 @@ bool RenderTransform::update() if (!mathZero(degree)) mathRotate(&m, degree); mathTranslate(&m, x, y); - - return true; -} - - -RenderTransform::RenderTransform() -{ } RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs) { - m = mathMultiply(&lhs->m, &rhs->m); + if (lhs && rhs) m = mathMultiply(&lhs->m, &rhs->m); + else if (lhs) m = lhs->m; + else if (rhs) m = rhs->m; + else mathIdentity(&m); } diff --git a/thirdparty/thorvg/src/renderer/tvgRender.h b/thirdparty/thorvg/src/renderer/tvgRender.h index 1231089ff5..1e70b53494 100644 --- a/thirdparty/thorvg/src/renderer/tvgRender.h +++ b/thirdparty/thorvg/src/renderer/tvgRender.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,7 @@ #ifndef _TVG_RENDER_H_ #define _TVG_RENDER_H_ +#include <mutex> #include "tvgCommon.h" #include "tvgArray.h" @@ -32,7 +33,7 @@ namespace tvg using RenderData = void*; using pixel_t = uint32_t; -enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255}; +enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, Blend = 128, All = 255}; struct Surface; @@ -49,17 +50,33 @@ enum ColorSpace struct Surface { union { - pixel_t* data; //system based data pointer - uint32_t* buf32; //for explicit 32bits channels - uint8_t* buf8; //for explicit 8bits grayscale + pixel_t* data = nullptr; //system based data pointer + uint32_t* buf32; //for explicit 32bits channels + uint8_t* buf8; //for explicit 8bits grayscale }; - uint32_t stride; - uint32_t w, h; - ColorSpace cs; - uint8_t channelSize; + mutex mtx; //used for thread safety + uint32_t stride = 0; + uint32_t w = 0, h = 0; + ColorSpace cs = ColorSpace::Unsupported; + uint8_t channelSize = 0; + bool premultiplied = 0; //Alpha-premultiplied + + Surface() + { + } + + Surface(const Surface* rhs) + { + data = rhs->data; + stride = rhs->stride; + w = rhs->w; + h = rhs->h; + cs = rhs->cs; + channelSize = rhs->channelSize; + premultiplied = rhs->premultiplied; + } + - bool premultiplied; //Alpha-premultiplied - bool owner; //Only owner could modify the buffer }; struct Compositor @@ -123,10 +140,10 @@ struct RenderTransform float scale = 1.0f; //scale factor bool overriding = false; //user transform? - bool update(); + void update(); void override(const Matrix& m); - RenderTransform(); + RenderTransform() {} RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs); }; diff --git a/thirdparty/thorvg/src/renderer/tvgSaveModule.h b/thirdparty/thorvg/src/renderer/tvgSaveModule.h index a997b644a7..fed05c52df 100644 --- a/thirdparty/thorvg/src/renderer/tvgSaveModule.h +++ b/thirdparty/thorvg/src/renderer/tvgSaveModule.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,7 @@ public: virtual ~SaveModule() {} virtual bool save(Paint* paint, const string& path, bool compress) = 0; + virtual bool save(Animation* animation, Paint* bg, const string& path, uint32_t quality, uint32_t fps) = 0; virtual bool close() = 0; }; diff --git a/thirdparty/thorvg/src/renderer/tvgSaver.cpp b/thirdparty/thorvg/src/renderer/tvgSaver.cpp index 3b4dfddcc2..11eb24d437 100644 --- a/thirdparty/thorvg/src/renderer/tvgSaver.cpp +++ b/thirdparty/thorvg/src/renderer/tvgSaver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,9 @@ #ifdef THORVG_TVG_SAVER_SUPPORT #include "tvgTvgSaver.h" #endif +#ifdef THORVG_GIF_SAVER_SUPPORT + #include "tvgGifSaver.h" +#endif /************************************************************************/ /* Internal Class Implementation */ @@ -34,9 +37,12 @@ struct Saver::Impl { SaveModule* saveModule = nullptr; + Paint* bg = nullptr; + ~Impl() { delete(saveModule); + delete(bg); } }; @@ -50,6 +56,12 @@ static SaveModule* _find(FileType type) #endif break; } + case FileType::Gif: { +#ifdef THORVG_GIF_SAVER_SUPPORT + return new GifSaver; +#endif + break; + } default: { break; } @@ -62,12 +74,16 @@ static SaveModule* _find(FileType type) format = "TVG"; break; } + case FileType::Gif: { + format = "GIF"; + break; + } default: { format = "???"; break; } } - TVGLOG("SAVER", "%s format is not supported", format); + TVGLOG("RENDERER", "%s format is not supported", format); #endif return nullptr; } @@ -78,6 +94,8 @@ static SaveModule* _find(const string& path) auto ext = path.substr(path.find_last_of(".") + 1); if (!ext.compare("tvg")) { return _find(FileType::Tvg); + } else if (!ext.compare("gif")) { + return _find(FileType::Gif); } return nullptr; } @@ -124,6 +142,46 @@ Result Saver::save(std::unique_ptr<Paint> paint, const string& path, bool compre } +Result Saver::background(unique_ptr<Paint> paint) noexcept +{ + delete(pImpl->bg); + pImpl->bg = paint.release(); + + return Result::Success; +} + + +Result Saver::save(unique_ptr<Animation> animation, const string& path, uint32_t quality, uint32_t fps) noexcept +{ + auto a = animation.release(); + if (!a) return Result::MemoryCorruption; + + if (mathZero(a->totalFrame())) { + delete(a); + return Result::InsufficientCondition; + } + + //Already on saving an other resource. + if (pImpl->saveModule) { + delete(a); + return Result::InsufficientCondition; + } + + if (auto saveModule = _find(path)) { + if (saveModule->save(a, pImpl->bg, path, quality, fps)) { + pImpl->saveModule = saveModule; + return Result::Success; + } else { + delete(a); + delete(saveModule); + return Result::Unknown; + } + } + delete(a); + return Result::NonSupport; +} + + Result Saver::sync() noexcept { if (!pImpl->saveModule) return Result::InsufficientCondition; diff --git a/thirdparty/thorvg/src/renderer/tvgScene.cpp b/thirdparty/thorvg/src/renderer/tvgScene.cpp index 52e7ea2bf6..f5809cf93b 100644 --- a/thirdparty/thorvg/src/renderer/tvgScene.cpp +++ b/thirdparty/thorvg/src/renderer/tvgScene.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,6 @@ Scene::Scene() : pImpl(new Impl(this)) { Paint::pImpl->id = TVG_CLASS_ID_SCENE; - Paint::pImpl->method(new PaintMethod<Scene::Impl>(pImpl)); } diff --git a/thirdparty/thorvg/src/renderer/tvgScene.h b/thirdparty/thorvg/src/renderer/tvgScene.h index 10daa49a99..1a5600c231 100644 --- a/thirdparty/thorvg/src/renderer/tvgScene.h +++ b/thirdparty/thorvg/src/renderer/tvgScene.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,15 +20,12 @@ * SOFTWARE. */ -#ifndef _TVG_SCENE_IMPL_H_ -#define _TVG_SCENE_IMPL_H_ +#ifndef _TVG_SCENE_H_ +#define _TVG_SCENE_H_ #include <float.h> #include "tvgPaint.h" -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ struct SceneIterator : Iterator { @@ -66,7 +63,7 @@ struct Scene::Impl RenderData rd = nullptr; Scene* scene = nullptr; uint8_t opacity; //for composition - bool needComp; //composite or not + bool needComp = false; //composite or not Impl(Scene* s) : scene(s) { @@ -75,7 +72,7 @@ struct Scene::Impl ~Impl() { for (auto paint : paints) { - if (paint->pImpl->unref() == 0) delete(paint); + if (P(paint)->unref() == 0) delete(paint); } } @@ -126,8 +123,7 @@ struct Scene::Impl this->renderer = &renderer; if (clipper) { - Array<RenderData> rds; - rds.reserve(paints.size()); + Array<RenderData> rds(paints.size()); for (auto paint : paints) { rds.push(paint->pImpl->update(renderer, transform, clips, opacity, flag, true)); } @@ -148,6 +144,7 @@ struct Scene::Impl if (needComp) { cmp = renderer.target(bounds(renderer), renderer.colorSpace()); renderer.beginComposite(cmp, CompositeMethod::None, opacity); + needComp = false; } for (auto paint : paints) { @@ -215,9 +212,8 @@ struct Scene::Impl Paint* duplicate() { - auto ret = Scene::gen(); - - auto dup = ret.get()->pImpl; + auto ret = Scene::gen().release(); + auto dup = ret->pImpl; for (auto paint : paints) { auto cdup = paint->duplicate(); @@ -225,7 +221,7 @@ struct Scene::Impl dup->paints.push_back(cdup); } - return ret.release(); + return ret; } void clear(bool free) @@ -246,4 +242,4 @@ struct Scene::Impl } }; -#endif //_TVG_SCENE_IMPL_H_ +#endif //_TVG_SCENE_H_ diff --git a/thirdparty/thorvg/src/renderer/tvgShape.cpp b/thirdparty/thorvg/src/renderer/tvgShape.cpp index efb7666b29..d083c8aa2c 100644 --- a/thirdparty/thorvg/src/renderer/tvgShape.cpp +++ b/thirdparty/thorvg/src/renderer/tvgShape.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,6 @@ constexpr auto PATH_KAPPA = 0.552284f; Shape :: Shape() : pImpl(new Impl(this)) { Paint::pImpl->id = TVG_CLASS_ID_SHAPE; - Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl)); } @@ -62,7 +61,7 @@ Result Shape::reset() noexcept pImpl->rs.path.cmds.clear(); pImpl->rs.path.pts.clear(); - pImpl->flag = RenderUpdateFlag::Path; + pImpl->flag |= RenderUpdateFlag::Path; return Result::Success; } @@ -70,18 +69,14 @@ Result Shape::reset() noexcept uint32_t Shape::pathCommands(const PathCommand** cmds) const noexcept { - if (!cmds) return 0; - - *cmds = pImpl->rs.path.cmds.data; + if (cmds) *cmds = pImpl->rs.path.cmds.data; return pImpl->rs.path.cmds.count; } uint32_t Shape::pathCoords(const Point** pts) const noexcept { - if (!pts) return 0; - - *pts = pImpl->rs.path.pts.data; + if (pts) *pts = pImpl->rs.path.pts.data; return pImpl->rs.path.pts.count; } @@ -135,11 +130,11 @@ Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept auto ryKappa = ry * PATH_KAPPA; pImpl->grow(6, 13); - pImpl->moveTo(cx, cy - ry); - pImpl->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy); + pImpl->moveTo(cx + rx, cy); pImpl->cubicTo(cx + rx, cy + ryKappa, cx + rxKappa, cy + ry, cx, cy + ry); pImpl->cubicTo(cx - rxKappa, cy + ry, cx - rx, cy + ryKappa, cx - rx, cy); pImpl->cubicTo(cx - rx, cy - ryKappa, cx - rxKappa, cy - ry, cx, cy - ry); + pImpl->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy); pImpl->close(); return Result::Success; @@ -224,8 +219,8 @@ Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry) } else if (mathEqual(rx, halfW) && mathEqual(ry, halfH)) { return appendCircle(x + (w * 0.5f), y + (h * 0.5f), rx, ry); } else { - auto hrx = rx * 0.5f; - auto hry = ry * 0.5f; + auto hrx = rx * PATH_KAPPA; + auto hry = ry * PATH_KAPPA; pImpl->grow(10, 17); pImpl->moveTo(x + rx, y); pImpl->lineTo(x + w - rx, y); diff --git a/thirdparty/thorvg/src/renderer/tvgShape.h b/thirdparty/thorvg/src/renderer/tvgShape.h index bb266866d0..a7f1226690 100644 --- a/thirdparty/thorvg/src/renderer/tvgShape.h +++ b/thirdparty/thorvg/src/renderer/tvgShape.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,16 +20,13 @@ * SOFTWARE. */ -#ifndef _TVG_SHAPE_IMPL_H_ -#define _TVG_SHAPE_IMPL_H_ +#ifndef _TVG_SHAPE_H_ +#define _TVG_SHAPE_H_ #include <memory.h> #include "tvgMath.h" #include "tvgPaint.h" -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ struct Shape::Impl { @@ -38,7 +35,7 @@ struct Shape::Impl Shape* shape; uint8_t flag = RenderUpdateFlag::None; uint8_t opacity; //for composition - bool needComp; //composite or not + bool needComp = false; //composite or not Impl(Shape* s) : shape(s) { @@ -59,6 +56,7 @@ struct Shape::Impl if (needComp) { cmp = renderer.target(bounds(renderer), renderer.colorSpace()); renderer.beginComposite(cmp, CompositeMethod::None, opacity); + needComp = false; } ret = renderer.renderShape(rd); if (cmp) renderer.endComposite(cmp); @@ -340,9 +338,9 @@ struct Shape::Impl Paint* duplicate() { - auto ret = Shape::gen(); + auto ret = Shape::gen().release(); + auto dup = ret->pImpl; - auto dup = ret.get()->pImpl; dup->rs.rule = rs.rule; //Color @@ -378,7 +376,7 @@ struct Shape::Impl dup->flag |= RenderUpdateFlag::Gradient; } - return ret.release(); + return ret; } Iterator* iterator() @@ -387,4 +385,4 @@ struct Shape::Impl } }; -#endif //_TVG_SHAPE_IMPL_H_ +#endif //_TVG_SHAPE_H_ diff --git a/thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp b/thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp index 95df6b486d..4404057049 100644 --- a/thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp +++ b/thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp index e3887c60fc..36d1ce1f8b 100644 --- a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp +++ b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,11 +20,11 @@ * SOFTWARE. */ -#include <deque> #include <thread> -#include <vector> #include <atomic> #include <condition_variable> +#include "tvgArray.h" +#include "tvgInlist.h" #include "tvgTaskScheduler.h" /************************************************************************/ @@ -34,7 +34,7 @@ namespace tvg { struct TaskQueue { - deque<Task*> taskDeque; + Inlist<Task> taskDeque; mutex mtx; condition_variable ready; bool done = false; @@ -44,8 +44,6 @@ struct TaskQueue { unique_lock<mutex> lock{mtx, try_to_lock}; if (!lock || taskDeque.empty()) return false; *task = taskDeque.front(); - taskDeque.pop_front(); - return true; } @@ -54,11 +52,9 @@ struct TaskQueue { { unique_lock<mutex> lock{mtx, try_to_lock}; if (!lock) return false; - taskDeque.push_back(task); + taskDeque.back(task); } - ready.notify_one(); - return true; } @@ -82,8 +78,6 @@ struct TaskQueue { if (taskDeque.empty()) return false; *task = taskDeque.front(); - taskDeque.pop_front(); - return true; } @@ -91,12 +85,10 @@ struct TaskQueue { { { unique_lock<mutex> lock{mtx}; - taskDeque.push_back(task); + taskDeque.back(task); } - ready.notify_one(); } - }; @@ -105,24 +97,36 @@ static thread_local bool _async = true; //toggle async tasking for each thread struct TaskSchedulerImpl { - uint32_t threadCnt; - vector<thread> threads; - vector<TaskQueue> taskQueues; + Array<thread*> threads; + Array<TaskQueue*> taskQueues; atomic<uint32_t> idx{0}; - TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt) + TaskSchedulerImpl(unsigned threadCnt) { threads.reserve(threadCnt); + taskQueues.reserve(threadCnt); for (unsigned i = 0; i < threadCnt; ++i) { - threads.emplace_back([&, i] { run(i); }); + taskQueues.push(new TaskQueue); + threads.push(new thread); + } + for (unsigned i = 0; i < threadCnt; ++i) { + *threads.data[i] = thread([&, i] { run(i); }); } } ~TaskSchedulerImpl() { - for (auto& queue : taskQueues) queue.complete(); - for (auto& thread : threads) thread.join(); + for (auto tq = taskQueues.data; tq < taskQueues.end(); ++tq) { + (*tq)->complete(); + } + for (auto thread = threads.data; thread < threads.end(); ++thread) { + (*thread)->join(); + delete(*thread); + } + for (auto tq = taskQueues.data; tq < taskQueues.end(); ++tq) { + delete(*tq); + } } void run(unsigned i) @@ -132,14 +136,14 @@ struct TaskSchedulerImpl //Thread Loop while (true) { auto success = false; - for (unsigned x = 0; x < threadCnt * 2; ++x) { - if (taskQueues[(i + x) % threadCnt].tryPop(&task)) { + for (unsigned x = 0; x < threads.count * 2; ++x) { + if (taskQueues[(i + x) % threads.count]->tryPop(&task)) { success = true; break; } } - if (!success && !taskQueues[i].pop(&task)) break; + if (!success && !taskQueues[i]->pop(&task)) break; (*task)(i + 1); } } @@ -147,13 +151,13 @@ struct TaskSchedulerImpl void request(Task* task) { //Async - if (threadCnt > 0 && _async) { + if (threads.count > 0 && _async) { task->prepare(); auto i = idx++; - for (unsigned n = 0; n < threadCnt; ++n) { - if (taskQueues[(i + n) % threadCnt].tryPush(task)) return; + for (unsigned n = 0; n < threads.count; ++n) { + if (taskQueues[(i + n) % threads.count]->tryPush(task)) return; } - taskQueues[i % threadCnt].push(task); + taskQueues[i % threads.count]->push(task); //Sync } else { task->run(0); @@ -192,7 +196,7 @@ void TaskScheduler::request(Task* task) unsigned TaskScheduler::threads() { - if (inst) return inst->threadCnt; + if (inst) return inst->threads.count; return 0; } diff --git a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h index 2dad80f5d0..483e084880 100644 --- a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h +++ b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,7 @@ #include <mutex> #include <condition_variable> #include "tvgCommon.h" +#include "tvgInlist.h" namespace tvg { @@ -50,6 +51,8 @@ private: bool pending = false; public: + INLIST_ITEM(Task); + virtual ~Task() = default; void done() diff --git a/thirdparty/thorvg/src/renderer/tvgText.cpp b/thirdparty/thorvg/src/renderer/tvgText.cpp new file mode 100644 index 0000000000..1fe244c11d --- /dev/null +++ b/thirdparty/thorvg/src/renderer/tvgText.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved. + + * 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 "tvgText.h" + + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + + +Text::Text() : pImpl(new Impl) +{ + Paint::pImpl->id = TVG_CLASS_ID_TEXT; +} + + +Text::~Text() +{ + delete(pImpl); +} + + +Result Text::text(const char* text) noexcept +{ + return pImpl->text(text); +} + + +Result Text::font(const char* name, float size, const char* style) noexcept +{ + return pImpl->font(name, size, style); +} + + +Result Text::load(const std::string& path) noexcept +{ + bool invalid; //invalid path + if (!LoaderMgr::loader(path, &invalid)) { + if (invalid) return Result::InvalidArguments; + else return Result::NonSupport; + } + + return Result::Success; +} + + +Result Text::unload(const std::string& path) noexcept +{ + if (LoaderMgr::retrieve(path)) return Result::Success; + return Result::InsufficientCondition; +} + + +Result Text::fill(uint8_t r, uint8_t g, uint8_t b) noexcept +{ + if (!pImpl->paint) return Result::InsufficientCondition; + + return pImpl->fill(r, g, b); +} + + +Result Text::fill(unique_ptr<Fill> f) noexcept +{ + if (!pImpl->paint) return Result::InsufficientCondition; + + auto p = f.release(); + if (!p) return Result::MemoryCorruption; + + return pImpl->fill(p); +} + + +unique_ptr<Text> Text::gen() noexcept +{ + return unique_ptr<Text>(new Text); +} + + +uint32_t Text::identifier() noexcept +{ + return TVG_CLASS_ID_TEXT; +} diff --git a/thirdparty/thorvg/src/renderer/tvgText.h b/thirdparty/thorvg/src/renderer/tvgText.h new file mode 100644 index 0000000000..b9f7ef6079 --- /dev/null +++ b/thirdparty/thorvg/src/renderer/tvgText.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved. + + * 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 _TVG_TEXT_H +#define _TVG_TEXT_H + +#include <cstring> +#include "tvgShape.h" +#include "tvgFill.h" + +#ifdef THORVG_TTF_LOADER_SUPPORT + #include "tvgTtfLoader.h" +#else + #include "tvgLoader.h" +#endif + +struct Text::Impl +{ + RenderData rd = nullptr; + FontLoader* loader = nullptr; + Shape* paint = nullptr; + char* utf8 = nullptr; + float fontSize; + bool italic = false; + bool changed = false; + + ~Impl() + { + free(utf8); + LoaderMgr::retrieve(loader); + delete(paint); + } + + Result fill(uint8_t r, uint8_t g, uint8_t b) + { + return paint->fill(r, g, b); + } + + Result fill(Fill* f) + { + return paint->fill(cast<Fill>(f)); + } + + Result text(const char* utf8) + { + free(this->utf8); + if (utf8) this->utf8 = strdup(utf8); + else this->utf8 = nullptr; + changed = true; + + return Result::Success; + } + + Result font(const char* name, float size, const char* style) + { + auto loader = LoaderMgr::loader(name); + if (!loader) return Result::InsufficientCondition; + + //Same resource has been loaded. + if (this->loader == loader) { + this->loader->sharing--; //make it sure the reference counting. + return Result::Success; + } else if (this->loader) { + LoaderMgr::retrieve(this->loader); + } + this->loader = static_cast<FontLoader*>(loader); + + if (!paint) paint = Shape::gen().release(); + + fontSize = size; + if (style && strstr(style, "italic")) italic = true; + changed = true; + return Result::Success; + } + + RenderRegion bounds(RenderMethod& renderer) + { + return renderer.region(rd); + } + + bool render(RenderMethod& renderer) + { + if (paint) return PP(paint)->render(renderer); + return false; + } + + bool load() + { + if (!loader) return false; + + //reload + if (changed) { + loader->request(paint, utf8, italic); + loader->read(); + changed = false; + } + if (paint) { + loader->resize(paint, fontSize, fontSize); + return true; + } + return false; + } + + RenderData update(RenderMethod& renderer, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) + { + if (!load()) return nullptr; + + //transform the gradient coordinates based on the final scaled font. + if (P(paint)->flag & RenderUpdateFlag::Gradient) { + auto fill = P(paint)->rs.fill; + auto scale = 1.0f / loader->scale; + if (fill->identifier() == TVG_CLASS_ID_LINEAR) { + P(static_cast<LinearGradient*>(fill))->x1 *= scale; + P(static_cast<LinearGradient*>(fill))->y1 *= scale; + P(static_cast<LinearGradient*>(fill))->x2 *= scale; + P(static_cast<LinearGradient*>(fill))->y2 *= scale; + } else { + P(static_cast<RadialGradient*>(fill))->cx *= scale; + P(static_cast<RadialGradient*>(fill))->cy *= scale; + P(static_cast<RadialGradient*>(fill))->r *= scale; + P(static_cast<RadialGradient*>(fill))->fx *= scale; + P(static_cast<RadialGradient*>(fill))->fy *= scale; + P(static_cast<RadialGradient*>(fill))->fr *= scale; + } + } + rd = PP(paint)->update(renderer, transform, clips, opacity, pFlag, clipper); + return rd; + } + + bool bounds(float* x, float* y, float* w, float* h, TVG_UNUSED bool stroking) + { + if (!load() || !paint) return false; + paint->bounds(x, y, w, h, true); + return true; + } + + bool dispose(RenderMethod& renderer) + { + renderer.dispose(rd); + this->rd = nullptr; + return true; + } + + Paint* duplicate() + { + load(); + + auto ret = Text::gen().release(); + auto dup = ret->pImpl; + if (paint) dup->paint = static_cast<Shape*>(paint->duplicate()); + + if (loader) { + dup->loader = loader; + ++dup->loader->sharing; + } + + dup->utf8 = strdup(utf8); + dup->italic = italic; + dup->fontSize = fontSize; + + return ret; + } + + Iterator* iterator() + { + return nullptr; + } +}; + + + +#endif //_TVG_TEXT_H diff --git a/thirdparty/thorvg/src/renderer/tvgWgCanvas.cpp b/thirdparty/thorvg/src/renderer/tvgWgCanvas.cpp new file mode 100644 index 0000000000..5205df1737 --- /dev/null +++ b/thirdparty/thorvg/src/renderer/tvgWgCanvas.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved. + + * 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 "tvgCanvas.h" + +#ifdef THORVG_WG_RASTER_SUPPORT + #include "tvgWgRenderer.h" +#endif + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct WgCanvas::Impl +{ +}; + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +#ifdef THORVG_WG_RASTER_SUPPORT +WgCanvas::WgCanvas() : Canvas(WgRenderer::gen()), pImpl(new Impl) +#else +WgCanvas::WgCanvas() : Canvas(nullptr), pImpl(nullptr) +#endif +{ +} + +WgCanvas::~WgCanvas() +{ + delete pImpl; +} + +Result WgCanvas::target(void* window, uint32_t w, uint32_t h) noexcept +{ +#ifdef THORVG_WG_RASTER_SUPPORT + if (!window) return Result::InvalidArguments; + if ((w == 0) || (h == 0)) return Result::InvalidArguments; + + //We know renderer type, avoid dynamic_cast for performance. + auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer); + if (!renderer) return Result::MemoryCorruption; + + if (!renderer->target(window, w, h)) return Result::Unknown; + + //Paints must be updated again with this new target. + Canvas::pImpl->needRefresh(); + + return Result::Success; +#endif + return Result::NonSupport; +} + +unique_ptr<WgCanvas> WgCanvas::gen() noexcept +{ +#ifdef THORVG_WG_RASTER_SUPPORT + return unique_ptr<WgCanvas>(new WgCanvas); +#endif + return nullptr; +} diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index 04d1dd0b9a..7e7fd0591c 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION=0.11.2 +VERSION=0.12.1 cd thirdparty/thorvg/ || true rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/ @@ -52,13 +52,13 @@ cp -rv src/renderer ../src/ # Only sw_engine is enabled. rm -rfv ../src/renderer/gl_engine +rm -rfv ../src/renderer/wg_engine # Enabled embedded loaders: raw, JPEG, PNG. mkdir ../src/loaders cp -rv src/loaders/svg src/loaders/raw ../src/loaders/ -cp -rv src/loaders/svg src/loaders/jpg ../src/loaders/ -cp -rv src/loaders/svg src/loaders/png ../src/loaders/ -cp -rv src/loaders/svg src/loaders/external_png ../src/loaders/ +cp -rv src/loaders/jpg ../src/loaders/ +cp -rv src/loaders/png src/loaders/external_png ../src/loaders/ popd rm -rf tmp diff --git a/thirdparty/volk/volk.c b/thirdparty/volk/volk.c index b390e73643..3da1667699 100644 --- a/thirdparty/volk/volk.c +++ b/thirdparty/volk/volk.c @@ -6,7 +6,9 @@ typedef const char* LPCSTR; typedef struct HINSTANCE__* HINSTANCE; typedef HINSTANCE HMODULE; - #ifdef _WIN64 + #if defined(_MINWINDEF_) + /* minwindef.h defines FARPROC, and attempting to redefine it may conflict with -Wstrict-prototypes */ + #elif defined(_WIN64) typedef __int64 (__stdcall* FARPROC)(void); #else typedef int (__stdcall* FARPROC)(void); @@ -1017,6 +1019,13 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_NV_fragment_shading_rate_enums) vkCmdSetFragmentShadingRateEnumNV = (PFN_vkCmdSetFragmentShadingRateEnumNV)load(context, "vkCmdSetFragmentShadingRateEnumNV"); #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + vkGetLatencyTimingsNV = (PFN_vkGetLatencyTimingsNV)load(context, "vkGetLatencyTimingsNV"); + vkLatencySleepNV = (PFN_vkLatencySleepNV)load(context, "vkLatencySleepNV"); + vkQueueNotifyOutOfBandNV = (PFN_vkQueueNotifyOutOfBandNV)load(context, "vkQueueNotifyOutOfBandNV"); + vkSetLatencyMarkerNV = (PFN_vkSetLatencyMarkerNV)load(context, "vkSetLatencyMarkerNV"); + vkSetLatencySleepModeNV = (PFN_vkSetLatencySleepModeNV)load(context, "vkSetLatencySleepModeNV"); +#endif /* defined(VK_NV_low_latency2) */ #if defined(VK_NV_memory_decompression) vkCmdDecompressMemoryIndirectCountNV = (PFN_vkCmdDecompressMemoryIndirectCountNV)load(context, "vkCmdDecompressMemoryIndirectCountNV"); vkCmdDecompressMemoryNV = (PFN_vkCmdDecompressMemoryNV)load(context, "vkCmdDecompressMemoryNV"); @@ -1818,6 +1827,13 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_NV_fragment_shading_rate_enums) table->vkCmdSetFragmentShadingRateEnumNV = (PFN_vkCmdSetFragmentShadingRateEnumNV)load(context, "vkCmdSetFragmentShadingRateEnumNV"); #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + table->vkGetLatencyTimingsNV = (PFN_vkGetLatencyTimingsNV)load(context, "vkGetLatencyTimingsNV"); + table->vkLatencySleepNV = (PFN_vkLatencySleepNV)load(context, "vkLatencySleepNV"); + table->vkQueueNotifyOutOfBandNV = (PFN_vkQueueNotifyOutOfBandNV)load(context, "vkQueueNotifyOutOfBandNV"); + table->vkSetLatencyMarkerNV = (PFN_vkSetLatencyMarkerNV)load(context, "vkSetLatencyMarkerNV"); + table->vkSetLatencySleepModeNV = (PFN_vkSetLatencySleepModeNV)load(context, "vkSetLatencySleepModeNV"); +#endif /* defined(VK_NV_low_latency2) */ #if defined(VK_NV_memory_decompression) table->vkCmdDecompressMemoryIndirectCountNV = (PFN_vkCmdDecompressMemoryIndirectCountNV)load(context, "vkCmdDecompressMemoryIndirectCountNV"); table->vkCmdDecompressMemoryNV = (PFN_vkCmdDecompressMemoryNV)load(context, "vkCmdDecompressMemoryNV"); @@ -2806,6 +2822,13 @@ PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; #if defined(VK_NV_fragment_shading_rate_enums) PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) +PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; +PFN_vkLatencySleepNV vkLatencySleepNV; +PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; +PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; +PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#endif /* defined(VK_NV_low_latency2) */ #if defined(VK_NV_memory_decompression) PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; diff --git a/thirdparty/volk/volk.h b/thirdparty/volk/volk.h index f70c51fcda..2d66b22621 100644 --- a/thirdparty/volk/volk.h +++ b/thirdparty/volk/volk.h @@ -15,7 +15,7 @@ #endif /* VOLK_GENERATE_VERSION_DEFINE */ -#define VOLK_HEADER_VERSION 261 +#define VOLK_HEADER_VERSION 268 /* VOLK_GENERATE_VERSION_DEFINE */ #ifndef VK_NO_PROTOTYPES @@ -787,6 +787,13 @@ struct VolkDeviceTable #if defined(VK_NV_fragment_shading_rate_enums) PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) + PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; + PFN_vkLatencySleepNV vkLatencySleepNV; + PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; + PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; + PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#endif /* defined(VK_NV_low_latency2) */ #if defined(VK_NV_memory_decompression) PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; @@ -1767,6 +1774,13 @@ extern PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; #if defined(VK_NV_fragment_shading_rate_enums) extern PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; #endif /* defined(VK_NV_fragment_shading_rate_enums) */ +#if defined(VK_NV_low_latency2) +extern PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV; +extern PFN_vkLatencySleepNV vkLatencySleepNV; +extern PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV; +extern PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV; +extern PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV; +#endif /* defined(VK_NV_low_latency2) */ #if defined(VK_NV_memory_decompression) extern PFN_vkCmdDecompressMemoryIndirectCountNV vkCmdDecompressMemoryIndirectCountNV; extern PFN_vkCmdDecompressMemoryNV vkCmdDecompressMemoryNV; diff --git a/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h264std.h b/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h264std.h index a23789c68a..ef7eaf745e 100644 --- a/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h264std.h +++ b/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h264std.h @@ -29,6 +29,7 @@ extern "C" { #define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS 64 #define STD_VIDEO_H264_MAX_NUM_LIST_REF 32 #define STD_VIDEO_H264_MAX_CHROMA_PLANES 2 +#define STD_VIDEO_H264_NO_REFERENCE_PICTURE 0xFF typedef enum StdVideoH264ChromaFormatIdc { STD_VIDEO_H264_CHROMA_FORMAT_IDC_MONOCHROME = 0, diff --git a/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h264std_encode.h b/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h264std_encode.h index 2e0d706f6c..58b8bdb2f6 100644 --- a/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h264std_encode.h +++ b/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h264std_encode.h @@ -23,9 +23,9 @@ extern "C" { #define vulkan_video_codec_h264std_encode 1 #include "vulkan_video_codec_h264std.h" // Vulkan 0.9 provisional Vulkan video H.264 encode std specification version number -#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_10 VK_MAKE_VIDEO_STD_VERSION(0, 9, 10) +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_11 VK_MAKE_VIDEO_STD_VERSION(0, 9, 11) -#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_10 +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_11 #define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_encode" typedef struct StdVideoEncodeH264WeightTableFlags { uint32_t luma_weight_l0_flag; @@ -81,7 +81,7 @@ typedef struct StdVideoEncodeH264RefListModEntry { } StdVideoEncodeH264RefListModEntry; typedef struct StdVideoEncodeH264RefPicMarkingEntry { - StdVideoH264MemMgmtControlOp operation; + StdVideoH264MemMgmtControlOp memory_management_control_operation; uint16_t difference_of_pic_nums_minus1; uint16_t long_term_pic_num; uint16_t long_term_frame_idx; @@ -132,7 +132,8 @@ typedef struct StdVideoEncodeH264SliceHeader { StdVideoH264SliceType slice_type; int8_t slice_alpha_c0_offset_div2; int8_t slice_beta_offset_div2; - uint16_t reserved1; + int8_t slice_qp_delta; + uint8_t reserved1; StdVideoH264CabacInitIdc cabac_init_idc; StdVideoH264DisableDeblockingFilterIdc disable_deblocking_filter_idc; const StdVideoEncodeH264WeightTable* pWeightTable; diff --git a/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h265std.h b/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h265std.h index 793bdbcff9..ff5d0dacbf 100644 --- a/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h265std.h +++ b/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h265std.h @@ -44,6 +44,7 @@ extern "C" { #define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32 #define STD_VIDEO_H265_MAX_LONG_TERM_PICS 16 #define STD_VIDEO_H265_MAX_DELTA_POC 48 +#define STD_VIDEO_H265_NO_REFERENCE_PICTURE 0xFF typedef enum StdVideoH265ChromaFormatIdc { STD_VIDEO_H265_CHROMA_FORMAT_IDC_MONOCHROME = 0, diff --git a/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h265std_encode.h b/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h265std_encode.h index 25740398a4..2a7024caba 100644 --- a/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h265std_encode.h +++ b/thirdparty/vulkan/include/vk_video/vulkan_video_codec_h265std_encode.h @@ -23,9 +23,9 @@ extern "C" { #define vulkan_video_codec_h265std_encode 1 #include "vulkan_video_codec_h265std.h" // Vulkan 0.9 provisional Vulkan video H.265 encode std specification version number -#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_11 VK_MAKE_VIDEO_STD_VERSION(0, 9, 11) +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_12 VK_MAKE_VIDEO_STD_VERSION(0, 9, 12) -#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_11 +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_12 #define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_encode" typedef struct StdVideoEncodeH265WeightTableFlags { uint16_t luma_weight_l0_flag; @@ -77,7 +77,8 @@ typedef struct StdVideoEncodeH265SliceSegmentHeader { int8_t slice_act_y_qp_offset; int8_t slice_act_cb_qp_offset; int8_t slice_act_cr_qp_offset; - uint8_t reserved1[3]; + int8_t slice_qp_delta; + uint16_t reserved1; const StdVideoEncodeH265WeightTable* pWeightTable; } StdVideoEncodeH265SliceSegmentHeader; @@ -110,7 +111,7 @@ typedef struct StdVideoEncodeH265PictureInfoFlags { uint32_t reserved : 23; } StdVideoEncodeH265PictureInfoFlags; -typedef struct StdVideoEncodeH265SliceSegmentLongTermRefPics { +typedef struct StdVideoEncodeH265LongTermRefPics { uint8_t num_long_term_sps; uint8_t num_long_term_pics; uint8_t lt_idx_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS]; @@ -118,21 +119,21 @@ typedef struct StdVideoEncodeH265SliceSegmentLongTermRefPics { uint16_t used_by_curr_pic_lt_flag; uint8_t delta_poc_msb_present_flag[STD_VIDEO_H265_MAX_DELTA_POC]; uint8_t delta_poc_msb_cycle_lt[STD_VIDEO_H265_MAX_DELTA_POC]; -} StdVideoEncodeH265SliceSegmentLongTermRefPics; +} StdVideoEncodeH265LongTermRefPics; typedef struct StdVideoEncodeH265PictureInfo { - StdVideoEncodeH265PictureInfoFlags flags; - StdVideoH265PictureType pic_type; - uint8_t sps_video_parameter_set_id; - uint8_t pps_seq_parameter_set_id; - uint8_t pps_pic_parameter_set_id; - uint8_t short_term_ref_pic_set_idx; - int32_t PicOrderCntVal; - uint8_t TemporalId; - uint8_t reserved1[7]; - const StdVideoEncodeH265ReferenceListsInfo* pRefLists; - const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet; - const StdVideoEncodeH265SliceSegmentLongTermRefPics* pLongTermRefPics; + StdVideoEncodeH265PictureInfoFlags flags; + StdVideoH265PictureType pic_type; + uint8_t sps_video_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t pps_pic_parameter_set_id; + uint8_t short_term_ref_pic_set_idx; + int32_t PicOrderCntVal; + uint8_t TemporalId; + uint8_t reserved1[7]; + const StdVideoEncodeH265ReferenceListsInfo* pRefLists; + const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet; + const StdVideoEncodeH265LongTermRefPics* pLongTermRefPics; } StdVideoEncodeH265PictureInfo; typedef struct StdVideoEncodeH265ReferenceInfoFlags { diff --git a/thirdparty/vulkan/include/vulkan/vulkan.cppm b/thirdparty/vulkan/include/vulkan/vulkan.cppm index cc693b8d43..9a2cad55c2 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan.cppm +++ b/thirdparty/vulkan/include/vulkan/vulkan.cppm @@ -5,6 +5,9 @@ // This header is generated from the Khronos Vulkan XML API Registry. +// Note: This module is still in an experimental state. +// Any feedback is welcome on https://github.com/KhronosGroup/Vulkan-Hpp/issues. + module; #include <vulkan/vulkan.hpp> @@ -12,10 +15,9 @@ module; #include <vulkan/vulkan_format_traits.hpp> #include <vulkan/vulkan_hash.hpp> #include <vulkan/vulkan_raii.hpp> +#include <vulkan/vulkan_shared.hpp> -export module vulkan; - -VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE +export module vulkan_hpp; export namespace VULKAN_HPP_NAMESPACE { @@ -25,6 +27,7 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::ArrayWrapper1D; using VULKAN_HPP_NAMESPACE::ArrayWrapper2D; using VULKAN_HPP_NAMESPACE::DispatchLoaderBase; + using VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic; using VULKAN_HPP_NAMESPACE::Flags; using VULKAN_HPP_NAMESPACE::FlagTraits; @@ -44,14 +47,19 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::Optional; using VULKAN_HPP_NAMESPACE::StridedArrayProxy; using VULKAN_HPP_NAMESPACE::StructureChain; - using VULKAN_HPP_NAMESPACE::UniqueHandle; #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ #if !defined( VULKAN_HPP_NO_SMART_HANDLE ) using VULKAN_HPP_NAMESPACE::ObjectDestroy; + using VULKAN_HPP_NAMESPACE::ObjectDestroyShared; using VULKAN_HPP_NAMESPACE::ObjectFree; + using VULKAN_HPP_NAMESPACE::ObjectFreeShared; using VULKAN_HPP_NAMESPACE::ObjectRelease; + using VULKAN_HPP_NAMESPACE::ObjectReleaseShared; using VULKAN_HPP_NAMESPACE::PoolFree; + using VULKAN_HPP_NAMESPACE::PoolFreeShared; + using VULKAN_HPP_NAMESPACE::SharedHandle; + using VULKAN_HPP_NAMESPACE::UniqueHandle; #endif /*VULKAN_HPP_NO_SMART_HANDLE*/ //================== @@ -110,6 +118,8 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::DescriptorType; using VULKAN_HPP_NAMESPACE::DeviceCreateFlagBits; using VULKAN_HPP_NAMESPACE::DeviceCreateFlags; + using VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlagBits; + using VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlags; using VULKAN_HPP_NAMESPACE::DynamicState; using VULKAN_HPP_NAMESPACE::EventCreateFlagBits; using VULKAN_HPP_NAMESPACE::EventCreateFlags; @@ -148,13 +158,21 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::ObjectType; using VULKAN_HPP_NAMESPACE::PhysicalDeviceType; using VULKAN_HPP_NAMESPACE::PipelineBindPoint; + using VULKAN_HPP_NAMESPACE::PipelineCacheCreateFlagBits; + using VULKAN_HPP_NAMESPACE::PipelineCacheCreateFlags; using VULKAN_HPP_NAMESPACE::PipelineCacheHeaderVersion; + using VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateFlagBits; + using VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateFlags; using VULKAN_HPP_NAMESPACE::PipelineCreateFlagBits; using VULKAN_HPP_NAMESPACE::PipelineCreateFlags; + using VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateFlagBits; + using VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateFlags; using VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateFlagBits; using VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateFlags; using VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateFlagBits; using VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateFlags; + using VULKAN_HPP_NAMESPACE::PipelineLayoutCreateFlagBits; + using VULKAN_HPP_NAMESPACE::PipelineLayoutCreateFlags; using VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateFlagBits; using VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateFlags; using VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateFlagBits; @@ -222,8 +240,6 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateFlags; using VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateType; using VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateTypeKHR; - using VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlagBits; - using VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlags; using VULKAN_HPP_NAMESPACE::ExternalFenceFeatureFlagBits; using VULKAN_HPP_NAMESPACE::ExternalFenceFeatureFlagBitsKHR; using VULKAN_HPP_NAMESPACE::ExternalFenceFeatureFlags; @@ -669,10 +685,6 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::DeviceMemoryReportFlagBitsEXT; using VULKAN_HPP_NAMESPACE::DeviceMemoryReportFlagsEXT; - //=== VK_EXT_pipeline_creation_cache_control === - using VULKAN_HPP_NAMESPACE::PipelineCacheCreateFlagBits; - using VULKAN_HPP_NAMESPACE::PipelineCacheCreateFlags; - #if defined( VK_ENABLE_BETA_EXTENSIONS ) //=== VK_KHR_video_encode_queue === using VULKAN_HPP_NAMESPACE::VideoEncodeCapabilityFlagBitsKHR; @@ -705,8 +717,6 @@ export namespace VULKAN_HPP_NAMESPACE //=== VK_EXT_graphics_pipeline_library === using VULKAN_HPP_NAMESPACE::GraphicsPipelineLibraryFlagBitsEXT; using VULKAN_HPP_NAMESPACE::GraphicsPipelineLibraryFlagsEXT; - using VULKAN_HPP_NAMESPACE::PipelineLayoutCreateFlagBits; - using VULKAN_HPP_NAMESPACE::PipelineLayoutCreateFlags; //=== VK_NV_fragment_shading_rate_enums === using VULKAN_HPP_NAMESPACE::FragmentShadingRateNV; @@ -748,6 +758,10 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::ImageFormatConstraintsFlagsFUCHSIA; #endif /*VK_USE_PLATFORM_FUCHSIA*/ + //=== VK_EXT_frame_boundary === + using VULKAN_HPP_NAMESPACE::FrameBoundaryFlagBitsEXT; + using VULKAN_HPP_NAMESPACE::FrameBoundaryFlagsEXT; + #if defined( VK_USE_PLATFORM_SCREEN_QNX ) //=== VK_QNX_screen_surface === using VULKAN_HPP_NAMESPACE::ScreenSurfaceCreateFlagBitsQNX; @@ -782,12 +796,6 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::DirectDriverLoadingFlagsLUNARG; using VULKAN_HPP_NAMESPACE::DirectDriverLoadingModeLUNARG; - //=== VK_EXT_rasterization_order_attachment_access === - using VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateFlagBits; - using VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateFlags; - using VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateFlagBits; - using VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateFlags; - //=== VK_NV_optical_flow === using VULKAN_HPP_NAMESPACE::OpticalFlowExecuteFlagBitsNV; using VULKAN_HPP_NAMESPACE::OpticalFlowExecuteFlagsNV; @@ -814,12 +822,25 @@ export namespace VULKAN_HPP_NAMESPACE //=== VK_NV_ray_tracing_invocation_reorder === using VULKAN_HPP_NAMESPACE::RayTracingInvocationReorderModeNV; + //=== VK_NV_low_latency2 === + using VULKAN_HPP_NAMESPACE::LatencyMarkerNV; + using VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeNV; + //=== VK_KHR_cooperative_matrix === using VULKAN_HPP_NAMESPACE::ComponentTypeKHR; using VULKAN_HPP_NAMESPACE::ComponentTypeNV; using VULKAN_HPP_NAMESPACE::ScopeKHR; using VULKAN_HPP_NAMESPACE::ScopeNV; + //=== VK_QCOM_image_processing2 === + using VULKAN_HPP_NAMESPACE::BlockMatchWindowCompareModeQCOM; + + //=== VK_QCOM_filter_cubic_weights === + using VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM; + + //=== VK_MSFT_layered_driver === + using VULKAN_HPP_NAMESPACE::LayeredDriverUnderlyingApiMSFT; + //========================= //=== Index Type Traits === //========================= @@ -925,40 +946,40 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::MaxDriverNameSize; //=== VK_KHR_device_group_creation === - using VULKAN_HPP_NAMESPACE::MaxDeviceGroupSizeKhr; + using VULKAN_HPP_NAMESPACE::MaxDeviceGroupSizeKHR; //=== VK_KHR_external_memory_capabilities === - using VULKAN_HPP_NAMESPACE::LuidSizeKhr; + using VULKAN_HPP_NAMESPACE::LuidSizeKHR; //=== VK_KHR_external_memory === - using VULKAN_HPP_NAMESPACE::QueueFamilyExternalKhr; + using VULKAN_HPP_NAMESPACE::QueueFamilyExternalKHR; #if defined( VK_ENABLE_BETA_EXTENSIONS ) //=== VK_AMDX_shader_enqueue === - using VULKAN_HPP_NAMESPACE::ShaderIndexUnusedAmdx; + using VULKAN_HPP_NAMESPACE::ShaderIndexUnusedAMDX; #endif /*VK_ENABLE_BETA_EXTENSIONS*/ //=== VK_KHR_ray_tracing_pipeline === - using VULKAN_HPP_NAMESPACE::ShaderUnusedKhr; + using VULKAN_HPP_NAMESPACE::ShaderUnusedKHR; //=== VK_NV_ray_tracing === - using VULKAN_HPP_NAMESPACE::ShaderUnusedNv; + using VULKAN_HPP_NAMESPACE::ShaderUnusedNV; //=== VK_KHR_global_priority === - using VULKAN_HPP_NAMESPACE::MaxGlobalPrioritySizeKhr; + using VULKAN_HPP_NAMESPACE::MaxGlobalPrioritySizeKHR; //=== VK_KHR_driver_properties === - using VULKAN_HPP_NAMESPACE::MaxDriverInfoSizeKhr; - using VULKAN_HPP_NAMESPACE::MaxDriverNameSizeKhr; + using VULKAN_HPP_NAMESPACE::MaxDriverInfoSizeKHR; + using VULKAN_HPP_NAMESPACE::MaxDriverNameSizeKHR; //=== VK_EXT_global_priority_query === - using VULKAN_HPP_NAMESPACE::MaxGlobalPrioritySizeExt; + using VULKAN_HPP_NAMESPACE::MaxGlobalPrioritySizeEXT; //=== VK_EXT_image_sliced_view_of_3d === - using VULKAN_HPP_NAMESPACE::Remaining3DSlicesExt; + using VULKAN_HPP_NAMESPACE::Remaining3DSlicesEXT; //=== VK_EXT_shader_module_identifier === - using VULKAN_HPP_NAMESPACE::MaxShaderModuleIdentifierSizeExt; + using VULKAN_HPP_NAMESPACE::MaxShaderModuleIdentifierSizeEXT; //======================== //=== CONSTEXPR VALUEs === @@ -2416,6 +2437,10 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::PhysicalDevicePipelinePropertiesFeaturesEXT; using VULKAN_HPP_NAMESPACE::PipelinePropertiesIdentifierEXT; + //=== VK_EXT_frame_boundary === + using VULKAN_HPP_NAMESPACE::FrameBoundaryEXT; + using VULKAN_HPP_NAMESPACE::PhysicalDeviceFrameBoundaryFeaturesEXT; + //=== VK_EXT_multisampled_render_to_single_sampled === using VULKAN_HPP_NAMESPACE::MultisampledRenderToSingleSampledInfoEXT; using VULKAN_HPP_NAMESPACE::PhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT; @@ -2540,6 +2565,10 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessingFeaturesQCOM; using VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessingPropertiesQCOM; + //=== VK_EXT_nested_command_buffer === + using VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferFeaturesEXT; + using VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferPropertiesEXT; + //=== VK_EXT_external_memory_acquire_unmodified === using VULKAN_HPP_NAMESPACE::ExternalMemoryAcquireUnmodifiedEXT; @@ -2586,6 +2615,13 @@ export namespace VULKAN_HPP_NAMESPACE //=== VK_EXT_pipeline_protected_access === using VULKAN_HPP_NAMESPACE::PhysicalDevicePipelineProtectedAccessFeaturesEXT; +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + //=== VK_ANDROID_external_format_resolve === + using VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatResolvePropertiesANDROID; + using VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolveFeaturesANDROID; + using VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolvePropertiesANDROID; +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + //=== VK_KHR_maintenance5 === using VULKAN_HPP_NAMESPACE::BufferUsageFlags2CreateInfoKHR; using VULKAN_HPP_NAMESPACE::DeviceImageSubresourceInfoKHR; @@ -2621,6 +2657,10 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingInvocationReorderFeaturesNV; using VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingInvocationReorderPropertiesNV; + //=== VK_NV_extended_sparse_address_space === + using VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + using VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + //=== VK_EXT_mutable_descriptor_type === using VULKAN_HPP_NAMESPACE::MutableDescriptorTypeCreateInfoEXT; using VULKAN_HPP_NAMESPACE::MutableDescriptorTypeCreateInfoVALVE; @@ -2639,6 +2679,17 @@ export namespace VULKAN_HPP_NAMESPACE //=== VK_EXT_dynamic_rendering_unused_attachments === using VULKAN_HPP_NAMESPACE::PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT; + //=== VK_NV_low_latency2 === + using VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV; + using VULKAN_HPP_NAMESPACE::LatencySleepInfoNV; + using VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV; + using VULKAN_HPP_NAMESPACE::LatencySubmissionPresentIdNV; + using VULKAN_HPP_NAMESPACE::LatencySurfaceCapabilitiesNV; + using VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV; + using VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV; + using VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV; + using VULKAN_HPP_NAMESPACE::SwapchainLatencyCreateInfoNV; + //=== VK_KHR_cooperative_matrix === using VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesKHR; using VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixFeaturesKHR; @@ -2648,6 +2699,23 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM; using VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM; + //=== VK_QCOM_image_processing2 === + using VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2FeaturesQCOM; + using VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2PropertiesQCOM; + using VULKAN_HPP_NAMESPACE::SamplerBlockMatchWindowCreateInfoQCOM; + + //=== VK_QCOM_filter_cubic_weights === + using VULKAN_HPP_NAMESPACE::BlitImageCubicWeightsInfoQCOM; + using VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicWeightsFeaturesQCOM; + using VULKAN_HPP_NAMESPACE::SamplerCubicWeightsCreateInfoQCOM; + + //=== VK_QCOM_ycbcr_degamma === + using VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrDegammaFeaturesQCOM; + using VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; + + //=== VK_QCOM_filter_cubic_clamp === + using VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicClampFeaturesQCOM; + //=== VK_EXT_attachment_feedback_loop_dynamic_state === using VULKAN_HPP_NAMESPACE::PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT; @@ -2660,6 +2728,12 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::ScreenBufferPropertiesQNX; #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ + //=== VK_MSFT_layered_driver === + using VULKAN_HPP_NAMESPACE::PhysicalDeviceLayeredDriverPropertiesMSFT; + + //=== VK_NV_descriptor_pool_overallocation === + using VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + //=============== //=== HANDLEs === //=============== @@ -2845,6 +2919,104 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::UniqueShaderEXT; #endif /*VULKAN_HPP_NO_SMART_HANDLE*/ + //====================== + //=== SHARED HANDLEs === + //====================== + +#if !defined( VULKAN_HPP_NO_SMART_HANDLE ) + + //=== VK_VERSION_1_0 === + using VULKAN_HPP_NAMESPACE::SharedBuffer; + using VULKAN_HPP_NAMESPACE::SharedBufferView; + using VULKAN_HPP_NAMESPACE::SharedCommandBuffer; + using VULKAN_HPP_NAMESPACE::SharedCommandPool; + using VULKAN_HPP_NAMESPACE::SharedDescriptorPool; + using VULKAN_HPP_NAMESPACE::SharedDescriptorSet; + using VULKAN_HPP_NAMESPACE::SharedDescriptorSetLayout; + using VULKAN_HPP_NAMESPACE::SharedDevice; + using VULKAN_HPP_NAMESPACE::SharedDeviceMemory; + using VULKAN_HPP_NAMESPACE::SharedEvent; + using VULKAN_HPP_NAMESPACE::SharedFence; + using VULKAN_HPP_NAMESPACE::SharedFramebuffer; + using VULKAN_HPP_NAMESPACE::SharedImage; + using VULKAN_HPP_NAMESPACE::SharedImageView; + using VULKAN_HPP_NAMESPACE::SharedInstance; + using VULKAN_HPP_NAMESPACE::SharedPhysicalDevice; + using VULKAN_HPP_NAMESPACE::SharedPipeline; + using VULKAN_HPP_NAMESPACE::SharedPipelineCache; + using VULKAN_HPP_NAMESPACE::SharedPipelineLayout; + using VULKAN_HPP_NAMESPACE::SharedQueryPool; + using VULKAN_HPP_NAMESPACE::SharedQueue; + using VULKAN_HPP_NAMESPACE::SharedRenderPass; + using VULKAN_HPP_NAMESPACE::SharedSampler; + using VULKAN_HPP_NAMESPACE::SharedSemaphore; + using VULKAN_HPP_NAMESPACE::SharedShaderModule; + + //=== VK_VERSION_1_1 === + using VULKAN_HPP_NAMESPACE::SharedDescriptorUpdateTemplate; + using VULKAN_HPP_NAMESPACE::SharedSamplerYcbcrConversion; + + //=== VK_VERSION_1_3 === + using VULKAN_HPP_NAMESPACE::SharedPrivateDataSlot; + + //=== VK_KHR_surface === + using VULKAN_HPP_NAMESPACE::SharedSurfaceKHR; + + //=== VK_KHR_swapchain === + using VULKAN_HPP_NAMESPACE::SharedSwapchainKHR; + + //=== VK_KHR_display === + using VULKAN_HPP_NAMESPACE::SharedDisplayKHR; + using VULKAN_HPP_NAMESPACE::SharedDisplayModeKHR; + + //=== VK_EXT_debug_report === + using VULKAN_HPP_NAMESPACE::SharedDebugReportCallbackEXT; + + //=== VK_KHR_video_queue === + using VULKAN_HPP_NAMESPACE::SharedVideoSessionKHR; + using VULKAN_HPP_NAMESPACE::SharedVideoSessionParametersKHR; + + //=== VK_NVX_binary_import === + using VULKAN_HPP_NAMESPACE::SharedCuFunctionNVX; + using VULKAN_HPP_NAMESPACE::SharedCuModuleNVX; + + //=== VK_EXT_debug_utils === + using VULKAN_HPP_NAMESPACE::SharedDebugUtilsMessengerEXT; + + //=== VK_KHR_acceleration_structure === + using VULKAN_HPP_NAMESPACE::SharedAccelerationStructureKHR; + + //=== VK_EXT_validation_cache === + using VULKAN_HPP_NAMESPACE::SharedValidationCacheEXT; + + //=== VK_NV_ray_tracing === + using VULKAN_HPP_NAMESPACE::SharedAccelerationStructureNV; + + //=== VK_INTEL_performance_query === + using VULKAN_HPP_NAMESPACE::SharedPerformanceConfigurationINTEL; + + //=== VK_KHR_deferred_host_operations === + using VULKAN_HPP_NAMESPACE::SharedDeferredOperationKHR; + + //=== VK_NV_device_generated_commands === + using VULKAN_HPP_NAMESPACE::SharedIndirectCommandsLayoutNV; + +# if defined( VK_USE_PLATFORM_FUCHSIA ) + //=== VK_FUCHSIA_buffer_collection === + using VULKAN_HPP_NAMESPACE::SharedBufferCollectionFUCHSIA; +# endif /*VK_USE_PLATFORM_FUCHSIA*/ + + //=== VK_EXT_opacity_micromap === + using VULKAN_HPP_NAMESPACE::SharedMicromapEXT; + + //=== VK_NV_optical_flow === + using VULKAN_HPP_NAMESPACE::SharedOpticalFlowSessionNV; + + //=== VK_EXT_shader_object === + using VULKAN_HPP_NAMESPACE::SharedHandleTraits; + using VULKAN_HPP_NAMESPACE::SharedShaderEXT; +#endif /*VULKAN_HPP_NO_SMART_HANDLE*/ + //=========================== //=== COMMAND Definitions === //=========================== @@ -2865,8 +3037,6 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::DynamicLoader; #endif /*VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL*/ - using VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic; - //===================== //=== Format Traits === //===================== @@ -2906,6 +3076,7 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_NAMESPACE::isObsoletedExtension; using VULKAN_HPP_NAMESPACE::isPromotedExtension; +#if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) && !defined( VULKAN_HPP_NO_EXCEPTIONS ) namespace VULKAN_HPP_RAII_NAMESPACE { //====================== @@ -3004,10 +3175,10 @@ export namespace VULKAN_HPP_NAMESPACE //=== VK_NV_device_generated_commands === using VULKAN_HPP_RAII_NAMESPACE::IndirectCommandsLayoutNV; -#if defined( VK_USE_PLATFORM_FUCHSIA ) +# if defined( VK_USE_PLATFORM_FUCHSIA ) //=== VK_FUCHSIA_buffer_collection === using VULKAN_HPP_RAII_NAMESPACE::BufferCollectionFUCHSIA; -#endif /*VK_USE_PLATFORM_FUCHSIA*/ +# endif /*VK_USE_PLATFORM_FUCHSIA*/ //=== VK_EXT_opacity_micromap === using VULKAN_HPP_RAII_NAMESPACE::MicromapEXT; @@ -3020,4 +3191,5 @@ export namespace VULKAN_HPP_NAMESPACE using VULKAN_HPP_RAII_NAMESPACE::ShaderEXTs; } // namespace VULKAN_HPP_RAII_NAMESPACE +#endif } // namespace VULKAN_HPP_NAMESPACE diff --git a/thirdparty/vulkan/include/vulkan/vulkan.hpp b/thirdparty/vulkan/include/vulkan/vulkan.hpp index 03789305bf..37f72277cf 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan.hpp @@ -8,37 +8,17 @@ #ifndef VULKAN_HPP #define VULKAN_HPP -#if defined( _MSVC_LANG ) -# define VULKAN_HPP_CPLUSPLUS _MSVC_LANG -#else -# define VULKAN_HPP_CPLUSPLUS __cplusplus -#endif - -#if 201703L < VULKAN_HPP_CPLUSPLUS -# define VULKAN_HPP_CPP_VERSION 20 -#elif 201402L < VULKAN_HPP_CPLUSPLUS -# define VULKAN_HPP_CPP_VERSION 17 -#elif 201103L < VULKAN_HPP_CPLUSPLUS -# define VULKAN_HPP_CPP_VERSION 14 -#elif 199711L < VULKAN_HPP_CPLUSPLUS -# define VULKAN_HPP_CPP_VERSION 11 -#else -# error "vulkan.hpp needs at least c++ standard version 11" -#endif - #include <algorithm> #include <array> // ArrayWrapperND #include <string> // std::string #include <vulkan/vulkan.h> +#include <vulkan/vulkan_hpp_macros.hpp> + #if 17 <= VULKAN_HPP_CPP_VERSION # include <string_view> // std::string_view #endif -#if defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) -# if !defined( VULKAN_HPP_NO_SMART_HANDLE ) -# define VULKAN_HPP_NO_SMART_HANDLE -# endif -#else +#if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) # include <tuple> // std::tie # include <vector> // std::vector #endif @@ -47,43 +27,12 @@ # include <system_error> // std::is_error_code_enum #endif -#if defined( VULKAN_HPP_NO_CONSTRUCTORS ) -# if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) -# define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS -# endif -# if !defined( VULKAN_HPP_NO_UNION_CONSTRUCTORS ) -# define VULKAN_HPP_NO_UNION_CONSTRUCTORS -# endif -#endif - -#if defined( VULKAN_HPP_NO_SETTERS ) -# if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) -# define VULKAN_HPP_NO_STRUCT_SETTERS -# endif -# if !defined( VULKAN_HPP_NO_UNION_SETTERS ) -# define VULKAN_HPP_NO_UNION_SETTERS -# endif -#endif - -#if !defined( VULKAN_HPP_ASSERT ) +#if ( VULKAN_HPP_ASSERT == assert ) # include <cassert> -# define VULKAN_HPP_ASSERT assert -#endif - -#if !defined( VULKAN_HPP_ASSERT_ON_RESULT ) -# define VULKAN_HPP_ASSERT_ON_RESULT VULKAN_HPP_ASSERT -#endif - -#if !defined( VULKAN_HPP_STATIC_ASSERT ) -# define VULKAN_HPP_STATIC_ASSERT static_assert -#endif - -#if !defined( VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL ) -# define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1 #endif #if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL == 1 -# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNXNTO__ ) || defined( __Fuchsia__ ) +# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNX__ ) || defined( __Fuchsia__ ) # include <dlfcn.h> # elif defined( _WIN32 ) typedef struct HINSTANCE__ * HINSTANCE; @@ -98,31 +47,15 @@ extern "C" __declspec( dllimport ) FARPROC __stdcall GetProcAddress( HINSTANCE h # endif #endif -#if !defined( __has_include ) -# define __has_include( x ) false -#endif - -#if ( 201907 <= __cpp_lib_three_way_comparison ) && __has_include( <compare> ) && !defined( VULKAN_HPP_NO_SPACESHIP_OPERATOR ) -# define VULKAN_HPP_HAS_SPACESHIP_OPERATOR -#endif #if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) # include <compare> #endif -#if ( 201803 <= __cpp_lib_span ) -# define VULKAN_HPP_SUPPORT_SPAN +#if defined( VULKAN_HPP_SUPPORT_SPAN ) # include <span> #endif -static_assert( VK_HEADER_VERSION == 261, "Wrong VK_HEADER_VERSION!" ); - -// 32-bit vulkan is not typesafe for non-dispatchable handles, so don't allow copy constructors on this platform by default. -// To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION -#if ( VK_USE_64_BIT_PTR_DEFINES == 1 ) -# if !defined( VULKAN_HPP_TYPESAFE_CONVERSION ) -# define VULKAN_HPP_TYPESAFE_CONVERSION -# endif -#endif +static_assert( VK_HEADER_VERSION == 268, "Wrong VK_HEADER_VERSION!" ); // <tuple> includes <sys/sysmacros.h> through some other header // this results in major(x) being resolved to gnu_dev_major(x) @@ -151,115 +84,6 @@ constexpr int True = 1; constexpr int False = 0; #endif -#if defined( __GNUC__ ) -# define GCC_VERSION ( __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) -#endif - -#if !defined( VULKAN_HPP_HAS_UNRESTRICTED_UNIONS ) -# if defined( __clang__ ) -# if __has_feature( cxx_unrestricted_unions ) -# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS -# endif -# elif defined( __GNUC__ ) -# if 40600 <= GCC_VERSION -# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS -# endif -# elif defined( _MSC_VER ) -# if 1900 <= _MSC_VER -# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS -# endif -# endif -#endif - -#if !defined( VULKAN_HPP_INLINE ) -# if defined( __clang__ ) -# if __has_attribute( always_inline ) -# define VULKAN_HPP_INLINE __attribute__( ( always_inline ) ) __inline__ -# else -# define VULKAN_HPP_INLINE inline -# endif -# elif defined( __GNUC__ ) -# define VULKAN_HPP_INLINE __attribute__( ( always_inline ) ) __inline__ -# elif defined( _MSC_VER ) -# define VULKAN_HPP_INLINE inline -# else -# define VULKAN_HPP_INLINE inline -# endif -#endif - -#if defined( VULKAN_HPP_TYPESAFE_CONVERSION ) -# define VULKAN_HPP_TYPESAFE_EXPLICIT -#else -# define VULKAN_HPP_TYPESAFE_EXPLICIT explicit -#endif - -#if defined( __cpp_constexpr ) -# define VULKAN_HPP_CONSTEXPR constexpr -# if 201304 <= __cpp_constexpr -# define VULKAN_HPP_CONSTEXPR_14 constexpr -# else -# define VULKAN_HPP_CONSTEXPR_14 -# endif -# if ( 201907 <= __cpp_constexpr ) && ( !defined( __GNUC__ ) || ( 110400 < GCC_VERSION ) ) -# define VULKAN_HPP_CONSTEXPR_20 constexpr -# else -# define VULKAN_HPP_CONSTEXPR_20 -# endif -# define VULKAN_HPP_CONST_OR_CONSTEXPR constexpr -#else -# define VULKAN_HPP_CONSTEXPR -# define VULKAN_HPP_CONSTEXPR_14 -# define VULKAN_HPP_CONST_OR_CONSTEXPR const -#endif - -#if !defined( VULKAN_HPP_CONSTEXPR_INLINE ) -# if 201606L <= __cpp_inline_variables -# define VULKAN_HPP_CONSTEXPR_INLINE VULKAN_HPP_CONSTEXPR inline -# else -# define VULKAN_HPP_CONSTEXPR_INLINE VULKAN_HPP_CONSTEXPR -# endif -#endif - -#if !defined( VULKAN_HPP_NOEXCEPT ) -# if defined( _MSC_VER ) && ( _MSC_VER <= 1800 ) -# define VULKAN_HPP_NOEXCEPT -# else -# define VULKAN_HPP_NOEXCEPT noexcept -# define VULKAN_HPP_HAS_NOEXCEPT 1 -# if defined( VULKAN_HPP_NO_EXCEPTIONS ) -# define VULKAN_HPP_NOEXCEPT_WHEN_NO_EXCEPTIONS noexcept -# else -# define VULKAN_HPP_NOEXCEPT_WHEN_NO_EXCEPTIONS -# endif -# endif -#endif - -#if 14 <= VULKAN_HPP_CPP_VERSION -# define VULKAN_HPP_DEPRECATED( msg ) [[deprecated( msg )]] -#else -# define VULKAN_HPP_DEPRECATED( msg ) -#endif - -#if ( 17 <= VULKAN_HPP_CPP_VERSION ) && !defined( VULKAN_HPP_NO_NODISCARD_WARNINGS ) -# define VULKAN_HPP_NODISCARD [[nodiscard]] -# if defined( VULKAN_HPP_NO_EXCEPTIONS ) -# define VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS [[nodiscard]] -# else -# define VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS -# endif -#else -# define VULKAN_HPP_NODISCARD -# define VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS -#endif - -#if !defined( VULKAN_HPP_NAMESPACE ) -# define VULKAN_HPP_NAMESPACE vk -#endif - -#define VULKAN_HPP_STRINGIFY2( text ) #text -#define VULKAN_HPP_STRINGIFY( text ) VULKAN_HPP_STRINGIFY2( text ) -#define VULKAN_HPP_NAMESPACE_STRING VULKAN_HPP_STRINGIFY( VULKAN_HPP_NAMESPACE ) - namespace VULKAN_HPP_NAMESPACE { template <typename T, size_t N> @@ -401,212 +225,6 @@ namespace VULKAN_HPP_NAMESPACE } }; - template <typename FlagBitsType> - struct FlagTraits - { - static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = false; - }; - - template <typename BitType> - class Flags - { - public: - using MaskType = typename std::underlying_type<BitType>::type; - - // constructors - VULKAN_HPP_CONSTEXPR Flags() VULKAN_HPP_NOEXCEPT : m_mask( 0 ) {} - - VULKAN_HPP_CONSTEXPR Flags( BitType bit ) VULKAN_HPP_NOEXCEPT : m_mask( static_cast<MaskType>( bit ) ) {} - - VULKAN_HPP_CONSTEXPR Flags( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT = default; - - VULKAN_HPP_CONSTEXPR explicit Flags( MaskType flags ) VULKAN_HPP_NOEXCEPT : m_mask( flags ) {} - - // relational operators -#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) - auto operator<=>( Flags<BitType> const & ) const = default; -#else - VULKAN_HPP_CONSTEXPR bool operator<( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return m_mask < rhs.m_mask; - } - - VULKAN_HPP_CONSTEXPR bool operator<=( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return m_mask <= rhs.m_mask; - } - - VULKAN_HPP_CONSTEXPR bool operator>( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return m_mask > rhs.m_mask; - } - - VULKAN_HPP_CONSTEXPR bool operator>=( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return m_mask >= rhs.m_mask; - } - - VULKAN_HPP_CONSTEXPR bool operator==( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return m_mask == rhs.m_mask; - } - - VULKAN_HPP_CONSTEXPR bool operator!=( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return m_mask != rhs.m_mask; - } -#endif - - // logical operator - VULKAN_HPP_CONSTEXPR bool operator!() const VULKAN_HPP_NOEXCEPT - { - return !m_mask; - } - - // bitwise operators - VULKAN_HPP_CONSTEXPR Flags<BitType> operator&( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return Flags<BitType>( m_mask & rhs.m_mask ); - } - - VULKAN_HPP_CONSTEXPR Flags<BitType> operator|( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return Flags<BitType>( m_mask | rhs.m_mask ); - } - - VULKAN_HPP_CONSTEXPR Flags<BitType> operator^( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT - { - return Flags<BitType>( m_mask ^ rhs.m_mask ); - } - - VULKAN_HPP_CONSTEXPR Flags<BitType> operator~() const VULKAN_HPP_NOEXCEPT - { - return Flags<BitType>( m_mask ^ FlagTraits<BitType>::allFlags.m_mask ); - } - - // assignment operators - VULKAN_HPP_CONSTEXPR_14 Flags<BitType> & operator=( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT = default; - - VULKAN_HPP_CONSTEXPR_14 Flags<BitType> & operator|=( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT - { - m_mask |= rhs.m_mask; - return *this; - } - - VULKAN_HPP_CONSTEXPR_14 Flags<BitType> & operator&=( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT - { - m_mask &= rhs.m_mask; - return *this; - } - - VULKAN_HPP_CONSTEXPR_14 Flags<BitType> & operator^=( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT - { - m_mask ^= rhs.m_mask; - return *this; - } - - // cast operators - explicit VULKAN_HPP_CONSTEXPR operator bool() const VULKAN_HPP_NOEXCEPT - { - return !!m_mask; - } - - explicit VULKAN_HPP_CONSTEXPR operator MaskType() const VULKAN_HPP_NOEXCEPT - { - return m_mask; - } - -#if defined( VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC ) - public: -#else - private: -#endif - MaskType m_mask; - }; - -#if !defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) - // relational operators only needed for pre C++20 - template <typename BitType> - VULKAN_HPP_CONSTEXPR bool operator<( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator>( bit ); - } - - template <typename BitType> - VULKAN_HPP_CONSTEXPR bool operator<=( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator>=( bit ); - } - - template <typename BitType> - VULKAN_HPP_CONSTEXPR bool operator>( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator<( bit ); - } - - template <typename BitType> - VULKAN_HPP_CONSTEXPR bool operator>=( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator<=( bit ); - } - - template <typename BitType> - VULKAN_HPP_CONSTEXPR bool operator==( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator==( bit ); - } - - template <typename BitType> - VULKAN_HPP_CONSTEXPR bool operator!=( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator!=( bit ); - } -#endif - - // bitwise operators - template <typename BitType> - VULKAN_HPP_CONSTEXPR Flags<BitType> operator&( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator&( bit ); - } - - template <typename BitType> - VULKAN_HPP_CONSTEXPR Flags<BitType> operator|( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator|( bit ); - } - - template <typename BitType> - VULKAN_HPP_CONSTEXPR Flags<BitType> operator^( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT - { - return flags.operator^( bit ); - } - - // bitwise operators on BitType - template <typename BitType, typename std::enable_if<FlagTraits<BitType>::isBitmask, bool>::type = true> - VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR Flags<BitType> operator&( BitType lhs, BitType rhs ) VULKAN_HPP_NOEXCEPT - { - return Flags<BitType>( lhs ) & rhs; - } - - template <typename BitType, typename std::enable_if<FlagTraits<BitType>::isBitmask, bool>::type = true> - VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR Flags<BitType> operator|( BitType lhs, BitType rhs ) VULKAN_HPP_NOEXCEPT - { - return Flags<BitType>( lhs ) | rhs; - } - - template <typename BitType, typename std::enable_if<FlagTraits<BitType>::isBitmask, bool>::type = true> - VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR Flags<BitType> operator^( BitType lhs, BitType rhs ) VULKAN_HPP_NOEXCEPT - { - return Flags<BitType>( lhs ) ^ rhs; - } - - template <typename BitType, typename std::enable_if<FlagTraits<BitType>::isBitmask, bool>::type = true> - VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR Flags<BitType> operator~( BitType bit ) VULKAN_HPP_NOEXCEPT - { - return ~( Flags<BitType>( bit ) ); - } - #if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) template <typename T> class ArrayProxy @@ -6093,6 +5711,36 @@ namespace VULKAN_HPP_NAMESPACE return ::vkGetDynamicRenderingTilePropertiesQCOM( device, pRenderingInfo, pProperties ); } + //=== VK_NV_low_latency2 === + + VkResult vkSetLatencySleepModeNV( VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepModeInfoNV * pSleepModeInfo ) const VULKAN_HPP_NOEXCEPT + { + return ::vkSetLatencySleepModeNV( device, swapchain, pSleepModeInfo ); + } + + VkResult vkLatencySleepNV( VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepInfoNV * pSleepInfo ) const VULKAN_HPP_NOEXCEPT + { + return ::vkLatencySleepNV( device, swapchain, pSleepInfo ); + } + + void vkSetLatencyMarkerNV( VkDevice device, VkSwapchainKHR swapchain, const VkSetLatencyMarkerInfoNV * pLatencyMarkerInfo ) const VULKAN_HPP_NOEXCEPT + { + return ::vkSetLatencyMarkerNV( device, swapchain, pLatencyMarkerInfo ); + } + + void vkGetLatencyTimingsNV( VkDevice device, + VkSwapchainKHR swapchain, + uint32_t * pTimingCount, + VkGetLatencyMarkerInfoNV * pLatencyMarkerInfo ) const VULKAN_HPP_NOEXCEPT + { + return ::vkGetLatencyTimingsNV( device, swapchain, pTimingCount, pLatencyMarkerInfo ); + } + + void vkQueueNotifyOutOfBandNV( VkQueue queue, const VkOutOfBandQueueTypeInfoNV * pQueueTypeInfo ) const VULKAN_HPP_NOEXCEPT + { + return ::vkQueueNotifyOutOfBandNV( queue, pQueueTypeInfo ); + } + //=== VK_KHR_cooperative_matrix === VkResult vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR( VkPhysicalDevice physicalDevice, @@ -6120,76 +5768,12 @@ namespace VULKAN_HPP_NAMESPACE } # endif /*VK_USE_PLATFORM_SCREEN_QNX*/ }; -#endif - - class DispatchLoaderDynamic; -#if !defined( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC ) -# if defined( VK_NO_PROTOTYPES ) -# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 -# else -# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 0 -# endif -#endif - -#if !defined( VULKAN_HPP_STORAGE_API ) -# if defined( VULKAN_HPP_STORAGE_SHARED ) -# if defined( _MSC_VER ) -# if defined( VULKAN_HPP_STORAGE_SHARED_EXPORT ) -# define VULKAN_HPP_STORAGE_API __declspec( dllexport ) -# else -# define VULKAN_HPP_STORAGE_API __declspec( dllimport ) -# endif -# elif defined( __clang__ ) || defined( __GNUC__ ) -# if defined( VULKAN_HPP_STORAGE_SHARED_EXPORT ) -# define VULKAN_HPP_STORAGE_API __attribute__( ( visibility( "default" ) ) ) -# else -# define VULKAN_HPP_STORAGE_API -# endif -# else -# define VULKAN_HPP_STORAGE_API -# pragma warning Unknown import / export semantics -# endif -# else -# define VULKAN_HPP_STORAGE_API -# endif -#endif -#if !defined( VULKAN_HPP_DEFAULT_DISPATCHER ) -# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 -# define VULKAN_HPP_DEFAULT_DISPATCHER ::VULKAN_HPP_NAMESPACE::defaultDispatchLoaderDynamic -# define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE \ - namespace VULKAN_HPP_NAMESPACE \ - { \ - VULKAN_HPP_STORAGE_API DispatchLoaderDynamic defaultDispatchLoaderDynamic; \ - } - extern VULKAN_HPP_STORAGE_API DispatchLoaderDynamic defaultDispatchLoaderDynamic; -# else inline ::VULKAN_HPP_NAMESPACE::DispatchLoaderStatic & getDispatchLoaderStatic() { static ::VULKAN_HPP_NAMESPACE::DispatchLoaderStatic dls; return dls; } -# define VULKAN_HPP_DEFAULT_DISPATCHER ::VULKAN_HPP_NAMESPACE::getDispatchLoaderStatic() -# define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE -# endif -#endif - -#if !defined( VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ) -# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 -# define VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ::VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic -# else -# define VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ::VULKAN_HPP_NAMESPACE::DispatchLoaderStatic -# endif -#endif - -#if defined( VULKAN_HPP_NO_DEFAULT_DISPATCHER ) -# define VULKAN_HPP_DEFAULT_ARGUMENT_ASSIGNMENT -# define VULKAN_HPP_DEFAULT_ARGUMENT_NULLPTR_ASSIGNMENT -# define VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT -#else -# define VULKAN_HPP_DEFAULT_ARGUMENT_ASSIGNMENT = {} -# define VULKAN_HPP_DEFAULT_ARGUMENT_NULLPTR_ASSIGNMENT = nullptr -# define VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT = VULKAN_HPP_DEFAULT_DISPATCHER #endif #if !defined( VULKAN_HPP_NO_SMART_HANDLE ) @@ -7034,40 +6618,40 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxDriverInfoSize = VK_MAX_DRIVER_INFO_SIZE; //=== VK_KHR_device_group_creation === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxDeviceGroupSizeKhr = VK_MAX_DEVICE_GROUP_SIZE_KHR; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxDeviceGroupSizeKHR = VK_MAX_DEVICE_GROUP_SIZE_KHR; //=== VK_KHR_external_memory_capabilities === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t LuidSizeKhr = VK_LUID_SIZE_KHR; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t LuidSizeKHR = VK_LUID_SIZE_KHR; //=== VK_KHR_external_memory === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t QueueFamilyExternalKhr = VK_QUEUE_FAMILY_EXTERNAL_KHR; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t QueueFamilyExternalKHR = VK_QUEUE_FAMILY_EXTERNAL_KHR; #if defined( VK_ENABLE_BETA_EXTENSIONS ) //=== VK_AMDX_shader_enqueue === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t ShaderIndexUnusedAmdx = VK_SHADER_INDEX_UNUSED_AMDX; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t ShaderIndexUnusedAMDX = VK_SHADER_INDEX_UNUSED_AMDX; #endif /*VK_ENABLE_BETA_EXTENSIONS*/ //=== VK_KHR_ray_tracing_pipeline === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t ShaderUnusedKhr = VK_SHADER_UNUSED_KHR; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t ShaderUnusedKHR = VK_SHADER_UNUSED_KHR; //=== VK_NV_ray_tracing === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t ShaderUnusedNv = VK_SHADER_UNUSED_NV; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t ShaderUnusedNV = VK_SHADER_UNUSED_NV; //=== VK_KHR_global_priority === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxGlobalPrioritySizeKhr = VK_MAX_GLOBAL_PRIORITY_SIZE_KHR; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxGlobalPrioritySizeKHR = VK_MAX_GLOBAL_PRIORITY_SIZE_KHR; //=== VK_KHR_driver_properties === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxDriverNameSizeKhr = VK_MAX_DRIVER_NAME_SIZE_KHR; - VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxDriverInfoSizeKhr = VK_MAX_DRIVER_INFO_SIZE_KHR; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxDriverNameSizeKHR = VK_MAX_DRIVER_NAME_SIZE_KHR; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxDriverInfoSizeKHR = VK_MAX_DRIVER_INFO_SIZE_KHR; //=== VK_EXT_global_priority_query === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxGlobalPrioritySizeExt = VK_MAX_GLOBAL_PRIORITY_SIZE_EXT; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxGlobalPrioritySizeEXT = VK_MAX_GLOBAL_PRIORITY_SIZE_EXT; //=== VK_EXT_image_sliced_view_of_3d === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t Remaining3DSlicesExt = VK_REMAINING_3D_SLICES_EXT; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t Remaining3DSlicesEXT = VK_REMAINING_3D_SLICES_EXT; //=== VK_EXT_shader_module_identifier === - VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxShaderModuleIdentifierSizeExt = VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT; + VULKAN_HPP_CONSTEXPR_INLINE uint32_t MaxShaderModuleIdentifierSizeEXT = VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT; //======================== //=== CONSTEXPR VALUEs === @@ -9508,6 +9092,30 @@ namespace VULKAN_HPP_NAMESPACE }; }; template <> + struct StructExtends<ExternalFormatANDROID, AttachmentDescription2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<ExternalFormatANDROID, GraphicsPipelineCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<ExternalFormatANDROID, CommandBufferInheritanceInfo> + { + enum + { + value = true + }; + }; + template <> struct StructExtends<AndroidHardwareBufferFormatProperties2ANDROID, AndroidHardwareBufferPropertiesANDROID> { enum @@ -12249,6 +11857,56 @@ namespace VULKAN_HPP_NAMESPACE }; }; + //=== VK_EXT_frame_boundary === + template <> + struct StructExtends<PhysicalDeviceFrameBoundaryFeaturesEXT, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceFrameBoundaryFeaturesEXT, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<FrameBoundaryEXT, SubmitInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<FrameBoundaryEXT, SubmitInfo2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<FrameBoundaryEXT, PresentInfoKHR> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<FrameBoundaryEXT, BindSparseInfo> + { + enum + { + value = true + }; + }; + //=== VK_EXT_multisampled_render_to_single_sampled === template <> struct StructExtends<PhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT, PhysicalDeviceFeatures2> @@ -12871,6 +12529,32 @@ namespace VULKAN_HPP_NAMESPACE }; }; + //=== VK_EXT_nested_command_buffer === + template <> + struct StructExtends<PhysicalDeviceNestedCommandBufferFeaturesEXT, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceNestedCommandBufferFeaturesEXT, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceNestedCommandBufferPropertiesEXT, PhysicalDeviceProperties2> + { + enum + { + value = true + }; + }; + //=== VK_EXT_external_memory_acquire_unmodified === template <> struct StructExtends<ExternalMemoryAcquireUnmodifiedEXT, BufferMemoryBarrier> @@ -13129,6 +12813,42 @@ namespace VULKAN_HPP_NAMESPACE }; }; +# if defined( VK_USE_PLATFORM_ANDROID_KHR ) + //=== VK_ANDROID_external_format_resolve === + template <> + struct StructExtends<PhysicalDeviceExternalFormatResolveFeaturesANDROID, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceExternalFormatResolveFeaturesANDROID, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceExternalFormatResolvePropertiesANDROID, PhysicalDeviceProperties2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<AndroidHardwareBufferFormatResolvePropertiesANDROID, AndroidHardwareBufferPropertiesANDROID> + { + enum + { + value = true + }; + }; +# endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + //=== VK_KHR_maintenance5 === template <> struct StructExtends<PhysicalDeviceMaintenance5FeaturesKHR, PhysicalDeviceFeatures2> @@ -13351,6 +13071,32 @@ namespace VULKAN_HPP_NAMESPACE }; }; + //=== VK_NV_extended_sparse_address_space === + template <> + struct StructExtends<PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceExtendedSparseAddressSpacePropertiesNV, PhysicalDeviceProperties2> + { + enum + { + value = true + }; + }; + //=== VK_EXT_mutable_descriptor_type === template <> struct StructExtends<PhysicalDeviceMutableDescriptorTypeFeaturesEXT, PhysicalDeviceFeatures2> @@ -13447,6 +13193,40 @@ namespace VULKAN_HPP_NAMESPACE }; }; + //=== VK_NV_low_latency2 === + template <> + struct StructExtends<LatencySubmissionPresentIdNV, SubmitInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<LatencySubmissionPresentIdNV, SubmitInfo2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<SwapchainLatencyCreateInfoNV, SwapchainCreateInfoKHR> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<LatencySurfaceCapabilitiesNV, SurfaceCapabilities2KHR> + { + enum + { + value = true + }; + }; + //=== VK_KHR_cooperative_matrix === template <> struct StructExtends<PhysicalDeviceCooperativeMatrixFeaturesKHR, PhysicalDeviceFeatures2> @@ -13507,6 +13287,118 @@ namespace VULKAN_HPP_NAMESPACE }; }; + //=== VK_QCOM_image_processing2 === + template <> + struct StructExtends<PhysicalDeviceImageProcessing2FeaturesQCOM, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceImageProcessing2FeaturesQCOM, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceImageProcessing2PropertiesQCOM, PhysicalDeviceProperties2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<SamplerBlockMatchWindowCreateInfoQCOM, SamplerCreateInfo> + { + enum + { + value = true + }; + }; + + //=== VK_QCOM_filter_cubic_weights === + template <> + struct StructExtends<PhysicalDeviceCubicWeightsFeaturesQCOM, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceCubicWeightsFeaturesQCOM, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<SamplerCubicWeightsCreateInfoQCOM, SamplerCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<BlitImageCubicWeightsInfoQCOM, BlitImageInfo2> + { + enum + { + value = true + }; + }; + + //=== VK_QCOM_ycbcr_degamma === + template <> + struct StructExtends<PhysicalDeviceYcbcrDegammaFeaturesQCOM, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceYcbcrDegammaFeaturesQCOM, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM, SamplerYcbcrConversionCreateInfo> + { + enum + { + value = true + }; + }; + + //=== VK_QCOM_filter_cubic_clamp === + template <> + struct StructExtends<PhysicalDeviceCubicClampFeaturesQCOM, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceCubicClampFeaturesQCOM, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + //=== VK_EXT_attachment_feedback_loop_dynamic_state === template <> struct StructExtends<PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT, PhysicalDeviceFeatures2> @@ -13577,6 +13469,34 @@ namespace VULKAN_HPP_NAMESPACE }; # endif /*VK_USE_PLATFORM_SCREEN_QNX*/ + //=== VK_MSFT_layered_driver === + template <> + struct StructExtends<PhysicalDeviceLayeredDriverPropertiesMSFT, PhysicalDeviceProperties2> + { + enum + { + value = true + }; + }; + + //=== VK_NV_descriptor_pool_overallocation === + template <> + struct StructExtends<PhysicalDeviceDescriptorPoolOverallocationFeaturesNV, PhysicalDeviceFeatures2> + { + enum + { + value = true + }; + }; + template <> + struct StructExtends<PhysicalDeviceDescriptorPoolOverallocationFeaturesNV, DeviceCreateInfo> + { + enum + { + value = true + }; + }; + #endif // VULKAN_HPP_DISABLE_ENHANCED_MODE #if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL @@ -13591,7 +13511,7 @@ namespace VULKAN_HPP_NAMESPACE { if ( !vulkanLibraryName.empty() ) { -# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNXNTO__ ) || defined( __Fuchsia__ ) +# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNX__ ) || defined( __Fuchsia__ ) m_library = dlopen( vulkanLibraryName.c_str(), RTLD_NOW | RTLD_LOCAL ); # elif defined( _WIN32 ) m_library = ::LoadLibraryA( vulkanLibraryName.c_str() ); @@ -13601,7 +13521,7 @@ namespace VULKAN_HPP_NAMESPACE } else { -# if defined( __unix__ ) || defined( __QNXNTO__ ) || defined( __Fuchsia__ ) +# if defined( __unix__ ) || defined( __QNX__ ) || defined( __Fuchsia__ ) m_library = dlopen( "libvulkan.so", RTLD_NOW | RTLD_LOCAL ); if ( m_library == nullptr ) { @@ -13644,7 +13564,7 @@ namespace VULKAN_HPP_NAMESPACE { if ( m_library ) { -# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNXNTO__ ) || defined( __Fuchsia__ ) +# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNX__ ) || defined( __Fuchsia__ ) dlclose( m_library ); # elif defined( _WIN32 ) ::FreeLibrary( m_library ); @@ -13657,7 +13577,7 @@ namespace VULKAN_HPP_NAMESPACE template <typename T> T getProcAddress( const char * function ) const VULKAN_HPP_NOEXCEPT { -# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNXNTO__ ) || defined( __Fuchsia__ ) +# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNX__ ) || defined( __Fuchsia__ ) return (T)dlsym( m_library, function ); # elif defined( _WIN32 ) return ( T )::GetProcAddress( m_library, function ); @@ -13672,7 +13592,7 @@ namespace VULKAN_HPP_NAMESPACE } private: -# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNXNTO__ ) || defined( __Fuchsia__ ) +# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNX__ ) || defined( __Fuchsia__ ) void * m_library; # elif defined( _WIN32 ) ::HINSTANCE m_library; @@ -14763,6 +14683,13 @@ namespace VULKAN_HPP_NAMESPACE PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM = 0; PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM = 0; + //=== VK_NV_low_latency2 === + PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV = 0; + PFN_vkLatencySleepNV vkLatencySleepNV = 0; + PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV = 0; + PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV = 0; + PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV = 0; + //=== VK_KHR_cooperative_matrix === PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR = 0; @@ -14785,6 +14712,33 @@ namespace VULKAN_HPP_NAMESPACE init( getInstanceProcAddr ); } + // This interface does not require a linked vulkan library. + DispatchLoaderDynamic( VkInstance instance, + PFN_vkGetInstanceProcAddr getInstanceProcAddr, + VkDevice device = {}, + PFN_vkGetDeviceProcAddr getDeviceProcAddr = nullptr ) VULKAN_HPP_NOEXCEPT + { + init( instance, getInstanceProcAddr, device, getDeviceProcAddr ); + } + + template <typename DynamicLoader +#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL + = VULKAN_HPP_NAMESPACE::DynamicLoader +#endif + > + void init() + { + static DynamicLoader dl; + init( dl ); + } + + template <typename DynamicLoader> + void init( DynamicLoader const & dl ) VULKAN_HPP_NOEXCEPT + { + PFN_vkGetInstanceProcAddr getInstanceProcAddr = dl.template getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" ); + init( getInstanceProcAddr ); + } + void init( PFN_vkGetInstanceProcAddr getInstanceProcAddr ) VULKAN_HPP_NOEXCEPT { VULKAN_HPP_ASSERT( getInstanceProcAddr ); @@ -14802,15 +14756,6 @@ namespace VULKAN_HPP_NAMESPACE } // This interface does not require a linked vulkan library. - DispatchLoaderDynamic( VkInstance instance, - PFN_vkGetInstanceProcAddr getInstanceProcAddr, - VkDevice device = {}, - PFN_vkGetDeviceProcAddr getDeviceProcAddr = nullptr ) VULKAN_HPP_NOEXCEPT - { - init( instance, getInstanceProcAddr, device, getDeviceProcAddr ); - } - - // This interface does not require a linked vulkan library. void init( VkInstance instance, PFN_vkGetInstanceProcAddr getInstanceProcAddr, VkDevice device = {}, @@ -16106,6 +16051,13 @@ namespace VULKAN_HPP_NAMESPACE vkGetDynamicRenderingTilePropertiesQCOM = PFN_vkGetDynamicRenderingTilePropertiesQCOM( vkGetInstanceProcAddr( instance, "vkGetDynamicRenderingTilePropertiesQCOM" ) ); + //=== VK_NV_low_latency2 === + vkSetLatencySleepModeNV = PFN_vkSetLatencySleepModeNV( vkGetInstanceProcAddr( instance, "vkSetLatencySleepModeNV" ) ); + vkLatencySleepNV = PFN_vkLatencySleepNV( vkGetInstanceProcAddr( instance, "vkLatencySleepNV" ) ); + vkSetLatencyMarkerNV = PFN_vkSetLatencyMarkerNV( vkGetInstanceProcAddr( instance, "vkSetLatencyMarkerNV" ) ); + vkGetLatencyTimingsNV = PFN_vkGetLatencyTimingsNV( vkGetInstanceProcAddr( instance, "vkGetLatencyTimingsNV" ) ); + vkQueueNotifyOutOfBandNV = PFN_vkQueueNotifyOutOfBandNV( vkGetInstanceProcAddr( instance, "vkQueueNotifyOutOfBandNV" ) ); + //=== VK_KHR_cooperative_matrix === vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR = PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR" ) ); @@ -17113,6 +17065,13 @@ namespace VULKAN_HPP_NAMESPACE vkGetDynamicRenderingTilePropertiesQCOM = PFN_vkGetDynamicRenderingTilePropertiesQCOM( vkGetDeviceProcAddr( device, "vkGetDynamicRenderingTilePropertiesQCOM" ) ); + //=== VK_NV_low_latency2 === + vkSetLatencySleepModeNV = PFN_vkSetLatencySleepModeNV( vkGetDeviceProcAddr( device, "vkSetLatencySleepModeNV" ) ); + vkLatencySleepNV = PFN_vkLatencySleepNV( vkGetDeviceProcAddr( device, "vkLatencySleepNV" ) ); + vkSetLatencyMarkerNV = PFN_vkSetLatencyMarkerNV( vkGetDeviceProcAddr( device, "vkSetLatencyMarkerNV" ) ); + vkGetLatencyTimingsNV = PFN_vkGetLatencyTimingsNV( vkGetDeviceProcAddr( device, "vkGetLatencyTimingsNV" ) ); + vkQueueNotifyOutOfBandNV = PFN_vkQueueNotifyOutOfBandNV( vkGetDeviceProcAddr( device, "vkQueueNotifyOutOfBandNV" ) ); + //=== VK_EXT_attachment_feedback_loop_dynamic_state === vkCmdSetAttachmentFeedbackLoopEnableEXT = PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT( vkGetDeviceProcAddr( device, "vkCmdSetAttachmentFeedbackLoopEnableEXT" ) ); diff --git a/thirdparty/vulkan/include/vulkan/vulkan_android.h b/thirdparty/vulkan/include/vulkan/vulkan_android.h index d86f43f2d2..40b3c67ba6 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_android.h +++ b/thirdparty/vulkan/include/vulkan/vulkan_android.h @@ -120,6 +120,32 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID( struct AHardwareBuffer** pBuffer); #endif + +// VK_ANDROID_external_format_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_ANDROID_external_format_resolve 1 +#define VK_ANDROID_EXTERNAL_FORMAT_RESOLVE_SPEC_VERSION 1 +#define VK_ANDROID_EXTERNAL_FORMAT_RESOLVE_EXTENSION_NAME "VK_ANDROID_external_format_resolve" +typedef struct VkPhysicalDeviceExternalFormatResolveFeaturesANDROID { + VkStructureType sType; + void* pNext; + VkBool32 externalFormatResolve; +} VkPhysicalDeviceExternalFormatResolveFeaturesANDROID; + +typedef struct VkPhysicalDeviceExternalFormatResolvePropertiesANDROID { + VkStructureType sType; + void* pNext; + VkBool32 nullColorAttachmentWithExternalFormatResolve; + VkChromaLocation externalFormatResolveChromaOffsetX; + VkChromaLocation externalFormatResolveChromaOffsetY; +} VkPhysicalDeviceExternalFormatResolvePropertiesANDROID; + +typedef struct VkAndroidHardwareBufferFormatResolvePropertiesANDROID { + VkStructureType sType; + void* pNext; + VkFormat colorAttachmentFormat; +} VkAndroidHardwareBufferFormatResolvePropertiesANDROID; + + #ifdef __cplusplus } #endif diff --git a/thirdparty/vulkan/include/vulkan/vulkan_beta.h b/thirdparty/vulkan/include/vulkan/vulkan_beta.h index f00ed3ff1f..1871651d26 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_beta.h +++ b/thirdparty/vulkan/include/vulkan/vulkan_beta.h @@ -53,7 +53,7 @@ typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { // VK_KHR_video_encode_queue is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_video_encode_queue 1 -#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 9 +#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 10 #define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue" typedef enum VkVideoEncodeTuningModeKHR { @@ -68,6 +68,7 @@ typedef VkFlags VkVideoEncodeFlagsKHR; typedef enum VkVideoEncodeCapabilityFlagBitsKHR { VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_CAPABILITY_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_DETECTION_BIT_KHR = 0x00000002, VK_VIDEO_ENCODE_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoEncodeCapabilityFlagBitsKHR; typedef VkFlags VkVideoEncodeCapabilityFlagsKHR; @@ -227,7 +228,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR( #define VK_EXT_video_encode_h264 1 #include "vk_video/vulkan_video_codec_h264std.h" #include "vk_video/vulkan_video_codec_h264std_encode.h" -#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 11 +#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 12 #define VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_EXT_video_encode_h264" typedef enum VkVideoEncodeH264CapabilityFlagBitsEXT { @@ -263,6 +264,8 @@ typedef enum VkVideoEncodeH264StdFlagBitsEXT { VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0x00008000, VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0x00010000, VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0x00020000, + VK_VIDEO_ENCODE_H264_STD_SLICE_QP_DELTA_BIT_EXT = 0x00080000, + VK_VIDEO_ENCODE_H264_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT = 0x00100000, VK_VIDEO_ENCODE_H264_STD_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkVideoEncodeH264StdFlagBitsEXT; typedef VkFlags VkVideoEncodeH264StdFlagsEXT; @@ -424,7 +427,7 @@ typedef struct VkVideoEncodeH264GopRemainingFrameInfoEXT { #define VK_EXT_video_encode_h265 1 #include "vk_video/vulkan_video_codec_h265std.h" #include "vk_video/vulkan_video_codec_h265std_encode.h" -#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 11 +#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 12 #define VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_EXT_video_encode_h265" typedef enum VkVideoEncodeH265CapabilityFlagBitsEXT { @@ -462,6 +465,8 @@ typedef enum VkVideoEncodeH265StdFlagBitsEXT { VK_VIDEO_ENCODE_H265_STD_DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_SET_BIT_EXT = 0x00010000, VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_EXT = 0x00020000, VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_EXT = 0x00040000, + VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_EXT = 0x00080000, + VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT = 0x00100000, VK_VIDEO_ENCODE_H265_STD_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkVideoEncodeH265StdFlagBitsEXT; typedef VkFlags VkVideoEncodeH265StdFlagsEXT; diff --git a/thirdparty/vulkan/include/vulkan/vulkan_core.h b/thirdparty/vulkan/include/vulkan/vulkan_core.h index c574858134..77bdf09412 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_core.h +++ b/thirdparty/vulkan/include/vulkan/vulkan_core.h @@ -27,7 +27,7 @@ extern "C" { #ifndef VK_USE_64_BIT_PTR_DEFINES - #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64) #define VK_USE_64_BIT_PTR_DEFINES 1 #else #define VK_USE_64_BIT_PTR_DEFINES 0 @@ -69,7 +69,7 @@ extern "C" { #define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 261 +#define VK_HEADER_VERSION 268 // Complete version of this file #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 3, VK_HEADER_VERSION) @@ -992,6 +992,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001, VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT = 1000372000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT = 1000372001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT = 1000375000, + VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT = 1000375001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT = 1000376000, VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT = 1000376001, VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT = 1000376002, @@ -1055,6 +1057,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM = 1000440000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM = 1000440001, VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT = 1000451000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT = 1000451001, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT = 1000453000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001, @@ -1078,6 +1082,9 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = 1000466000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID = 1000468000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468001, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = 1000470000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = 1000470001, VK_STRUCTURE_TYPE_RENDERING_AREA_INFO_KHR = 1000470003, @@ -1097,23 +1104,45 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV = 1000490000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV = 1000490001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV = 1000492000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV = 1000492001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT = 1000351000, VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT = 1000499000, + VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV = 1000505000, + VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV = 1000505001, + VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV = 1000505002, + VK_STRUCTURE_TYPE_GET_LATENCY_MARKER_INFO_NV = 1000505003, + VK_STRUCTURE_TYPE_LATENCY_TIMINGS_FRAME_REPORT_NV = 1000505004, + VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV = 1000505005, + VK_STRUCTURE_TYPE_OUT_OF_BAND_QUEUE_TYPE_INFO_NV = 1000505006, + VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV = 1000505007, + VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV = 1000505008, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR = 1000506000, VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000, VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM = 1000518000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM = 1000518001, + VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM = 1000518002, + VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM = 1000519000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM = 1000519001, + VK_STRUCTURE_TYPE_BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM = 1000519002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM = 1000520000, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM = 1000520001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM = 1000521000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT = 1000524000, VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX = 1000529000, VK_STRUCTURE_TYPE_SCREEN_BUFFER_FORMAT_PROPERTIES_QNX = 1000529001, VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX = 1000529002, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_QNX = 1000529003, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX = 1000529004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT = 1000530000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV = 1000546000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, @@ -2163,6 +2192,7 @@ typedef enum VkIndexType { typedef enum VkSubpassContents { VK_SUBPASS_CONTENTS_INLINE = 0, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, + VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT = 1000451000, VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF } VkSubpassContents; @@ -2714,6 +2744,8 @@ typedef enum VkDescriptorPoolCreateFlagBits { VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002, VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT = 0x00000004, + VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV = 0x00000008, + VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV = 0x00000010, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT, VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -5784,6 +5816,7 @@ typedef enum VkDriverId { VK_DRIVER_ID_MESA_DOZEN = 23, VK_DRIVER_ID_MESA_NVK = 24, VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA = 25, + VK_DRIVER_ID_MESA_AGXV = 26, VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, @@ -5813,6 +5846,7 @@ typedef enum VkSamplerReductionMode { VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0, VK_SAMPLER_REDUCTION_MODE_MIN = 1, VK_SAMPLER_REDUCTION_MODE_MAX = 2, + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM = 1000521000, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, VK_SAMPLER_REDUCTION_MODE_MIN_EXT = VK_SAMPLER_REDUCTION_MODE_MIN, VK_SAMPLER_REDUCTION_MODE_MAX_EXT = VK_SAMPLER_REDUCTION_MODE_MAX, @@ -5833,6 +5867,7 @@ typedef enum VkResolveModeFlagBits { VK_RESOLVE_MODE_AVERAGE_BIT = 0x00000002, VK_RESOLVE_MODE_MIN_BIT = 0x00000004, VK_RESOLVE_MODE_MAX_BIT = 0x00000008, + VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID = 0x00000010, VK_RESOLVE_MODE_NONE_KHR = VK_RESOLVE_MODE_NONE, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, VK_RESOLVE_MODE_AVERAGE_BIT_KHR = VK_RESOLVE_MODE_AVERAGE_BIT, @@ -6711,6 +6746,7 @@ typedef enum VkRenderingFlagBits { VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 0x00000001, VK_RENDERING_SUSPENDING_BIT = 0x00000002, VK_RENDERING_RESUMING_BIT = 0x00000004, + VK_RENDERING_CONTENTS_INLINE_BIT_EXT = 0x00000010, VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x00000008, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, VK_RENDERING_SUSPENDING_BIT_KHR = VK_RENDERING_SUSPENDING_BIT, @@ -7992,6 +8028,7 @@ typedef enum VkQueryResultStatusKHR { VK_QUERY_RESULT_STATUS_ERROR_KHR = -1, VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0, VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1, + VK_QUERY_RESULT_STATUS_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_KHR = -1000299000, VK_QUERY_RESULT_STATUS_MAX_ENUM_KHR = 0x7FFFFFFF } VkQueryResultStatusKHR; @@ -15816,6 +15853,38 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelinePropertiesEXT( #endif +// VK_EXT_frame_boundary is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_frame_boundary 1 +#define VK_EXT_FRAME_BOUNDARY_SPEC_VERSION 1 +#define VK_EXT_FRAME_BOUNDARY_EXTENSION_NAME "VK_EXT_frame_boundary" + +typedef enum VkFrameBoundaryFlagBitsEXT { + VK_FRAME_BOUNDARY_FRAME_END_BIT_EXT = 0x00000001, + VK_FRAME_BOUNDARY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkFrameBoundaryFlagBitsEXT; +typedef VkFlags VkFrameBoundaryFlagsEXT; +typedef struct VkPhysicalDeviceFrameBoundaryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 frameBoundary; +} VkPhysicalDeviceFrameBoundaryFeaturesEXT; + +typedef struct VkFrameBoundaryEXT { + VkStructureType sType; + const void* pNext; + VkFrameBoundaryFlagsEXT flags; + uint64_t frameID; + uint32_t imageCount; + const VkImage* pImages; + uint32_t bufferCount; + const VkBuffer* pBuffers; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkFrameBoundaryEXT; + + + // VK_EXT_multisampled_render_to_single_sampled is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_multisampled_render_to_single_sampled 1 #define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION 1 @@ -16728,6 +16797,26 @@ typedef struct VkPhysicalDeviceImageProcessingPropertiesQCOM { +// VK_EXT_nested_command_buffer is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_nested_command_buffer 1 +#define VK_EXT_NESTED_COMMAND_BUFFER_SPEC_VERSION 1 +#define VK_EXT_NESTED_COMMAND_BUFFER_EXTENSION_NAME "VK_EXT_nested_command_buffer" +typedef struct VkPhysicalDeviceNestedCommandBufferFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 nestedCommandBuffer; + VkBool32 nestedCommandBufferRendering; + VkBool32 nestedCommandBufferSimultaneousUse; +} VkPhysicalDeviceNestedCommandBufferFeaturesEXT; + +typedef struct VkPhysicalDeviceNestedCommandBufferPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxCommandBufferNestingLevel; +} VkPhysicalDeviceNestedCommandBufferPropertiesEXT; + + + // VK_EXT_external_memory_acquire_unmodified is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_external_memory_acquire_unmodified 1 #define VK_EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_SPEC_VERSION 1 @@ -17482,6 +17571,26 @@ typedef struct VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV { +// VK_NV_extended_sparse_address_space is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_extended_sparse_address_space 1 +#define VK_NV_EXTENDED_SPARSE_ADDRESS_SPACE_SPEC_VERSION 1 +#define VK_NV_EXTENDED_SPARSE_ADDRESS_SPACE_EXTENSION_NAME "VK_NV_extended_sparse_address_space" +typedef struct VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 extendedSparseAddressSpace; +} VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + +typedef struct VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV { + VkStructureType sType; + void* pNext; + VkDeviceSize extendedSparseAddressSpaceSize; + VkImageUsageFlags extendedSparseImageUsageFlags; + VkBufferUsageFlags extendedSparseBufferUsageFlags; +} VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + + + // VK_EXT_mutable_descriptor_type is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_mutable_descriptor_type 1 #define VK_EXT_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 @@ -17532,6 +17641,138 @@ typedef struct VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { +// VK_NV_low_latency2 is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_low_latency2 1 +#define VK_NV_LOW_LATENCY_2_SPEC_VERSION 1 +#define VK_NV_LOW_LATENCY_2_EXTENSION_NAME "VK_NV_low_latency2" + +typedef enum VkLatencyMarkerNV { + VK_LATENCY_MARKER_SIMULATION_START_NV = 0, + VK_LATENCY_MARKER_SIMULATION_END_NV = 1, + VK_LATENCY_MARKER_RENDERSUBMIT_START_NV = 2, + VK_LATENCY_MARKER_RENDERSUBMIT_END_NV = 3, + VK_LATENCY_MARKER_PRESENT_START_NV = 4, + VK_LATENCY_MARKER_PRESENT_END_NV = 5, + VK_LATENCY_MARKER_INPUT_SAMPLE_NV = 6, + VK_LATENCY_MARKER_TRIGGER_FLASH_NV = 7, + VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_START_NV = 8, + VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_END_NV = 9, + VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_START_NV = 10, + VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_END_NV = 11, + VK_LATENCY_MARKER_MAX_ENUM_NV = 0x7FFFFFFF +} VkLatencyMarkerNV; + +typedef enum VkOutOfBandQueueTypeNV { + VK_OUT_OF_BAND_QUEUE_TYPE_RENDER_NV = 0, + VK_OUT_OF_BAND_QUEUE_TYPE_PRESENT_NV = 1, + VK_OUT_OF_BAND_QUEUE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkOutOfBandQueueTypeNV; +typedef struct VkLatencySleepModeInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 lowLatencyMode; + VkBool32 lowLatencyBoost; + uint32_t minimumIntervalUs; +} VkLatencySleepModeInfoNV; + +typedef struct VkLatencySleepInfoNV { + VkStructureType sType; + const void* pNext; + VkSemaphore signalSemaphore; + uint64_t value; +} VkLatencySleepInfoNV; + +typedef struct VkSetLatencyMarkerInfoNV { + VkStructureType sType; + const void* pNext; + uint64_t presentID; + VkLatencyMarkerNV marker; +} VkSetLatencyMarkerInfoNV; + +typedef struct VkLatencyTimingsFrameReportNV { + VkStructureType sType; + const void* pNext; + uint64_t presentID; + uint64_t inputSampleTimeUs; + uint64_t simStartTimeUs; + uint64_t simEndTimeUs; + uint64_t renderSubmitStartTimeUs; + uint64_t renderSubmitEndTimeUs; + uint64_t presentStartTimeUs; + uint64_t presentEndTimeUs; + uint64_t driverStartTimeUs; + uint64_t driverEndTimeUs; + uint64_t osRenderQueueStartTimeUs; + uint64_t osRenderQueueEndTimeUs; + uint64_t gpuRenderStartTimeUs; + uint64_t gpuRenderEndTimeUs; +} VkLatencyTimingsFrameReportNV; + +typedef struct VkGetLatencyMarkerInfoNV { + VkStructureType sType; + const void* pNext; + VkLatencyTimingsFrameReportNV* pTimings; +} VkGetLatencyMarkerInfoNV; + +typedef struct VkLatencySubmissionPresentIdNV { + VkStructureType sType; + const void* pNext; + uint64_t presentID; +} VkLatencySubmissionPresentIdNV; + +typedef struct VkSwapchainLatencyCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 latencyModeEnable; +} VkSwapchainLatencyCreateInfoNV; + +typedef struct VkOutOfBandQueueTypeInfoNV { + VkStructureType sType; + const void* pNext; + VkOutOfBandQueueTypeNV queueType; +} VkOutOfBandQueueTypeInfoNV; + +typedef struct VkLatencySurfaceCapabilitiesNV { + VkStructureType sType; + const void* pNext; + uint32_t presentModeCount; + VkPresentModeKHR* pPresentModes; +} VkLatencySurfaceCapabilitiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkSetLatencySleepModeNV)(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepModeInfoNV* pSleepModeInfo); +typedef VkResult (VKAPI_PTR *PFN_vkLatencySleepNV)(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepInfoNV* pSleepInfo); +typedef void (VKAPI_PTR *PFN_vkSetLatencyMarkerNV)(VkDevice device, VkSwapchainKHR swapchain, const VkSetLatencyMarkerInfoNV* pLatencyMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkGetLatencyTimingsNV)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pTimingCount, VkGetLatencyMarkerInfoNV* pLatencyMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkQueueNotifyOutOfBandNV)(VkQueue queue, const VkOutOfBandQueueTypeInfoNV* pQueueTypeInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetLatencySleepModeNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkLatencySleepModeInfoNV* pSleepModeInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkLatencySleepNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkLatencySleepInfoNV* pSleepInfo); + +VKAPI_ATTR void VKAPI_CALL vkSetLatencyMarkerNV( + VkDevice device, + VkSwapchainKHR swapchain, + const VkSetLatencyMarkerInfoNV* pLatencyMarkerInfo); + +VKAPI_ATTR void VKAPI_CALL vkGetLatencyTimingsNV( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pTimingCount, + VkGetLatencyMarkerInfoNV* pLatencyMarkerInfo); + +VKAPI_ATTR void VKAPI_CALL vkQueueNotifyOutOfBandNV( + VkQueue queue, + const VkOutOfBandQueueTypeInfoNV* pQueueTypeInfo); +#endif + + // VK_QCOM_multiview_per_view_render_areas is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_multiview_per_view_render_areas 1 #define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_SPEC_VERSION 1 @@ -17551,6 +17792,100 @@ typedef struct VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { +// VK_QCOM_image_processing2 is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_image_processing2 1 +#define VK_QCOM_IMAGE_PROCESSING_2_SPEC_VERSION 1 +#define VK_QCOM_IMAGE_PROCESSING_2_EXTENSION_NAME "VK_QCOM_image_processing2" + +typedef enum VkBlockMatchWindowCompareModeQCOM { + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MIN_QCOM = 0, + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_QCOM = 1, + VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkBlockMatchWindowCompareModeQCOM; +typedef struct VkPhysicalDeviceImageProcessing2FeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 textureBlockMatch2; +} VkPhysicalDeviceImageProcessing2FeaturesQCOM; + +typedef struct VkPhysicalDeviceImageProcessing2PropertiesQCOM { + VkStructureType sType; + void* pNext; + VkExtent2D maxBlockMatchWindow; +} VkPhysicalDeviceImageProcessing2PropertiesQCOM; + +typedef struct VkSamplerBlockMatchWindowCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkExtent2D windowExtent; + VkBlockMatchWindowCompareModeQCOM windowCompareMode; +} VkSamplerBlockMatchWindowCreateInfoQCOM; + + + +// VK_QCOM_filter_cubic_weights is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_filter_cubic_weights 1 +#define VK_QCOM_FILTER_CUBIC_WEIGHTS_SPEC_VERSION 1 +#define VK_QCOM_FILTER_CUBIC_WEIGHTS_EXTENSION_NAME "VK_QCOM_filter_cubic_weights" + +typedef enum VkCubicFilterWeightsQCOM { + VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM = 0, + VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM = 1, + VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM = 2, + VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM = 3, + VK_CUBIC_FILTER_WEIGHTS_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkCubicFilterWeightsQCOM; +typedef struct VkPhysicalDeviceCubicWeightsFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 selectableCubicWeights; +} VkPhysicalDeviceCubicWeightsFeaturesQCOM; + +typedef struct VkSamplerCubicWeightsCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkCubicFilterWeightsQCOM cubicWeights; +} VkSamplerCubicWeightsCreateInfoQCOM; + +typedef struct VkBlitImageCubicWeightsInfoQCOM { + VkStructureType sType; + const void* pNext; + VkCubicFilterWeightsQCOM cubicWeights; +} VkBlitImageCubicWeightsInfoQCOM; + + + +// VK_QCOM_ycbcr_degamma is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_ycbcr_degamma 1 +#define VK_QCOM_YCBCR_DEGAMMA_SPEC_VERSION 1 +#define VK_QCOM_YCBCR_DEGAMMA_EXTENSION_NAME "VK_QCOM_ycbcr_degamma" +typedef struct VkPhysicalDeviceYcbcrDegammaFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 ycbcrDegamma; +} VkPhysicalDeviceYcbcrDegammaFeaturesQCOM; + +typedef struct VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM { + VkStructureType sType; + void* pNext; + VkBool32 enableYDegamma; + VkBool32 enableCbCrDegamma; +} VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; + + + +// VK_QCOM_filter_cubic_clamp is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_filter_cubic_clamp 1 +#define VK_QCOM_FILTER_CUBIC_CLAMP_SPEC_VERSION 1 +#define VK_QCOM_FILTER_CUBIC_CLAMP_EXTENSION_NAME "VK_QCOM_filter_cubic_clamp" +typedef struct VkPhysicalDeviceCubicClampFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 cubicRangeClamp; +} VkPhysicalDeviceCubicClampFeaturesQCOM; + + + // VK_EXT_attachment_feedback_loop_dynamic_state is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_attachment_feedback_loop_dynamic_state 1 #define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_SPEC_VERSION 1 @@ -17570,6 +17905,36 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetAttachmentFeedbackLoopEnableEXT( #endif +// VK_MSFT_layered_driver is a preprocessor guard. Do not pass it to API calls. +#define VK_MSFT_layered_driver 1 +#define VK_MSFT_LAYERED_DRIVER_SPEC_VERSION 1 +#define VK_MSFT_LAYERED_DRIVER_EXTENSION_NAME "VK_MSFT_layered_driver" + +typedef enum VkLayeredDriverUnderlyingApiMSFT { + VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT = 0, + VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT = 1, + VK_LAYERED_DRIVER_UNDERLYING_API_MAX_ENUM_MSFT = 0x7FFFFFFF +} VkLayeredDriverUnderlyingApiMSFT; +typedef struct VkPhysicalDeviceLayeredDriverPropertiesMSFT { + VkStructureType sType; + void* pNext; + VkLayeredDriverUnderlyingApiMSFT underlyingAPI; +} VkPhysicalDeviceLayeredDriverPropertiesMSFT; + + + +// VK_NV_descriptor_pool_overallocation is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_descriptor_pool_overallocation 1 +#define VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_SPEC_VERSION 1 +#define VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME "VK_NV_descriptor_pool_overallocation" +typedef struct VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 descriptorPoolOverallocation; +} VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + + + // VK_KHR_acceleration_structure is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_acceleration_structure 1 #define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 diff --git a/thirdparty/vulkan/include/vulkan/vulkan_enums.hpp b/thirdparty/vulkan/include/vulkan/vulkan_enums.hpp index bac993339b..d243cd4014 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_enums.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_enums.hpp @@ -10,6 +10,212 @@ namespace VULKAN_HPP_NAMESPACE { + template <typename FlagBitsType> + struct FlagTraits + { + static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = false; + }; + + template <typename BitType> + class Flags + { + public: + using MaskType = typename std::underlying_type<BitType>::type; + + // constructors + VULKAN_HPP_CONSTEXPR Flags() VULKAN_HPP_NOEXCEPT : m_mask( 0 ) {} + + VULKAN_HPP_CONSTEXPR Flags( BitType bit ) VULKAN_HPP_NOEXCEPT : m_mask( static_cast<MaskType>( bit ) ) {} + + VULKAN_HPP_CONSTEXPR Flags( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + VULKAN_HPP_CONSTEXPR explicit Flags( MaskType flags ) VULKAN_HPP_NOEXCEPT : m_mask( flags ) {} + + // relational operators +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( Flags<BitType> const & ) const = default; +#else + VULKAN_HPP_CONSTEXPR bool operator<( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return m_mask < rhs.m_mask; + } + + VULKAN_HPP_CONSTEXPR bool operator<=( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return m_mask <= rhs.m_mask; + } + + VULKAN_HPP_CONSTEXPR bool operator>( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return m_mask > rhs.m_mask; + } + + VULKAN_HPP_CONSTEXPR bool operator>=( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return m_mask >= rhs.m_mask; + } + + VULKAN_HPP_CONSTEXPR bool operator==( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return m_mask == rhs.m_mask; + } + + VULKAN_HPP_CONSTEXPR bool operator!=( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return m_mask != rhs.m_mask; + } +#endif + + // logical operator + VULKAN_HPP_CONSTEXPR bool operator!() const VULKAN_HPP_NOEXCEPT + { + return !m_mask; + } + + // bitwise operators + VULKAN_HPP_CONSTEXPR Flags<BitType> operator&( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return Flags<BitType>( m_mask & rhs.m_mask ); + } + + VULKAN_HPP_CONSTEXPR Flags<BitType> operator|( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return Flags<BitType>( m_mask | rhs.m_mask ); + } + + VULKAN_HPP_CONSTEXPR Flags<BitType> operator^( Flags<BitType> const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return Flags<BitType>( m_mask ^ rhs.m_mask ); + } + + VULKAN_HPP_CONSTEXPR Flags<BitType> operator~() const VULKAN_HPP_NOEXCEPT + { + return Flags<BitType>( m_mask ^ FlagTraits<BitType>::allFlags.m_mask ); + } + + // assignment operators + VULKAN_HPP_CONSTEXPR_14 Flags<BitType> & operator=( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + VULKAN_HPP_CONSTEXPR_14 Flags<BitType> & operator|=( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT + { + m_mask |= rhs.m_mask; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 Flags<BitType> & operator&=( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT + { + m_mask &= rhs.m_mask; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 Flags<BitType> & operator^=( Flags<BitType> const & rhs ) VULKAN_HPP_NOEXCEPT + { + m_mask ^= rhs.m_mask; + return *this; + } + + // cast operators + explicit VULKAN_HPP_CONSTEXPR operator bool() const VULKAN_HPP_NOEXCEPT + { + return !!m_mask; + } + + explicit VULKAN_HPP_CONSTEXPR operator MaskType() const VULKAN_HPP_NOEXCEPT + { + return m_mask; + } + +#if defined( VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC ) + public: +#else + private: +#endif + MaskType m_mask; + }; + +#if !defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + // relational operators only needed for pre C++20 + template <typename BitType> + VULKAN_HPP_CONSTEXPR bool operator<( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator>( bit ); + } + + template <typename BitType> + VULKAN_HPP_CONSTEXPR bool operator<=( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator>=( bit ); + } + + template <typename BitType> + VULKAN_HPP_CONSTEXPR bool operator>( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator<( bit ); + } + + template <typename BitType> + VULKAN_HPP_CONSTEXPR bool operator>=( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator<=( bit ); + } + + template <typename BitType> + VULKAN_HPP_CONSTEXPR bool operator==( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator==( bit ); + } + + template <typename BitType> + VULKAN_HPP_CONSTEXPR bool operator!=( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator!=( bit ); + } +#endif + + // bitwise operators + template <typename BitType> + VULKAN_HPP_CONSTEXPR Flags<BitType> operator&( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator&( bit ); + } + + template <typename BitType> + VULKAN_HPP_CONSTEXPR Flags<BitType> operator|( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator|( bit ); + } + + template <typename BitType> + VULKAN_HPP_CONSTEXPR Flags<BitType> operator^( BitType bit, Flags<BitType> const & flags ) VULKAN_HPP_NOEXCEPT + { + return flags.operator^( bit ); + } + + // bitwise operators on BitType + template <typename BitType, typename std::enable_if<FlagTraits<BitType>::isBitmask, bool>::type = true> + VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR Flags<BitType> operator&( BitType lhs, BitType rhs ) VULKAN_HPP_NOEXCEPT + { + return Flags<BitType>( lhs ) & rhs; + } + + template <typename BitType, typename std::enable_if<FlagTraits<BitType>::isBitmask, bool>::type = true> + VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR Flags<BitType> operator|( BitType lhs, BitType rhs ) VULKAN_HPP_NOEXCEPT + { + return Flags<BitType>( lhs ) | rhs; + } + + template <typename BitType, typename std::enable_if<FlagTraits<BitType>::isBitmask, bool>::type = true> + VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR Flags<BitType> operator^( BitType lhs, BitType rhs ) VULKAN_HPP_NOEXCEPT + { + return Flags<BitType>( lhs ) ^ rhs; + } + + template <typename BitType, typename std::enable_if<FlagTraits<BitType>::isBitmask, bool>::type = true> + VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR Flags<BitType> operator~( BitType bit ) VULKAN_HPP_NOEXCEPT + { + return ~( Flags<BitType>( bit ) ); + } + template <typename EnumType, EnumType value> struct CppType { @@ -1007,6 +1213,8 @@ namespace VULKAN_HPP_NAMESPACE ePipelinePropertiesIdentifierEXT = VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT, ePhysicalDevicePipelinePropertiesFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT, ePipelineInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_INFO_EXT, + ePhysicalDeviceFrameBoundaryFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT, + eFrameBoundaryEXT = VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT, ePhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT, eSubpassResolvePerformanceQueryEXT = VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT, eMultisampledRenderToSingleSampledInfoEXT = VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT, @@ -1074,6 +1282,8 @@ namespace VULKAN_HPP_NAMESPACE ePhysicalDeviceImageProcessingFeaturesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM, ePhysicalDeviceImageProcessingPropertiesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM, eImageViewSampleWeightCreateInfoQCOM = VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM, + ePhysicalDeviceNestedCommandBufferFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT, + ePhysicalDeviceNestedCommandBufferPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT, eExternalMemoryAcquireUnmodifiedEXT = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT, ePhysicalDeviceExtendedDynamicState3FeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT, ePhysicalDeviceExtendedDynamicState3PropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT, @@ -1097,6 +1307,11 @@ namespace VULKAN_HPP_NAMESPACE eOpticalFlowSessionCreatePrivateDataInfoNV = VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV, ePhysicalDeviceLegacyDitheringFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT, ePhysicalDevicePipelineProtectedAccessFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT, +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + ePhysicalDeviceExternalFormatResolveFeaturesANDROID = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID, + ePhysicalDeviceExternalFormatResolvePropertiesANDROID = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID, + eAndroidHardwareBufferFormatResolvePropertiesANDROID = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID, +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ ePhysicalDeviceMaintenance5FeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR, ePhysicalDeviceMaintenance5PropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR, eRenderingAreaInfoKHR = VK_STRUCTURE_TYPE_RENDERING_AREA_INFO_KHR, @@ -1117,25 +1332,47 @@ namespace VULKAN_HPP_NAMESPACE ePhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM, ePhysicalDeviceRayTracingInvocationReorderFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV, ePhysicalDeviceRayTracingInvocationReorderPropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV, + ePhysicalDeviceExtendedSparseAddressSpaceFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV, + ePhysicalDeviceExtendedSparseAddressSpacePropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV, ePhysicalDeviceMutableDescriptorTypeFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, eMutableDescriptorTypeCreateInfoEXT = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT, ePhysicalDeviceShaderCoreBuiltinsFeaturesARM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM, ePhysicalDeviceShaderCoreBuiltinsPropertiesARM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM, ePhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT, ePhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT, + eLatencySleepModeInfoNV = VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV, + eLatencySleepInfoNV = VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV, + eSetLatencyMarkerInfoNV = VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV, + eGetLatencyMarkerInfoNV = VK_STRUCTURE_TYPE_GET_LATENCY_MARKER_INFO_NV, + eLatencyTimingsFrameReportNV = VK_STRUCTURE_TYPE_LATENCY_TIMINGS_FRAME_REPORT_NV, + eLatencySubmissionPresentIdNV = VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV, + eOutOfBandQueueTypeInfoNV = VK_STRUCTURE_TYPE_OUT_OF_BAND_QUEUE_TYPE_INFO_NV, + eSwapchainLatencyCreateInfoNV = VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV, + eLatencySurfaceCapabilitiesNV = VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV, ePhysicalDeviceCooperativeMatrixFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR, eCooperativeMatrixPropertiesKHR = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR, ePhysicalDeviceCooperativeMatrixPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR, ePhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM, eMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM = VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM, + ePhysicalDeviceImageProcessing2FeaturesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM, + ePhysicalDeviceImageProcessing2PropertiesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM, + eSamplerBlockMatchWindowCreateInfoQCOM = VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM, + eSamplerCubicWeightsCreateInfoQCOM = VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM, + ePhysicalDeviceCubicWeightsFeaturesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM, + eBlitImageCubicWeightsInfoQCOM = VK_STRUCTURE_TYPE_BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM, + ePhysicalDeviceYcbcrDegammaFeaturesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM, + eSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM, + ePhysicalDeviceCubicClampFeaturesQCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM, ePhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT, #if defined( VK_USE_PLATFORM_SCREEN_QNX ) eScreenBufferPropertiesQNX = VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX, eScreenBufferFormatPropertiesQNX = VK_STRUCTURE_TYPE_SCREEN_BUFFER_FORMAT_PROPERTIES_QNX, eImportScreenBufferInfoQNX = VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX, eExternalFormatQNX = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_QNX, - ePhysicalDeviceExternalMemoryScreenBufferFeaturesQNX = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX + ePhysicalDeviceExternalMemoryScreenBufferFeaturesQNX = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX, #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ + ePhysicalDeviceLayeredDriverPropertiesMSFT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT, + ePhysicalDeviceDescriptorPoolOverallocationFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV }; enum class PipelineCacheHeaderVersion @@ -1843,6 +2080,20 @@ namespace VULKAN_HPP_NAMESPACE static VULKAN_HPP_CONST_OR_CONSTEXPR DeviceCreateFlags allFlags = {}; }; + enum class DeviceQueueCreateFlagBits : VkDeviceQueueCreateFlags + { + eProtected = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT + }; + + using DeviceQueueCreateFlags = Flags<DeviceQueueCreateFlagBits>; + + template <> + struct FlagTraits<DeviceQueueCreateFlagBits> + { + static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; + static VULKAN_HPP_CONST_OR_CONSTEXPR DeviceQueueCreateFlags allFlags = DeviceQueueCreateFlagBits::eProtected; + }; + enum class PipelineStageFlagBits : VkPipelineStageFlags { eTopOfPipe = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, @@ -2306,6 +2557,21 @@ namespace VULKAN_HPP_NAMESPACE static VULKAN_HPP_CONST_OR_CONSTEXPR ShaderModuleCreateFlags allFlags = {}; }; + enum class PipelineCacheCreateFlagBits : VkPipelineCacheCreateFlags + { + eExternallySynchronized = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, + eExternallySynchronizedEXT = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT + }; + + using PipelineCacheCreateFlags = Flags<PipelineCacheCreateFlagBits>; + + template <> + struct FlagTraits<PipelineCacheCreateFlagBits> + { + static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; + static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineCacheCreateFlags allFlags = PipelineCacheCreateFlagBits::eExternallySynchronized; + }; + enum class BlendFactor { eZero = VK_BLEND_FACTOR_ZERO, @@ -2720,6 +2986,41 @@ namespace VULKAN_HPP_NAMESPACE eInstance = VK_VERTEX_INPUT_RATE_INSTANCE }; + enum class PipelineColorBlendStateCreateFlagBits : VkPipelineColorBlendStateCreateFlags + { + eRasterizationOrderAttachmentAccessARM = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM, + eRasterizationOrderAttachmentAccessEXT = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT + }; + + using PipelineColorBlendStateCreateFlags = Flags<PipelineColorBlendStateCreateFlagBits>; + + template <> + struct FlagTraits<PipelineColorBlendStateCreateFlagBits> + { + static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; + static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineColorBlendStateCreateFlags allFlags = + PipelineColorBlendStateCreateFlagBits::eRasterizationOrderAttachmentAccessEXT; + }; + + enum class PipelineDepthStencilStateCreateFlagBits : VkPipelineDepthStencilStateCreateFlags + { + eRasterizationOrderAttachmentDepthAccessARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM, + eRasterizationOrderAttachmentStencilAccessARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM, + eRasterizationOrderAttachmentDepthAccessEXT = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, + eRasterizationOrderAttachmentStencilAccessEXT = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT + }; + + using PipelineDepthStencilStateCreateFlags = Flags<PipelineDepthStencilStateCreateFlagBits>; + + template <> + struct FlagTraits<PipelineDepthStencilStateCreateFlagBits> + { + static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; + static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineDepthStencilStateCreateFlags allFlags = + PipelineDepthStencilStateCreateFlagBits::eRasterizationOrderAttachmentDepthAccessEXT | + PipelineDepthStencilStateCreateFlagBits::eRasterizationOrderAttachmentStencilAccessEXT; + }; + enum class PipelineDynamicStateCreateFlagBits : VkPipelineDynamicStateCreateFlags { }; @@ -2746,6 +3047,20 @@ namespace VULKAN_HPP_NAMESPACE static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineInputAssemblyStateCreateFlags allFlags = {}; }; + enum class PipelineLayoutCreateFlagBits : VkPipelineLayoutCreateFlags + { + eIndependentSetsEXT = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT + }; + + using PipelineLayoutCreateFlags = Flags<PipelineLayoutCreateFlagBits>; + + template <> + struct FlagTraits<PipelineLayoutCreateFlagBits> + { + static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; + static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineLayoutCreateFlags allFlags = PipelineLayoutCreateFlagBits::eIndependentSetsEXT; + }; + enum class PipelineMultisampleStateCreateFlagBits : VkPipelineMultisampleStateCreateFlags { }; @@ -2869,11 +3184,13 @@ namespace VULKAN_HPP_NAMESPACE enum class DescriptorPoolCreateFlagBits : VkDescriptorPoolCreateFlags { - eFreeDescriptorSet = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - eUpdateAfterBind = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, - eUpdateAfterBindEXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT, - eHostOnlyVALVE = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE, - eHostOnlyEXT = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT + eFreeDescriptorSet = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + eUpdateAfterBind = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, + eUpdateAfterBindEXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT, + eHostOnlyVALVE = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE, + eHostOnlyEXT = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT, + eAllowOverallocationSetsNV = VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV, + eAllowOverallocationPoolsNV = VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV }; using DescriptorPoolCreateFlags = Flags<DescriptorPoolCreateFlagBits>; @@ -2883,7 +3200,8 @@ namespace VULKAN_HPP_NAMESPACE { static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; static VULKAN_HPP_CONST_OR_CONSTEXPR DescriptorPoolCreateFlags allFlags = - DescriptorPoolCreateFlagBits::eFreeDescriptorSet | DescriptorPoolCreateFlagBits::eUpdateAfterBind | DescriptorPoolCreateFlagBits::eHostOnlyEXT; + DescriptorPoolCreateFlagBits::eFreeDescriptorSet | DescriptorPoolCreateFlagBits::eUpdateAfterBind | DescriptorPoolCreateFlagBits::eHostOnlyEXT | + DescriptorPoolCreateFlagBits::eAllowOverallocationSetsNV | DescriptorPoolCreateFlagBits::eAllowOverallocationPoolsNV; }; enum class DescriptorSetLayoutCreateFlagBits : VkDescriptorSetLayoutCreateFlags @@ -3232,8 +3550,9 @@ namespace VULKAN_HPP_NAMESPACE enum class SubpassContents { - eInline = VK_SUBPASS_CONTENTS_INLINE, - eSecondaryCommandBuffers = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS + eInline = VK_SUBPASS_CONTENTS_INLINE, + eSecondaryCommandBuffers = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, + eInlineAndSecondaryCommandBuffersEXT = VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT }; //=== VK_VERSION_1_1 === @@ -3330,20 +3649,6 @@ namespace VULKAN_HPP_NAMESPACE }; using TessellationDomainOriginKHR = TessellationDomainOrigin; - enum class DeviceQueueCreateFlagBits : VkDeviceQueueCreateFlags - { - eProtected = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT - }; - - using DeviceQueueCreateFlags = Flags<DeviceQueueCreateFlagBits>; - - template <> - struct FlagTraits<DeviceQueueCreateFlagBits> - { - static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; - static VULKAN_HPP_CONST_OR_CONSTEXPR DeviceQueueCreateFlags allFlags = DeviceQueueCreateFlagBits::eProtected; - }; - enum class SamplerYcbcrModelConversion { eRgbIdentity = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, @@ -3605,7 +3910,8 @@ namespace VULKAN_HPP_NAMESPACE eMesaVenus = VK_DRIVER_ID_MESA_VENUS, eMesaDozen = VK_DRIVER_ID_MESA_DOZEN, eMesaNvk = VK_DRIVER_ID_MESA_NVK, - eImaginationOpenSourceMESA = VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA + eImaginationOpenSourceMESA = VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA, + eMesaAgxv = VK_DRIVER_ID_MESA_AGXV }; using DriverIdKHR = DriverId; @@ -3644,7 +3950,10 @@ namespace VULKAN_HPP_NAMESPACE eSampleZero = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, eAverage = VK_RESOLVE_MODE_AVERAGE_BIT, eMin = VK_RESOLVE_MODE_MIN_BIT, - eMax = VK_RESOLVE_MODE_MAX_BIT + eMax = VK_RESOLVE_MODE_MAX_BIT, +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + eExternalFormatDownsampleANDROID = VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ }; using ResolveModeFlagBitsKHR = ResolveModeFlagBits; @@ -3655,15 +3964,20 @@ namespace VULKAN_HPP_NAMESPACE struct FlagTraits<ResolveModeFlagBits> { static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; - static VULKAN_HPP_CONST_OR_CONSTEXPR ResolveModeFlags allFlags = - ResolveModeFlagBits::eNone | ResolveModeFlagBits::eSampleZero | ResolveModeFlagBits::eAverage | ResolveModeFlagBits::eMin | ResolveModeFlagBits::eMax; + static VULKAN_HPP_CONST_OR_CONSTEXPR ResolveModeFlags allFlags = ResolveModeFlagBits::eNone | ResolveModeFlagBits::eSampleZero | + ResolveModeFlagBits::eAverage | ResolveModeFlagBits::eMin | ResolveModeFlagBits::eMax +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + | ResolveModeFlagBits::eExternalFormatDownsampleANDROID +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + ; }; enum class SamplerReductionMode { - eWeightedAverage = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, - eMin = VK_SAMPLER_REDUCTION_MODE_MIN, - eMax = VK_SAMPLER_REDUCTION_MODE_MAX + eWeightedAverage = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, + eMin = VK_SAMPLER_REDUCTION_MODE_MIN, + eMax = VK_SAMPLER_REDUCTION_MODE_MAX, + eWeightedAverageRangeclampQCOM = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM }; using SamplerReductionModeEXT = SamplerReductionMode; @@ -3933,6 +4247,7 @@ namespace VULKAN_HPP_NAMESPACE eContentsSecondaryCommandBuffers = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, eSuspending = VK_RENDERING_SUSPENDING_BIT, eResuming = VK_RENDERING_RESUMING_BIT, + eContentsInlineEXT = VK_RENDERING_CONTENTS_INLINE_BIT_EXT, eEnableLegacyDitheringEXT = VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT }; using RenderingFlagBitsKHR = RenderingFlagBits; @@ -3945,7 +4260,8 @@ namespace VULKAN_HPP_NAMESPACE { static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; static VULKAN_HPP_CONST_OR_CONSTEXPR RenderingFlags allFlags = RenderingFlagBits::eContentsSecondaryCommandBuffers | RenderingFlagBits::eSuspending | - RenderingFlagBits::eResuming | RenderingFlagBits::eEnableLegacyDitheringEXT; + RenderingFlagBits::eResuming | RenderingFlagBits::eContentsInlineEXT | + RenderingFlagBits::eEnableLegacyDitheringEXT; }; enum class FormatFeatureFlagBits2 : VkFormatFeatureFlags2 @@ -4487,7 +4803,10 @@ namespace VULKAN_HPP_NAMESPACE { eError = VK_QUERY_RESULT_STATUS_ERROR_KHR, eNotReady = VK_QUERY_RESULT_STATUS_NOT_READY_KHR, - eComplete = VK_QUERY_RESULT_STATUS_COMPLETE_KHR + eComplete = VK_QUERY_RESULT_STATUS_COMPLETE_KHR, +#if defined( VK_ENABLE_BETA_EXTENSIONS ) + eInsufficientBitstreamBufferRange = VK_QUERY_RESULT_STATUS_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_KHR +#endif /*VK_ENABLE_BETA_EXTENSIONS*/ }; enum class VideoSessionParametersCreateFlagBitsKHR : VkVideoSessionParametersCreateFlagsKHR @@ -4642,7 +4961,9 @@ namespace VULKAN_HPP_NAMESPACE eConstrainedIntraPredFlagSet = VK_VIDEO_ENCODE_H264_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_EXT, eDeblockingFilterDisabled = VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_DISABLED_BIT_EXT, eDeblockingFilterEnabled = VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_ENABLED_BIT_EXT, - eDeblockingFilterPartial = VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_EXT + eDeblockingFilterPartial = VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_EXT, + eSliceQpDelta = VK_VIDEO_ENCODE_H264_STD_SLICE_QP_DELTA_BIT_EXT, + eDifferentSliceQpDelta = VK_VIDEO_ENCODE_H264_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT }; using VideoEncodeH264StdFlagsEXT = Flags<VideoEncodeH264StdFlagBitsEXT>; @@ -4660,7 +4981,8 @@ namespace VULKAN_HPP_NAMESPACE VideoEncodeH264StdFlagBitsEXT::eDirectSpatialMvPredFlagUnset | VideoEncodeH264StdFlagBitsEXT::eEntropyCodingModeFlagUnset | VideoEncodeH264StdFlagBitsEXT::eEntropyCodingModeFlagSet | VideoEncodeH264StdFlagBitsEXT::eDirect8X8InferenceFlagUnset | VideoEncodeH264StdFlagBitsEXT::eConstrainedIntraPredFlagSet | VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterDisabled | - VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterEnabled | VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterPartial; + VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterEnabled | VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterPartial | + VideoEncodeH264StdFlagBitsEXT::eSliceQpDelta | VideoEncodeH264StdFlagBitsEXT::eDifferentSliceQpDelta; }; enum class VideoEncodeH264RateControlFlagBitsEXT : VkVideoEncodeH264RateControlFlagsEXT @@ -4736,7 +5058,9 @@ namespace VULKAN_HPP_NAMESPACE eEntropyCodingSyncEnabledFlagSet = VK_VIDEO_ENCODE_H265_STD_ENTROPY_CODING_SYNC_ENABLED_FLAG_SET_BIT_EXT, eDeblockingFilterOverrideEnabledFlagSet = VK_VIDEO_ENCODE_H265_STD_DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_SET_BIT_EXT, eDependentSliceSegmentsEnabledFlagSet = VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_EXT, - eDependentSliceSegmentFlagSet = VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_EXT + eDependentSliceSegmentFlagSet = VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_EXT, + eSliceQpDelta = VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_EXT, + eDifferentSliceQpDelta = VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT }; using VideoEncodeH265StdFlagsEXT = Flags<VideoEncodeH265StdFlagBitsEXT>; @@ -4755,7 +5079,8 @@ namespace VULKAN_HPP_NAMESPACE VideoEncodeH265StdFlagBitsEXT::ePpsSliceChromaQpOffsetsPresentFlagSet | VideoEncodeH265StdFlagBitsEXT::eTransquantBypassEnabledFlagSet | VideoEncodeH265StdFlagBitsEXT::eConstrainedIntraPredFlagSet | VideoEncodeH265StdFlagBitsEXT::eEntropyCodingSyncEnabledFlagSet | VideoEncodeH265StdFlagBitsEXT::eDeblockingFilterOverrideEnabledFlagSet | VideoEncodeH265StdFlagBitsEXT::eDependentSliceSegmentsEnabledFlagSet | - VideoEncodeH265StdFlagBitsEXT::eDependentSliceSegmentFlagSet; + VideoEncodeH265StdFlagBitsEXT::eDependentSliceSegmentFlagSet | VideoEncodeH265StdFlagBitsEXT::eSliceQpDelta | + VideoEncodeH265StdFlagBitsEXT::eDifferentSliceQpDelta; }; enum class VideoEncodeH265CtbSizeFlagBitsEXT : VkVideoEncodeH265CtbSizeFlagsEXT @@ -5896,29 +6221,13 @@ namespace VULKAN_HPP_NAMESPACE static VULKAN_HPP_CONST_OR_CONSTEXPR DeviceMemoryReportFlagsEXT allFlags = {}; }; - //=== VK_EXT_pipeline_creation_cache_control === - - enum class PipelineCacheCreateFlagBits : VkPipelineCacheCreateFlags - { - eExternallySynchronized = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, - eExternallySynchronizedEXT = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT - }; - - using PipelineCacheCreateFlags = Flags<PipelineCacheCreateFlagBits>; - - template <> - struct FlagTraits<PipelineCacheCreateFlagBits> - { - static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; - static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineCacheCreateFlags allFlags = PipelineCacheCreateFlagBits::eExternallySynchronized; - }; - #if defined( VK_ENABLE_BETA_EXTENSIONS ) //=== VK_KHR_video_encode_queue === enum class VideoEncodeCapabilityFlagBitsKHR : VkVideoEncodeCapabilityFlagsKHR { - ePrecedingExternallyEncodedBytes = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR + ePrecedingExternallyEncodedBytes = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR, + eInsufficientstreamBufferRangeDetectionBit = VK_VIDEO_ENCODE_CAPABILITY_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_DETECTION_BIT_KHR }; using VideoEncodeCapabilityFlagsKHR = Flags<VideoEncodeCapabilityFlagBitsKHR>; @@ -5927,7 +6236,8 @@ namespace VULKAN_HPP_NAMESPACE struct FlagTraits<VideoEncodeCapabilityFlagBitsKHR> { static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; - static VULKAN_HPP_CONST_OR_CONSTEXPR VideoEncodeCapabilityFlagsKHR allFlags = VideoEncodeCapabilityFlagBitsKHR::ePrecedingExternallyEncodedBytes; + static VULKAN_HPP_CONST_OR_CONSTEXPR VideoEncodeCapabilityFlagsKHR allFlags = + VideoEncodeCapabilityFlagBitsKHR::ePrecedingExternallyEncodedBytes | VideoEncodeCapabilityFlagBitsKHR::eInsufficientstreamBufferRangeDetectionBit; }; enum class VideoEncodeFeedbackFlagBitsKHR : VkVideoEncodeFeedbackFlagsKHR @@ -6109,20 +6419,6 @@ namespace VULKAN_HPP_NAMESPACE GraphicsPipelineLibraryFlagBitsEXT::eFragmentShader | GraphicsPipelineLibraryFlagBitsEXT::eFragmentOutputInterface; }; - enum class PipelineLayoutCreateFlagBits : VkPipelineLayoutCreateFlags - { - eIndependentSetsEXT = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT - }; - - using PipelineLayoutCreateFlags = Flags<PipelineLayoutCreateFlagBits>; - - template <> - struct FlagTraits<PipelineLayoutCreateFlagBits> - { - static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; - static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineLayoutCreateFlags allFlags = PipelineLayoutCreateFlagBits::eIndependentSetsEXT; - }; - //=== VK_NV_fragment_shading_rate_enums === enum class FragmentShadingRateNV @@ -6345,6 +6641,22 @@ namespace VULKAN_HPP_NAMESPACE }; #endif /*VK_USE_PLATFORM_FUCHSIA*/ + //=== VK_EXT_frame_boundary === + + enum class FrameBoundaryFlagBitsEXT : VkFrameBoundaryFlagsEXT + { + eFrameEnd = VK_FRAME_BOUNDARY_FRAME_END_BIT_EXT + }; + + using FrameBoundaryFlagsEXT = Flags<FrameBoundaryFlagBitsEXT>; + + template <> + struct FlagTraits<FrameBoundaryFlagBitsEXT> + { + static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; + static VULKAN_HPP_CONST_OR_CONSTEXPR FrameBoundaryFlagsEXT allFlags = FrameBoundaryFlagBitsEXT::eFrameEnd; + }; + #if defined( VK_USE_PLATFORM_SCREEN_QNX ) //=== VK_QNX_screen_surface === @@ -6498,43 +6810,6 @@ namespace VULKAN_HPP_NAMESPACE static VULKAN_HPP_CONST_OR_CONSTEXPR DirectDriverLoadingFlagsLUNARG allFlags = {}; }; - //=== VK_EXT_rasterization_order_attachment_access === - - enum class PipelineColorBlendStateCreateFlagBits : VkPipelineColorBlendStateCreateFlags - { - eRasterizationOrderAttachmentAccessARM = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM, - eRasterizationOrderAttachmentAccessEXT = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT - }; - - using PipelineColorBlendStateCreateFlags = Flags<PipelineColorBlendStateCreateFlagBits>; - - template <> - struct FlagTraits<PipelineColorBlendStateCreateFlagBits> - { - static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; - static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineColorBlendStateCreateFlags allFlags = - PipelineColorBlendStateCreateFlagBits::eRasterizationOrderAttachmentAccessEXT; - }; - - enum class PipelineDepthStencilStateCreateFlagBits : VkPipelineDepthStencilStateCreateFlags - { - eRasterizationOrderAttachmentDepthAccessARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM, - eRasterizationOrderAttachmentStencilAccessARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM, - eRasterizationOrderAttachmentDepthAccessEXT = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, - eRasterizationOrderAttachmentStencilAccessEXT = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT - }; - - using PipelineDepthStencilStateCreateFlags = Flags<PipelineDepthStencilStateCreateFlagBits>; - - template <> - struct FlagTraits<PipelineDepthStencilStateCreateFlagBits> - { - static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true; - static VULKAN_HPP_CONST_OR_CONSTEXPR PipelineDepthStencilStateCreateFlags allFlags = - PipelineDepthStencilStateCreateFlagBits::eRasterizationOrderAttachmentDepthAccessEXT | - PipelineDepthStencilStateCreateFlagBits::eRasterizationOrderAttachmentStencilAccessEXT; - }; - //=== VK_NV_optical_flow === enum class OpticalFlowUsageFlagBitsNV : VkOpticalFlowUsageFlagsNV @@ -6793,6 +7068,30 @@ namespace VULKAN_HPP_NAMESPACE eReorder = VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV }; + //=== VK_NV_low_latency2 === + + enum class LatencyMarkerNV + { + eSimulationStart = VK_LATENCY_MARKER_SIMULATION_START_NV, + eSimulationEnd = VK_LATENCY_MARKER_SIMULATION_END_NV, + eRendersubmitStart = VK_LATENCY_MARKER_RENDERSUBMIT_START_NV, + eRendersubmitEnd = VK_LATENCY_MARKER_RENDERSUBMIT_END_NV, + ePresentStart = VK_LATENCY_MARKER_PRESENT_START_NV, + ePresentEnd = VK_LATENCY_MARKER_PRESENT_END_NV, + eInputSample = VK_LATENCY_MARKER_INPUT_SAMPLE_NV, + eTriggerFlash = VK_LATENCY_MARKER_TRIGGER_FLASH_NV, + eOutOfBandRendersubmitStart = VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_START_NV, + eOutOfBandRendersubmitEnd = VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_END_NV, + eOutOfBandPresentStart = VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_START_NV, + eOutOfBandPresentEnd = VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_END_NV + }; + + enum class OutOfBandQueueTypeNV + { + eRender = VK_OUT_OF_BAND_QUEUE_TYPE_RENDER_NV, + ePresent = VK_OUT_OF_BAND_QUEUE_TYPE_PRESENT_NV + }; + //=== VK_KHR_cooperative_matrix === enum class ScopeKHR @@ -6820,6 +7119,32 @@ namespace VULKAN_HPP_NAMESPACE }; using ComponentTypeNV = ComponentTypeKHR; + //=== VK_QCOM_image_processing2 === + + enum class BlockMatchWindowCompareModeQCOM + { + eMin = VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MIN_QCOM, + eMax = VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_QCOM + }; + + //=== VK_QCOM_filter_cubic_weights === + + enum class CubicFilterWeightsQCOM + { + eCatmullRom = VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM, + eZeroTangentCardinal = VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM, + eBSpline = VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM, + eMitchellNetravali = VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM + }; + + //=== VK_MSFT_layered_driver === + + enum class LayeredDriverUnderlyingApiMSFT + { + eNone = VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT, + eD3D12 = VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT + }; + //========================= //=== Index Type Traits === //========================= @@ -6865,5 +7190,124 @@ namespace VULKAN_HPP_NAMESPACE using Type = uint8_t; }; + //=========================================================== + //=== Mapping from ObjectType to DebugReportObjectTypeEXT === + //=========================================================== + + VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType( VULKAN_HPP_NAMESPACE::ObjectType objectType ) + { + switch ( objectType ) + { + //=== VK_VERSION_1_0 === + case VULKAN_HPP_NAMESPACE::ObjectType::eInstance: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eInstance; + case VULKAN_HPP_NAMESPACE::ObjectType::ePhysicalDevice: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::ePhysicalDevice; + case VULKAN_HPP_NAMESPACE::ObjectType::eDevice: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDevice; + case VULKAN_HPP_NAMESPACE::ObjectType::eQueue: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eQueue; + case VULKAN_HPP_NAMESPACE::ObjectType::eDeviceMemory: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDeviceMemory; + case VULKAN_HPP_NAMESPACE::ObjectType::eFence: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eFence; + case VULKAN_HPP_NAMESPACE::ObjectType::eSemaphore: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eSemaphore; + case VULKAN_HPP_NAMESPACE::ObjectType::eEvent: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eEvent; + case VULKAN_HPP_NAMESPACE::ObjectType::eQueryPool: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eQueryPool; + case VULKAN_HPP_NAMESPACE::ObjectType::eBuffer: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eBuffer; + case VULKAN_HPP_NAMESPACE::ObjectType::eBufferView: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eBufferView; + case VULKAN_HPP_NAMESPACE::ObjectType::eImage: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eImage; + case VULKAN_HPP_NAMESPACE::ObjectType::eImageView: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eImageView; + case VULKAN_HPP_NAMESPACE::ObjectType::eShaderModule: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eShaderModule; + case VULKAN_HPP_NAMESPACE::ObjectType::ePipelineCache: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::ePipelineCache; + case VULKAN_HPP_NAMESPACE::ObjectType::ePipeline: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::ePipeline; + case VULKAN_HPP_NAMESPACE::ObjectType::ePipelineLayout: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::ePipelineLayout; + case VULKAN_HPP_NAMESPACE::ObjectType::eSampler: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eSampler; + case VULKAN_HPP_NAMESPACE::ObjectType::eDescriptorPool: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDescriptorPool; + case VULKAN_HPP_NAMESPACE::ObjectType::eDescriptorSet: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDescriptorSet; + case VULKAN_HPP_NAMESPACE::ObjectType::eDescriptorSetLayout: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDescriptorSetLayout; + case VULKAN_HPP_NAMESPACE::ObjectType::eFramebuffer: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eFramebuffer; + case VULKAN_HPP_NAMESPACE::ObjectType::eRenderPass: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eRenderPass; + case VULKAN_HPP_NAMESPACE::ObjectType::eCommandPool: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eCommandPool; + case VULKAN_HPP_NAMESPACE::ObjectType::eCommandBuffer: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eCommandBuffer; + + //=== VK_VERSION_1_1 === + case VULKAN_HPP_NAMESPACE::ObjectType::eSamplerYcbcrConversion: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eSamplerYcbcrConversion; + case VULKAN_HPP_NAMESPACE::ObjectType::eDescriptorUpdateTemplate: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDescriptorUpdateTemplate; + + //=== VK_VERSION_1_3 === + case VULKAN_HPP_NAMESPACE::ObjectType::ePrivateDataSlot: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + + //=== VK_KHR_surface === + case VULKAN_HPP_NAMESPACE::ObjectType::eSurfaceKHR: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eSurfaceKHR; + + //=== VK_KHR_swapchain === + case VULKAN_HPP_NAMESPACE::ObjectType::eSwapchainKHR: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eSwapchainKHR; + + //=== VK_KHR_display === + case VULKAN_HPP_NAMESPACE::ObjectType::eDisplayKHR: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDisplayKHR; + case VULKAN_HPP_NAMESPACE::ObjectType::eDisplayModeKHR: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDisplayModeKHR; + + //=== VK_EXT_debug_report === + case VULKAN_HPP_NAMESPACE::ObjectType::eDebugReportCallbackEXT: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDebugReportCallbackEXT; + + //=== VK_KHR_video_queue === + case VULKAN_HPP_NAMESPACE::ObjectType::eVideoSessionKHR: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + case VULKAN_HPP_NAMESPACE::ObjectType::eVideoSessionParametersKHR: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + + //=== VK_NVX_binary_import === + case VULKAN_HPP_NAMESPACE::ObjectType::eCuModuleNVX: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eCuModuleNVX; + case VULKAN_HPP_NAMESPACE::ObjectType::eCuFunctionNVX: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eCuFunctionNVX; + + //=== VK_EXT_debug_utils === + case VULKAN_HPP_NAMESPACE::ObjectType::eDebugUtilsMessengerEXT: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + + //=== VK_KHR_acceleration_structure === + case VULKAN_HPP_NAMESPACE::ObjectType::eAccelerationStructureKHR: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eAccelerationStructureKHR; + + //=== VK_EXT_validation_cache === + case VULKAN_HPP_NAMESPACE::ObjectType::eValidationCacheEXT: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eValidationCacheEXT; + + //=== VK_NV_ray_tracing === + case VULKAN_HPP_NAMESPACE::ObjectType::eAccelerationStructureNV: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eAccelerationStructureNV; + + //=== VK_INTEL_performance_query === + case VULKAN_HPP_NAMESPACE::ObjectType::ePerformanceConfigurationINTEL: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + + //=== VK_KHR_deferred_host_operations === + case VULKAN_HPP_NAMESPACE::ObjectType::eDeferredOperationKHR: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + + //=== VK_NV_device_generated_commands === + case VULKAN_HPP_NAMESPACE::ObjectType::eIndirectCommandsLayoutNV: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + +#if defined( VK_USE_PLATFORM_FUCHSIA ) + //=== VK_FUCHSIA_buffer_collection === + case VULKAN_HPP_NAMESPACE::ObjectType::eBufferCollectionFUCHSIA: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eBufferCollectionFUCHSIA; +#endif /*VK_USE_PLATFORM_FUCHSIA*/ + + //=== VK_EXT_opacity_micromap === + case VULKAN_HPP_NAMESPACE::ObjectType::eMicromapEXT: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + + //=== VK_NV_optical_flow === + case VULKAN_HPP_NAMESPACE::ObjectType::eOpticalFlowSessionNV: + return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + + //=== VK_EXT_shader_object === + case VULKAN_HPP_NAMESPACE::ObjectType::eShaderEXT: return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + + default: VULKAN_HPP_ASSERT( false && "unknown ObjectType" ); return VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown; + } + } + } // namespace VULKAN_HPP_NAMESPACE #endif diff --git a/thirdparty/vulkan/include/vulkan/vulkan_extension_inspection.hpp b/thirdparty/vulkan/include/vulkan/vulkan_extension_inspection.hpp index 548a32fc27..d010468e08 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_extension_inspection.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_extension_inspection.hpp @@ -343,6 +343,7 @@ namespace VULKAN_HPP_NAMESPACE "VK_HUAWEI_invocation_mask", "VK_NV_external_memory_rdma", "VK_EXT_pipeline_properties", +"VK_EXT_frame_boundary", "VK_EXT_multisampled_render_to_single_sampled", "VK_EXT_extended_dynamic_state2", "VK_EXT_color_write_enable", @@ -374,6 +375,7 @@ namespace VULKAN_HPP_NAMESPACE "VK_NV_linear_color_attachment", "VK_EXT_image_compression_control_swapchain", "VK_QCOM_image_processing", +"VK_EXT_nested_command_buffer", "VK_EXT_external_memory_acquire_unmodified", "VK_EXT_extended_dynamic_state3", "VK_EXT_subpass_merge_feedback", @@ -381,7 +383,10 @@ namespace VULKAN_HPP_NAMESPACE "VK_EXT_rasterization_order_attachment_access", "VK_NV_optical_flow", "VK_EXT_legacy_dithering", -"VK_EXT_pipeline_protected_access", +"VK_EXT_pipeline_protected_access", +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) +"VK_ANDROID_external_format_resolve", +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ "VK_KHR_maintenance5", "VK_KHR_ray_tracing_position_fetch", "VK_EXT_shader_object", @@ -389,17 +394,24 @@ namespace VULKAN_HPP_NAMESPACE "VK_SEC_amigo_profiling", "VK_QCOM_multiview_per_view_viewports", "VK_NV_ray_tracing_invocation_reorder", +"VK_NV_extended_sparse_address_space", "VK_EXT_mutable_descriptor_type", "VK_ARM_shader_core_builtins", "VK_EXT_pipeline_library_group_handles", "VK_EXT_dynamic_rendering_unused_attachments", +"VK_NV_low_latency2", "VK_KHR_cooperative_matrix", "VK_QCOM_multiview_per_view_render_areas", +"VK_QCOM_image_processing2", +"VK_QCOM_filter_cubic_weights", +"VK_QCOM_ycbcr_degamma", +"VK_QCOM_filter_cubic_clamp", "VK_EXT_attachment_feedback_loop_dynamic_state", #if defined( VK_USE_PLATFORM_SCREEN_QNX ) -"VK_QNX_external_memory_screen_buffer" +"VK_QNX_external_memory_screen_buffer", #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ - }; +"VK_MSFT_layered_driver", +"VK_NV_descriptor_pool_overallocation" }; return deviceExtensions; } @@ -773,6 +785,7 @@ namespace VULKAN_HPP_NAMESPACE { "VK_GOOGLE_surfaceless_query", { { "VK_VERSION_1_0", { { "VK_KHR_surface", } } } } }, { "VK_EXT_image_compression_control_swapchain", { { "VK_VERSION_1_0", { { "VK_EXT_image_compression_control", } } } } }, { "VK_QCOM_image_processing", { { "VK_VERSION_1_0", { { "VK_KHR_format_feature_flags2", } } } } }, +{ "VK_EXT_nested_command_buffer", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, { "VK_EXT_external_memory_acquire_unmodified", { { "VK_VERSION_1_0", { { "VK_KHR_external_memory", } } } } }, { "VK_EXT_extended_dynamic_state3", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, { "VK_EXT_subpass_merge_feedback", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, @@ -780,7 +793,10 @@ namespace VULKAN_HPP_NAMESPACE { "VK_EXT_rasterization_order_attachment_access", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, { "VK_NV_optical_flow", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", "VK_KHR_format_feature_flags2", "VK_KHR_synchronization2", } } } } }, { "VK_EXT_legacy_dithering", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, -{ "VK_EXT_pipeline_protected_access", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, +{ "VK_EXT_pipeline_protected_access", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) +{ "VK_ANDROID_external_format_resolve", { { "VK_VERSION_1_0", { { "VK_ANDROID_external_memory_android_hardware_buffer", } } } } }, +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ { "VK_KHR_maintenance5", { { "VK_VERSION_1_1", { { "VK_KHR_dynamic_rendering", } } } } }, { "VK_KHR_ray_tracing_position_fetch", { { "VK_VERSION_1_0", { { "VK_KHR_acceleration_structure", } } } } }, { "VK_EXT_shader_object", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", "VK_KHR_dynamic_rendering", } } }, { "VK_VERSION_1_1", { { "VK_KHR_dynamic_rendering", } } }, { "VK_VERSION_1_3", { { } } } } }, @@ -793,11 +809,15 @@ namespace VULKAN_HPP_NAMESPACE { "VK_EXT_pipeline_library_group_handles", { { "VK_VERSION_1_0", { { "VK_KHR_ray_tracing_pipeline", "VK_KHR_pipeline_library", } } } } }, { "VK_EXT_dynamic_rendering_unused_attachments", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", "VK_KHR_dynamic_rendering", } } }, { "VK_VERSION_1_1", { { "VK_KHR_dynamic_rendering", } } }, { "VK_VERSION_1_3", { { } } } } }, { "VK_KHR_cooperative_matrix", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, +{ "VK_QCOM_image_processing2", { { "VK_VERSION_1_0", { { "VK_QCOM_image_processing", } } } } }, +{ "VK_QCOM_filter_cubic_weights", { { "VK_VERSION_1_0", { { "VK_EXT_filter_cubic", } } } } }, +{ "VK_QCOM_filter_cubic_clamp", { { "VK_VERSION_1_0", { { "VK_EXT_filter_cubic", "VK_EXT_sampler_filter_minmax", } } }, { "VK_VERSION_1_2", { { "VK_EXT_filter_cubic", } } } } }, { "VK_EXT_attachment_feedback_loop_dynamic_state", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", "VK_EXT_attachment_feedback_loop_layout", } } } } }, #if defined( VK_USE_PLATFORM_SCREEN_QNX ) -{ "VK_QNX_external_memory_screen_buffer", { { "VK_VERSION_1_0", { { "VK_KHR_sampler_ycbcr_conversion", "VK_KHR_external_memory", "VK_KHR_dedicated_allocation", } } }, { "VK_VERSION_1_1", { { "VK_EXT_queue_family_foreign", } } } } } +{ "VK_QNX_external_memory_screen_buffer", { { "VK_VERSION_1_0", { { "VK_KHR_sampler_ycbcr_conversion", "VK_KHR_external_memory", "VK_KHR_dedicated_allocation", } } }, { "VK_VERSION_1_1", { { "VK_EXT_queue_family_foreign", } } } } }, #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ - }; +{ "VK_MSFT_layered_driver", { { "VK_VERSION_1_0", { { "VK_KHR_get_physical_device_properties2", } } } } }, +{ "VK_NV_descriptor_pool_overallocation", { { "VK_VERSION_1_1", { { } } } } } }; auto depIt = dependencies.find( extension ); return ( depIt != dependencies.end() ) ? depIt->second : noDependencies; } @@ -1486,11 +1506,12 @@ namespace VULKAN_HPP_NAMESPACE ( extension == "VK_FUCHSIA_buffer_collection" ) #endif /*VK_USE_PLATFORM_FUCHSIA*/ || ( extension == "VK_HUAWEI_subpass_shading" ) || ( extension == "VK_HUAWEI_invocation_mask" ) || ( extension == "VK_NV_external_memory_rdma" ) || - ( extension == "VK_EXT_pipeline_properties" ) || ( extension == "VK_EXT_multisampled_render_to_single_sampled" ) || - ( extension == "VK_EXT_extended_dynamic_state2" ) || ( extension == "VK_EXT_color_write_enable" ) || - ( extension == "VK_EXT_primitives_generated_query" ) || ( extension == "VK_KHR_ray_tracing_maintenance1" ) || - ( extension == "VK_EXT_global_priority_query" ) || ( extension == "VK_EXT_image_view_min_lod" ) || ( extension == "VK_EXT_multi_draw" ) || - ( extension == "VK_EXT_image_2d_view_of_3d" ) || ( extension == "VK_EXT_shader_tile_image" ) || ( extension == "VK_EXT_opacity_micromap" ) + ( extension == "VK_EXT_pipeline_properties" ) || ( extension == "VK_EXT_frame_boundary" ) || + ( extension == "VK_EXT_multisampled_render_to_single_sampled" ) || ( extension == "VK_EXT_extended_dynamic_state2" ) || + ( extension == "VK_EXT_color_write_enable" ) || ( extension == "VK_EXT_primitives_generated_query" ) || + ( extension == "VK_KHR_ray_tracing_maintenance1" ) || ( extension == "VK_EXT_global_priority_query" ) || + ( extension == "VK_EXT_image_view_min_lod" ) || ( extension == "VK_EXT_multi_draw" ) || ( extension == "VK_EXT_image_2d_view_of_3d" ) || + ( extension == "VK_EXT_shader_tile_image" ) || ( extension == "VK_EXT_opacity_micromap" ) #if defined( VK_ENABLE_BETA_EXTENSIONS ) || ( extension == "VK_NV_displacement_micromap" ) #endif /*VK_ENABLE_BETA_EXTENSIONS*/ @@ -1502,20 +1523,26 @@ namespace VULKAN_HPP_NAMESPACE ( extension == "VK_NV_copy_memory_indirect" ) || ( extension == "VK_NV_memory_decompression" ) || ( extension == "VK_NV_device_generated_commands_compute" ) || ( extension == "VK_NV_linear_color_attachment" ) || ( extension == "VK_EXT_image_compression_control_swapchain" ) || ( extension == "VK_QCOM_image_processing" ) || - ( extension == "VK_EXT_external_memory_acquire_unmodified" ) || ( extension == "VK_EXT_extended_dynamic_state3" ) || - ( extension == "VK_EXT_subpass_merge_feedback" ) || ( extension == "VK_EXT_shader_module_identifier" ) || - ( extension == "VK_EXT_rasterization_order_attachment_access" ) || ( extension == "VK_NV_optical_flow" ) || - ( extension == "VK_EXT_legacy_dithering" ) || ( extension == "VK_EXT_pipeline_protected_access" ) || ( extension == "VK_KHR_maintenance5" ) || - ( extension == "VK_KHR_ray_tracing_position_fetch" ) || ( extension == "VK_EXT_shader_object" ) || ( extension == "VK_QCOM_tile_properties" ) || - ( extension == "VK_SEC_amigo_profiling" ) || ( extension == "VK_QCOM_multiview_per_view_viewports" ) || - ( extension == "VK_NV_ray_tracing_invocation_reorder" ) || ( extension == "VK_EXT_mutable_descriptor_type" ) || - ( extension == "VK_ARM_shader_core_builtins" ) || ( extension == "VK_EXT_pipeline_library_group_handles" ) || - ( extension == "VK_EXT_dynamic_rendering_unused_attachments" ) || ( extension == "VK_KHR_cooperative_matrix" ) || - ( extension == "VK_QCOM_multiview_per_view_render_areas" ) || ( extension == "VK_EXT_attachment_feedback_loop_dynamic_state" ) + ( extension == "VK_EXT_nested_command_buffer" ) || ( extension == "VK_EXT_external_memory_acquire_unmodified" ) || + ( extension == "VK_EXT_extended_dynamic_state3" ) || ( extension == "VK_EXT_subpass_merge_feedback" ) || + ( extension == "VK_EXT_shader_module_identifier" ) || ( extension == "VK_EXT_rasterization_order_attachment_access" ) || + ( extension == "VK_NV_optical_flow" ) || ( extension == "VK_EXT_legacy_dithering" ) || ( extension == "VK_EXT_pipeline_protected_access" ) +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + || ( extension == "VK_ANDROID_external_format_resolve" ) +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + || ( extension == "VK_KHR_maintenance5" ) || ( extension == "VK_KHR_ray_tracing_position_fetch" ) || ( extension == "VK_EXT_shader_object" ) || + ( extension == "VK_QCOM_tile_properties" ) || ( extension == "VK_SEC_amigo_profiling" ) || ( extension == "VK_QCOM_multiview_per_view_viewports" ) || + ( extension == "VK_NV_ray_tracing_invocation_reorder" ) || ( extension == "VK_NV_extended_sparse_address_space" ) || + ( extension == "VK_EXT_mutable_descriptor_type" ) || ( extension == "VK_ARM_shader_core_builtins" ) || + ( extension == "VK_EXT_pipeline_library_group_handles" ) || ( extension == "VK_EXT_dynamic_rendering_unused_attachments" ) || + ( extension == "VK_NV_low_latency2" ) || ( extension == "VK_KHR_cooperative_matrix" ) || + ( extension == "VK_QCOM_multiview_per_view_render_areas" ) || ( extension == "VK_QCOM_image_processing2" ) || + ( extension == "VK_QCOM_filter_cubic_weights" ) || ( extension == "VK_QCOM_ycbcr_degamma" ) || ( extension == "VK_QCOM_filter_cubic_clamp" ) || + ( extension == "VK_EXT_attachment_feedback_loop_dynamic_state" ) #if defined( VK_USE_PLATFORM_SCREEN_QNX ) || ( extension == "VK_QNX_external_memory_screen_buffer" ) #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ - ; + || ( extension == "VK_MSFT_layered_driver" ) || ( extension == "VK_NV_descriptor_pool_overallocation" ); } VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR_20 bool isInstanceExtension( std::string const & extension ) diff --git a/thirdparty/vulkan/include/vulkan/vulkan_funcs.hpp b/thirdparty/vulkan/include/vulkan/vulkan_funcs.hpp index 1ab87369d8..32715f8ddc 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_funcs.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_funcs.hpp @@ -19495,6 +19495,17 @@ namespace VULKAN_HPP_NAMESPACE } #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch> + VULKAN_HPP_INLINE void Device::getDescriptorEXT( const VULKAN_HPP_NAMESPACE::DescriptorGetInfoEXT & descriptorInfo, + size_t dataSize, + void * pDescriptor, + Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + + d.vkGetDescriptorEXT( m_device, reinterpret_cast<const VkDescriptorGetInfoEXT *>( &descriptorInfo ), dataSize, pDescriptor ); + } + template <typename DescriptorType, typename Dispatch> VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE DescriptorType Device::getDescriptorEXT( const VULKAN_HPP_NAMESPACE::DescriptorGetInfoEXT & descriptorInfo, Dispatch const & d ) const VULKAN_HPP_NOEXCEPT @@ -22786,6 +22797,126 @@ namespace VULKAN_HPP_NAMESPACE } #endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + //=== VK_NV_low_latency2 === + + template <typename Dispatch> + VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE Result Device::setLatencySleepModeNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV * pSleepModeInfo, + Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + return static_cast<Result>( + d.vkSetLatencySleepModeNV( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkLatencySleepModeInfoNV *>( pSleepModeInfo ) ) ); + } + +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch> + VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::setLatencySleepModeNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV & sleepModeInfo, + Dispatch const & d ) const + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + + VkResult result = + d.vkSetLatencySleepModeNV( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkLatencySleepModeInfoNV *>( &sleepModeInfo ) ); + resultCheck( static_cast<VULKAN_HPP_NAMESPACE::Result>( result ), VULKAN_HPP_NAMESPACE_STRING "::Device::setLatencySleepModeNV" ); + + return createResultValueType( static_cast<VULKAN_HPP_NAMESPACE::Result>( result ) ); + } +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + + template <typename Dispatch> + VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE Result Device::latencySleepNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::LatencySleepInfoNV * pSleepInfo, + Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + return static_cast<Result>( + d.vkLatencySleepNV( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkLatencySleepInfoNV *>( pSleepInfo ) ) ); + } + +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch> + VULKAN_HPP_INLINE typename ResultValueType<void>::type + Device::latencySleepNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, const VULKAN_HPP_NAMESPACE::LatencySleepInfoNV & sleepInfo, Dispatch const & d ) const + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + + VkResult result = d.vkLatencySleepNV( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkLatencySleepInfoNV *>( &sleepInfo ) ); + resultCheck( static_cast<VULKAN_HPP_NAMESPACE::Result>( result ), VULKAN_HPP_NAMESPACE_STRING "::Device::latencySleepNV" ); + + return createResultValueType( static_cast<VULKAN_HPP_NAMESPACE::Result>( result ) ); + } +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + + template <typename Dispatch> + VULKAN_HPP_INLINE void Device::setLatencyMarkerNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV * pLatencyMarkerInfo, + Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + d.vkSetLatencyMarkerNV( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkSetLatencyMarkerInfoNV *>( pLatencyMarkerInfo ) ); + } + +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch> + VULKAN_HPP_INLINE void Device::setLatencyMarkerNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV & latencyMarkerInfo, + Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + + d.vkSetLatencyMarkerNV( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkSetLatencyMarkerInfoNV *>( &latencyMarkerInfo ) ); + } +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + + template <typename Dispatch> + VULKAN_HPP_INLINE void Device::getLatencyTimingsNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + uint32_t * pTimingCount, + VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV * pLatencyMarkerInfo, + Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + d.vkGetLatencyTimingsNV( + m_device, static_cast<VkSwapchainKHR>( swapchain ), pTimingCount, reinterpret_cast<VkGetLatencyMarkerInfoNV *>( pLatencyMarkerInfo ) ); + } + +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch> + VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE std::pair<uint32_t, VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV> + Device::getLatencyTimingsNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + + std::pair<uint32_t, VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV> data_; + uint32_t & timingCount = data_.first; + VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV & latencyMarkerInfo = data_.second; + d.vkGetLatencyTimingsNV( + m_device, static_cast<VkSwapchainKHR>( swapchain ), &timingCount, reinterpret_cast<VkGetLatencyMarkerInfoNV *>( &latencyMarkerInfo ) ); + + return data_; + } +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + + template <typename Dispatch> + VULKAN_HPP_INLINE void Queue::notifyOutOfBandNV( const VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV * pQueueTypeInfo, + Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + d.vkQueueNotifyOutOfBandNV( m_queue, reinterpret_cast<const VkOutOfBandQueueTypeInfoNV *>( pQueueTypeInfo ) ); + } + +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch> + VULKAN_HPP_INLINE void Queue::notifyOutOfBandNV( const VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV & queueTypeInfo, + Dispatch const & d ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION ); + + d.vkQueueNotifyOutOfBandNV( m_queue, reinterpret_cast<const VkOutOfBandQueueTypeInfoNV *>( &queueTypeInfo ) ); + } +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + //=== VK_KHR_cooperative_matrix === template <typename Dispatch> diff --git a/thirdparty/vulkan/include/vulkan/vulkan_handles.hpp b/thirdparty/vulkan/include/vulkan/vulkan_handles.hpp index 9e7304f90a..332561680f 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_handles.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_handles.hpp @@ -1438,6 +1438,10 @@ namespace VULKAN_HPP_NAMESPACE struct PipelinePropertiesIdentifierEXT; struct PhysicalDevicePipelinePropertiesFeaturesEXT; + //=== VK_EXT_frame_boundary === + struct PhysicalDeviceFrameBoundaryFeaturesEXT; + struct FrameBoundaryEXT; + //=== VK_EXT_multisampled_render_to_single_sampled === struct PhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT; struct SubpassResolvePerformanceQueryEXT; @@ -1562,6 +1566,10 @@ namespace VULKAN_HPP_NAMESPACE struct PhysicalDeviceImageProcessingFeaturesQCOM; struct PhysicalDeviceImageProcessingPropertiesQCOM; + //=== VK_EXT_nested_command_buffer === + struct PhysicalDeviceNestedCommandBufferFeaturesEXT; + struct PhysicalDeviceNestedCommandBufferPropertiesEXT; + //=== VK_EXT_external_memory_acquire_unmodified === struct ExternalMemoryAcquireUnmodifiedEXT; @@ -1608,6 +1616,13 @@ namespace VULKAN_HPP_NAMESPACE //=== VK_EXT_pipeline_protected_access === struct PhysicalDevicePipelineProtectedAccessFeaturesEXT; +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + //=== VK_ANDROID_external_format_resolve === + struct PhysicalDeviceExternalFormatResolveFeaturesANDROID; + struct PhysicalDeviceExternalFormatResolvePropertiesANDROID; + struct AndroidHardwareBufferFormatResolvePropertiesANDROID; +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + //=== VK_KHR_maintenance5 === struct PhysicalDeviceMaintenance5FeaturesKHR; struct PhysicalDeviceMaintenance5PropertiesKHR; @@ -1643,6 +1658,10 @@ namespace VULKAN_HPP_NAMESPACE struct PhysicalDeviceRayTracingInvocationReorderPropertiesNV; struct PhysicalDeviceRayTracingInvocationReorderFeaturesNV; + //=== VK_NV_extended_sparse_address_space === + struct PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + struct PhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + //=== VK_EXT_mutable_descriptor_type === struct PhysicalDeviceMutableDescriptorTypeFeaturesEXT; using PhysicalDeviceMutableDescriptorTypeFeaturesVALVE = PhysicalDeviceMutableDescriptorTypeFeaturesEXT; @@ -1661,6 +1680,17 @@ namespace VULKAN_HPP_NAMESPACE //=== VK_EXT_dynamic_rendering_unused_attachments === struct PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT; + //=== VK_NV_low_latency2 === + struct LatencySleepModeInfoNV; + struct LatencySleepInfoNV; + struct SetLatencyMarkerInfoNV; + struct GetLatencyMarkerInfoNV; + struct LatencyTimingsFrameReportNV; + struct LatencySubmissionPresentIdNV; + struct SwapchainLatencyCreateInfoNV; + struct OutOfBandQueueTypeInfoNV; + struct LatencySurfaceCapabilitiesNV; + //=== VK_KHR_cooperative_matrix === struct CooperativeMatrixPropertiesKHR; struct PhysicalDeviceCooperativeMatrixFeaturesKHR; @@ -1670,6 +1700,23 @@ namespace VULKAN_HPP_NAMESPACE struct PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM; struct MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM; + //=== VK_QCOM_image_processing2 === + struct PhysicalDeviceImageProcessing2FeaturesQCOM; + struct PhysicalDeviceImageProcessing2PropertiesQCOM; + struct SamplerBlockMatchWindowCreateInfoQCOM; + + //=== VK_QCOM_filter_cubic_weights === + struct PhysicalDeviceCubicWeightsFeaturesQCOM; + struct SamplerCubicWeightsCreateInfoQCOM; + struct BlitImageCubicWeightsInfoQCOM; + + //=== VK_QCOM_ycbcr_degamma === + struct PhysicalDeviceYcbcrDegammaFeaturesQCOM; + struct SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; + + //=== VK_QCOM_filter_cubic_clamp === + struct PhysicalDeviceCubicClampFeaturesQCOM; + //=== VK_EXT_attachment_feedback_loop_dynamic_state === struct PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT; @@ -1682,6 +1729,12 @@ namespace VULKAN_HPP_NAMESPACE struct PhysicalDeviceExternalMemoryScreenBufferFeaturesQNX; #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ + //=== VK_MSFT_layered_driver === + struct PhysicalDeviceLayeredDriverPropertiesMSFT; + + //=== VK_NV_descriptor_pool_overallocation === + struct PhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + //=================================== //=== HANDLE forward declarations === //=================================== @@ -8173,6 +8226,17 @@ namespace VULKAN_HPP_NAMESPACE getCheckpointData2NV( CheckpointData2NVAllocator & checkpointData2NVAllocator, Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const; #endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + //=== VK_NV_low_latency2 === + + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + void notifyOutOfBandNV( const VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV * pQueueTypeInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + void notifyOutOfBandNV( const VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV & queueTypeInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + operator VkQueue() const VULKAN_HPP_NOEXCEPT { return m_queue; @@ -12363,6 +12427,11 @@ namespace VULKAN_HPP_NAMESPACE void * pDescriptor, Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + void getDescriptorEXT( const VULKAN_HPP_NAMESPACE::DescriptorGetInfoEXT & descriptorInfo, + size_t dataSize, + void * pDescriptor, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; template <typename DescriptorType, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> VULKAN_HPP_NODISCARD DescriptorType getDescriptorEXT( const VULKAN_HPP_NAMESPACE::DescriptorGetInfoEXT & descriptorInfo, Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; @@ -13117,6 +13186,53 @@ namespace VULKAN_HPP_NAMESPACE Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; #endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + //=== VK_NV_low_latency2 === + + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + VULKAN_HPP_NODISCARD Result setLatencySleepModeNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV * pSleepModeInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + typename ResultValueType<void>::type setLatencySleepModeNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV & sleepModeInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const; +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + VULKAN_HPP_NODISCARD Result latencySleepNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::LatencySleepInfoNV * pSleepInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + typename ResultValueType<void>::type latencySleepNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::LatencySleepInfoNV & sleepInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const; +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + void setLatencyMarkerNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV * pLatencyMarkerInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + void setLatencyMarkerNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + const VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV & latencyMarkerInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + void getLatencyTimingsNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + uint32_t * pTimingCount, + VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV * pLatencyMarkerInfo, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; +#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE + template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + VULKAN_HPP_NODISCARD std::pair<uint32_t, VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV> + getLatencyTimingsNV( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, + Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; +#endif /* VULKAN_HPP_DISABLE_ENHANCED_MODE */ + #if defined( VK_USE_PLATFORM_SCREEN_QNX ) //=== VK_QNX_external_memory_screen_buffer === diff --git a/thirdparty/vulkan/include/vulkan/vulkan_hash.hpp b/thirdparty/vulkan/include/vulkan/vulkan_hash.hpp index d194824807..fa35d2edcf 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_hash.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_hash.hpp @@ -977,6 +977,23 @@ namespace std # if defined( VK_USE_PLATFORM_ANDROID_KHR ) template <> + struct hash<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatResolvePropertiesANDROID> + { + std::size_t + operator()( VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatResolvePropertiesANDROID const & androidHardwareBufferFormatResolvePropertiesANDROID ) const + VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, androidHardwareBufferFormatResolvePropertiesANDROID.sType ); + VULKAN_HPP_HASH_COMBINE( seed, androidHardwareBufferFormatResolvePropertiesANDROID.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, androidHardwareBufferFormatResolvePropertiesANDROID.colorAttachmentFormat ); + return seed; + } + }; +# endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + +# if defined( VK_USE_PLATFORM_ANDROID_KHR ) + template <> struct hash<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID> { std::size_t @@ -1556,6 +1573,19 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::BlitImageCubicWeightsInfoQCOM> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::BlitImageCubicWeightsInfoQCOM const & blitImageCubicWeightsInfoQCOM ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, blitImageCubicWeightsInfoQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, blitImageCubicWeightsInfoQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, blitImageCubicWeightsInfoQCOM.cubicWeights ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::ImageSubresourceLayers> { std::size_t operator()( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers const & imageSubresourceLayers ) const VULKAN_HPP_NOEXCEPT @@ -4888,6 +4918,27 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::FrameBoundaryEXT> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::FrameBoundaryEXT const & frameBoundaryEXT ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.sType ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.flags ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.frameID ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.imageCount ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.pImages ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.bufferCount ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.pBuffers ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.tagName ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.tagSize ); + VULKAN_HPP_HASH_COMBINE( seed, frameBoundaryEXT.pTag ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo> { std::size_t operator()( VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo const & framebufferAttachmentImageInfo ) const VULKAN_HPP_NOEXCEPT @@ -5010,6 +5061,45 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV const & latencyTimingsFrameReportNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.presentID ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.inputSampleTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.simStartTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.simEndTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.renderSubmitStartTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.renderSubmitEndTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.presentStartTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.presentEndTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.driverStartTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.driverEndTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.osRenderQueueStartTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.osRenderQueueEndTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.gpuRenderStartTimeUs ); + VULKAN_HPP_HASH_COMBINE( seed, latencyTimingsFrameReportNV.gpuRenderEndTimeUs ); + return seed; + } + }; + + template <> + struct hash<VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV const & getLatencyMarkerInfoNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, getLatencyMarkerInfoNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, getLatencyMarkerInfoNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, getLatencyMarkerInfoNV.pTimings ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::VertexInputBindingDescription> { std::size_t operator()( VULKAN_HPP_NAMESPACE::VertexInputBindingDescription const & vertexInputBindingDescription ) const VULKAN_HPP_NOEXCEPT @@ -6238,6 +6328,62 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::LatencySleepInfoNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::LatencySleepInfoNV const & latencySleepInfoNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, latencySleepInfoNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, latencySleepInfoNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, latencySleepInfoNV.signalSemaphore ); + VULKAN_HPP_HASH_COMBINE( seed, latencySleepInfoNV.value ); + return seed; + } + }; + + template <> + struct hash<VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV const & latencySleepModeInfoNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, latencySleepModeInfoNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, latencySleepModeInfoNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, latencySleepModeInfoNV.lowLatencyMode ); + VULKAN_HPP_HASH_COMBINE( seed, latencySleepModeInfoNV.lowLatencyBoost ); + VULKAN_HPP_HASH_COMBINE( seed, latencySleepModeInfoNV.minimumIntervalUs ); + return seed; + } + }; + + template <> + struct hash<VULKAN_HPP_NAMESPACE::LatencySubmissionPresentIdNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::LatencySubmissionPresentIdNV const & latencySubmissionPresentIdNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, latencySubmissionPresentIdNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, latencySubmissionPresentIdNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, latencySubmissionPresentIdNV.presentID ); + return seed; + } + }; + + template <> + struct hash<VULKAN_HPP_NAMESPACE::LatencySurfaceCapabilitiesNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::LatencySurfaceCapabilitiesNV const & latencySurfaceCapabilitiesNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, latencySurfaceCapabilitiesNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, latencySurfaceCapabilitiesNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, latencySurfaceCapabilitiesNV.presentModeCount ); + VULKAN_HPP_HASH_COMBINE( seed, latencySurfaceCapabilitiesNV.pPresentModes ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::LayerProperties> { std::size_t operator()( VULKAN_HPP_NAMESPACE::LayerProperties const & layerProperties ) const VULKAN_HPP_NOEXCEPT @@ -6874,6 +7020,19 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV const & outOfBandQueueTypeInfoNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, outOfBandQueueTypeInfoNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, outOfBandQueueTypeInfoNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, outOfBandQueueTypeInfoNV.queueType ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PastPresentationTimingGOOGLE> { std::size_t operator()( VULKAN_HPP_NAMESPACE::PastPresentationTimingGOOGLE const & pastPresentationTimingGOOGLE ) const VULKAN_HPP_NOEXCEPT @@ -7467,6 +7626,33 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicClampFeaturesQCOM> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicClampFeaturesQCOM const & physicalDeviceCubicClampFeaturesQCOM ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceCubicClampFeaturesQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceCubicClampFeaturesQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceCubicClampFeaturesQCOM.cubicRangeClamp ); + return seed; + } + }; + + template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicWeightsFeaturesQCOM> + { + std::size_t + operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicWeightsFeaturesQCOM const & physicalDeviceCubicWeightsFeaturesQCOM ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceCubicWeightsFeaturesQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceCubicWeightsFeaturesQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceCubicWeightsFeaturesQCOM.selectableCubicWeights ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceCustomBorderColorFeaturesEXT> { std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceCustomBorderColorFeaturesEXT const & physicalDeviceCustomBorderColorFeaturesEXT ) const @@ -7732,6 +7918,20 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorPoolOverallocationFeaturesNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorPoolOverallocationFeaturesNV const & + physicalDeviceDescriptorPoolOverallocationFeaturesNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceDescriptorPoolOverallocationFeaturesNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceDescriptorPoolOverallocationFeaturesNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceDescriptorPoolOverallocationFeaturesNV.descriptorPoolOverallocation ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorSetHostMappingFeaturesVALVE> { std::size_t @@ -8043,6 +8243,37 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV> + { + std::size_t + operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const & physicalDeviceExtendedSparseAddressSpaceFeaturesNV ) const + VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExtendedSparseAddressSpaceFeaturesNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExtendedSparseAddressSpaceFeaturesNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExtendedSparseAddressSpaceFeaturesNV.extendedSparseAddressSpace ); + return seed; + } + }; + + template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpacePropertiesNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpacePropertiesNV const & + physicalDeviceExtendedSparseAddressSpacePropertiesNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExtendedSparseAddressSpacePropertiesNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExtendedSparseAddressSpacePropertiesNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExtendedSparseAddressSpacePropertiesNV.extendedSparseAddressSpaceSize ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExtendedSparseAddressSpacePropertiesNV.extendedSparseImageUsageFlags ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExtendedSparseAddressSpacePropertiesNV.extendedSparseBufferUsageFlags ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo> { std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo const & physicalDeviceExternalBufferInfo ) const VULKAN_HPP_NOEXCEPT @@ -8070,6 +8301,41 @@ namespace std } }; +# if defined( VK_USE_PLATFORM_ANDROID_KHR ) + template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolveFeaturesANDROID> + { + std::size_t + operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolveFeaturesANDROID const & physicalDeviceExternalFormatResolveFeaturesANDROID ) const + VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExternalFormatResolveFeaturesANDROID.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExternalFormatResolveFeaturesANDROID.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExternalFormatResolveFeaturesANDROID.externalFormatResolve ); + return seed; + } + }; +# endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + +# if defined( VK_USE_PLATFORM_ANDROID_KHR ) + template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolvePropertiesANDROID> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolvePropertiesANDROID const & + physicalDeviceExternalFormatResolvePropertiesANDROID ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExternalFormatResolvePropertiesANDROID.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExternalFormatResolvePropertiesANDROID.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExternalFormatResolvePropertiesANDROID.nullColorAttachmentWithExternalFormatResolve ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExternalFormatResolvePropertiesANDROID.externalFormatResolveChromaOffsetX ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceExternalFormatResolvePropertiesANDROID.externalFormatResolveChromaOffsetY ); + return seed; + } + }; +# endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalImageFormatInfo> { @@ -8428,6 +8694,20 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceFrameBoundaryFeaturesEXT> + { + std::size_t + operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceFrameBoundaryFeaturesEXT const & physicalDeviceFrameBoundaryFeaturesEXT ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceFrameBoundaryFeaturesEXT.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceFrameBoundaryFeaturesEXT.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceFrameBoundaryFeaturesEXT.frameBoundary ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceGlobalPriorityQueryFeaturesKHR> { std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceGlobalPriorityQueryFeaturesKHR const & physicalDeviceGlobalPriorityQueryFeaturesKHR ) const @@ -8642,6 +8922,34 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2FeaturesQCOM> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2FeaturesQCOM const & physicalDeviceImageProcessing2FeaturesQCOM ) const + VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceImageProcessing2FeaturesQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceImageProcessing2FeaturesQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceImageProcessing2FeaturesQCOM.textureBlockMatch2 ); + return seed; + } + }; + + template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2PropertiesQCOM> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2PropertiesQCOM const & physicalDeviceImageProcessing2PropertiesQCOM ) const + VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceImageProcessing2PropertiesQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceImageProcessing2PropertiesQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceImageProcessing2PropertiesQCOM.maxBlockMatchWindow ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessingFeaturesQCOM> { std::size_t @@ -8820,6 +9128,20 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceLayeredDriverPropertiesMSFT> + { + std::size_t + operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceLayeredDriverPropertiesMSFT const & physicalDeviceLayeredDriverPropertiesMSFT ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceLayeredDriverPropertiesMSFT.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceLayeredDriverPropertiesMSFT.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceLayeredDriverPropertiesMSFT.underlyingAPI ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceLegacyDitheringFeaturesEXT> { std::size_t @@ -9426,6 +9748,36 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferFeaturesEXT> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferFeaturesEXT const & physicalDeviceNestedCommandBufferFeaturesEXT ) const + VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceNestedCommandBufferFeaturesEXT.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceNestedCommandBufferFeaturesEXT.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceNestedCommandBufferFeaturesEXT.nestedCommandBuffer ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceNestedCommandBufferFeaturesEXT.nestedCommandBufferRendering ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceNestedCommandBufferFeaturesEXT.nestedCommandBufferSimultaneousUse ); + return seed; + } + }; + + template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferPropertiesEXT> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferPropertiesEXT const & physicalDeviceNestedCommandBufferPropertiesEXT ) const + VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceNestedCommandBufferPropertiesEXT.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceNestedCommandBufferPropertiesEXT.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceNestedCommandBufferPropertiesEXT.maxCommandBufferNestingLevel ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceNonSeamlessCubeMapFeaturesEXT> { std::size_t operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceNonSeamlessCubeMapFeaturesEXT const & physicalDeviceNonSeamlessCubeMapFeaturesEXT ) const @@ -11537,6 +11889,20 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrDegammaFeaturesQCOM> + { + std::size_t + operator()( VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrDegammaFeaturesQCOM const & physicalDeviceYcbcrDegammaFeaturesQCOM ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceYcbcrDegammaFeaturesQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceYcbcrDegammaFeaturesQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, physicalDeviceYcbcrDegammaFeaturesQCOM.ycbcrDegamma ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrImageArraysFeaturesEXT> { std::size_t @@ -13121,6 +13487,21 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::SamplerBlockMatchWindowCreateInfoQCOM> + { + std::size_t + operator()( VULKAN_HPP_NAMESPACE::SamplerBlockMatchWindowCreateInfoQCOM const & samplerBlockMatchWindowCreateInfoQCOM ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, samplerBlockMatchWindowCreateInfoQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, samplerBlockMatchWindowCreateInfoQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, samplerBlockMatchWindowCreateInfoQCOM.windowExtent ); + VULKAN_HPP_HASH_COMBINE( seed, samplerBlockMatchWindowCreateInfoQCOM.windowCompareMode ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::SamplerBorderColorComponentMappingCreateInfoEXT> { std::size_t operator()( @@ -13177,6 +13558,19 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::SamplerCubicWeightsCreateInfoQCOM> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::SamplerCubicWeightsCreateInfoQCOM const & samplerCubicWeightsCreateInfoQCOM ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, samplerCubicWeightsCreateInfoQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, samplerCubicWeightsCreateInfoQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, samplerCubicWeightsCreateInfoQCOM.cubicWeights ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::SamplerReductionModeCreateInfo> { std::size_t operator()( VULKAN_HPP_NAMESPACE::SamplerReductionModeCreateInfo const & samplerReductionModeCreateInfo ) const VULKAN_HPP_NOEXCEPT @@ -13236,6 +13630,21 @@ namespace std } }; + template <> + struct hash<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const & samplerYcbcrConversionYcbcrDegammaCreateInfoQCOM ) + const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, samplerYcbcrConversionYcbcrDegammaCreateInfoQCOM.sType ); + VULKAN_HPP_HASH_COMBINE( seed, samplerYcbcrConversionYcbcrDegammaCreateInfoQCOM.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, samplerYcbcrConversionYcbcrDegammaCreateInfoQCOM.enableYDegamma ); + VULKAN_HPP_HASH_COMBINE( seed, samplerYcbcrConversionYcbcrDegammaCreateInfoQCOM.enableCbCrDegamma ); + return seed; + } + }; + # if defined( VK_USE_PLATFORM_SCREEN_QNX ) template <> struct hash<VULKAN_HPP_NAMESPACE::ScreenBufferFormatPropertiesQNX> @@ -13412,6 +13821,20 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV const & setLatencyMarkerInfoNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, setLatencyMarkerInfoNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, setLatencyMarkerInfoNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, setLatencyMarkerInfoNV.presentID ); + VULKAN_HPP_HASH_COMBINE( seed, setLatencyMarkerInfoNV.marker ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::SetStateFlagsIndirectCommandNV> { std::size_t operator()( VULKAN_HPP_NAMESPACE::SetStateFlagsIndirectCommandNV const & setStateFlagsIndirectCommandNV ) const VULKAN_HPP_NOEXCEPT @@ -14028,6 +14451,19 @@ namespace std }; template <> + struct hash<VULKAN_HPP_NAMESPACE::SwapchainLatencyCreateInfoNV> + { + std::size_t operator()( VULKAN_HPP_NAMESPACE::SwapchainLatencyCreateInfoNV const & swapchainLatencyCreateInfoNV ) const VULKAN_HPP_NOEXCEPT + { + std::size_t seed = 0; + VULKAN_HPP_HASH_COMBINE( seed, swapchainLatencyCreateInfoNV.sType ); + VULKAN_HPP_HASH_COMBINE( seed, swapchainLatencyCreateInfoNV.pNext ); + VULKAN_HPP_HASH_COMBINE( seed, swapchainLatencyCreateInfoNV.latencyModeEnable ); + return seed; + } + }; + + template <> struct hash<VULKAN_HPP_NAMESPACE::SwapchainPresentBarrierCreateInfoNV> { std::size_t operator()( VULKAN_HPP_NAMESPACE::SwapchainPresentBarrierCreateInfoNV const & swapchainPresentBarrierCreateInfoNV ) const VULKAN_HPP_NOEXCEPT diff --git a/thirdparty/vulkan/include/vulkan/vulkan_hpp_macros.hpp b/thirdparty/vulkan/include/vulkan/vulkan_hpp_macros.hpp new file mode 100644 index 0000000000..13fa815f65 --- /dev/null +++ b/thirdparty/vulkan/include/vulkan/vulkan_hpp_macros.hpp @@ -0,0 +1,270 @@ +// Copyright 2015-2023 The Khronos Group Inc. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT +// + +// This header is generated from the Khronos Vulkan XML API Registry. + +#ifndef VULKAN_HPP_MACROS_HPP +#define VULKAN_HPP_MACROS_HPP + +#if defined( _MSVC_LANG ) +# define VULKAN_HPP_CPLUSPLUS _MSVC_LANG +#else +# define VULKAN_HPP_CPLUSPLUS __cplusplus +#endif + +#if 201703L < VULKAN_HPP_CPLUSPLUS +# define VULKAN_HPP_CPP_VERSION 20 +#elif 201402L < VULKAN_HPP_CPLUSPLUS +# define VULKAN_HPP_CPP_VERSION 17 +#elif 201103L < VULKAN_HPP_CPLUSPLUS +# define VULKAN_HPP_CPP_VERSION 14 +#elif 199711L < VULKAN_HPP_CPLUSPLUS +# define VULKAN_HPP_CPP_VERSION 11 +#else +# error "vulkan.hpp needs at least c++ standard version 11" +#endif + +#if defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) +# if !defined( VULKAN_HPP_NO_SMART_HANDLE ) +# define VULKAN_HPP_NO_SMART_HANDLE +# endif +#endif + +#if defined( VULKAN_HPP_NO_CONSTRUCTORS ) +# if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) +# define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS +# endif +# if !defined( VULKAN_HPP_NO_UNION_CONSTRUCTORS ) +# define VULKAN_HPP_NO_UNION_CONSTRUCTORS +# endif +#endif + +#if defined( VULKAN_HPP_NO_SETTERS ) +# if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) +# define VULKAN_HPP_NO_STRUCT_SETTERS +# endif +# if !defined( VULKAN_HPP_NO_UNION_SETTERS ) +# define VULKAN_HPP_NO_UNION_SETTERS +# endif +#endif + +#if !defined( VULKAN_HPP_ASSERT ) +# define VULKAN_HPP_ASSERT assert +#endif + +#if !defined( VULKAN_HPP_ASSERT_ON_RESULT ) +# define VULKAN_HPP_ASSERT_ON_RESULT VULKAN_HPP_ASSERT +#endif + +#if !defined( VULKAN_HPP_STATIC_ASSERT ) +# define VULKAN_HPP_STATIC_ASSERT static_assert +#endif + +#if !defined( VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL ) +# define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1 +#endif + +#if !defined( __has_include ) +# define __has_include( x ) false +#endif + +#if ( 201907 <= __cpp_lib_three_way_comparison ) && __has_include( <compare> ) && !defined( VULKAN_HPP_NO_SPACESHIP_OPERATOR ) +# define VULKAN_HPP_HAS_SPACESHIP_OPERATOR +#endif + +#if ( 201803 <= __cpp_lib_span ) +# define VULKAN_HPP_SUPPORT_SPAN +#endif + +// 32-bit vulkan is not typesafe for non-dispatchable handles, so don't allow copy constructors on this platform by default. +// To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION +#if ( VK_USE_64_BIT_PTR_DEFINES == 1 ) +# if !defined( VULKAN_HPP_TYPESAFE_CONVERSION ) +# define VULKAN_HPP_TYPESAFE_CONVERSION +# endif +#endif + +#if defined( __GNUC__ ) +# define GCC_VERSION ( __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) +#endif + +#if !defined( VULKAN_HPP_HAS_UNRESTRICTED_UNIONS ) +# if defined( __clang__ ) +# if __has_feature( cxx_unrestricted_unions ) +# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS +# endif +# elif defined( __GNUC__ ) +# if 40600 <= GCC_VERSION +# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS +# endif +# elif defined( _MSC_VER ) +# if 1900 <= _MSC_VER +# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS +# endif +# endif +#endif + +#if !defined( VULKAN_HPP_INLINE ) +# if defined( __clang__ ) +# if __has_attribute( always_inline ) +# define VULKAN_HPP_INLINE __attribute__( ( always_inline ) ) __inline__ +# else +# define VULKAN_HPP_INLINE inline +# endif +# elif defined( __GNUC__ ) +# define VULKAN_HPP_INLINE __attribute__( ( always_inline ) ) __inline__ +# elif defined( _MSC_VER ) +# define VULKAN_HPP_INLINE inline +# else +# define VULKAN_HPP_INLINE inline +# endif +#endif + +#if defined( VULKAN_HPP_TYPESAFE_CONVERSION ) +# define VULKAN_HPP_TYPESAFE_EXPLICIT +#else +# define VULKAN_HPP_TYPESAFE_EXPLICIT explicit +#endif + +#if defined( __cpp_constexpr ) +# define VULKAN_HPP_CONSTEXPR constexpr +# if 201304 <= __cpp_constexpr +# define VULKAN_HPP_CONSTEXPR_14 constexpr +# else +# define VULKAN_HPP_CONSTEXPR_14 +# endif +# if ( 201907 <= __cpp_constexpr ) && ( !defined( __GNUC__ ) || ( 110400 < GCC_VERSION ) ) +# define VULKAN_HPP_CONSTEXPR_20 constexpr +# else +# define VULKAN_HPP_CONSTEXPR_20 +# endif +# define VULKAN_HPP_CONST_OR_CONSTEXPR constexpr +#else +# define VULKAN_HPP_CONSTEXPR +# define VULKAN_HPP_CONSTEXPR_14 +# define VULKAN_HPP_CONST_OR_CONSTEXPR const +#endif + +#if !defined( VULKAN_HPP_CONSTEXPR_INLINE ) +# if 201606L <= __cpp_inline_variables +# define VULKAN_HPP_CONSTEXPR_INLINE VULKAN_HPP_CONSTEXPR inline +# else +# define VULKAN_HPP_CONSTEXPR_INLINE VULKAN_HPP_CONSTEXPR +# endif +#endif + +#if !defined( VULKAN_HPP_NOEXCEPT ) +# if defined( _MSC_VER ) && ( _MSC_VER <= 1800 ) +# define VULKAN_HPP_NOEXCEPT +# else +# define VULKAN_HPP_NOEXCEPT noexcept +# define VULKAN_HPP_HAS_NOEXCEPT 1 +# if defined( VULKAN_HPP_NO_EXCEPTIONS ) +# define VULKAN_HPP_NOEXCEPT_WHEN_NO_EXCEPTIONS noexcept +# else +# define VULKAN_HPP_NOEXCEPT_WHEN_NO_EXCEPTIONS +# endif +# endif +#endif + +#if 14 <= VULKAN_HPP_CPP_VERSION +# define VULKAN_HPP_DEPRECATED( msg ) [[deprecated( msg )]] +#else +# define VULKAN_HPP_DEPRECATED( msg ) +#endif + +#if ( 17 <= VULKAN_HPP_CPP_VERSION ) && !defined( VULKAN_HPP_NO_NODISCARD_WARNINGS ) +# define VULKAN_HPP_NODISCARD [[nodiscard]] +# if defined( VULKAN_HPP_NO_EXCEPTIONS ) +# define VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS [[nodiscard]] +# else +# define VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS +# endif +#else +# define VULKAN_HPP_NODISCARD +# define VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS +#endif + +#if !defined( VULKAN_HPP_NAMESPACE ) +# define VULKAN_HPP_NAMESPACE vk +#endif + +#define VULKAN_HPP_STRINGIFY2( text ) #text +#define VULKAN_HPP_STRINGIFY( text ) VULKAN_HPP_STRINGIFY2( text ) +#define VULKAN_HPP_NAMESPACE_STRING VULKAN_HPP_STRINGIFY( VULKAN_HPP_NAMESPACE ) + +#if !defined( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC ) +# if defined( VK_NO_PROTOTYPES ) +# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 +# else +# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 0 +# endif +#endif + +#if !defined( VULKAN_HPP_STORAGE_API ) +# if defined( VULKAN_HPP_STORAGE_SHARED ) +# if defined( _MSC_VER ) +# if defined( VULKAN_HPP_STORAGE_SHARED_EXPORT ) +# define VULKAN_HPP_STORAGE_API __declspec( dllexport ) +# else +# define VULKAN_HPP_STORAGE_API __declspec( dllimport ) +# endif +# elif defined( __clang__ ) || defined( __GNUC__ ) +# if defined( VULKAN_HPP_STORAGE_SHARED_EXPORT ) +# define VULKAN_HPP_STORAGE_API __attribute__( ( visibility( "default" ) ) ) +# else +# define VULKAN_HPP_STORAGE_API +# endif +# else +# define VULKAN_HPP_STORAGE_API +# pragma warning Unknown import / export semantics +# endif +# else +# define VULKAN_HPP_STORAGE_API +# endif +#endif + +namespace VULKAN_HPP_NAMESPACE +{ + class DispatchLoaderDynamic; +} // namespace VULKAN_HPP_NAMESPACE + +#if !defined( VULKAN_HPP_DEFAULT_DISPATCHER ) +# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 +# define VULKAN_HPP_DEFAULT_DISPATCHER ::VULKAN_HPP_NAMESPACE::defaultDispatchLoaderDynamic +# define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE \ + namespace VULKAN_HPP_NAMESPACE \ + { \ + VULKAN_HPP_STORAGE_API ::VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic defaultDispatchLoaderDynamic; \ + } +namespace VULKAN_HPP_NAMESPACE +{ + extern VULKAN_HPP_STORAGE_API VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic defaultDispatchLoaderDynamic; +} // namespace VULKAN_HPP_NAMESPACE +# else +# define VULKAN_HPP_DEFAULT_DISPATCHER ::VULKAN_HPP_NAMESPACE::getDispatchLoaderStatic() +# define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE +# endif +#endif + +#if !defined( VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ) +# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 +# define VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ::VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic +# else +# define VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ::VULKAN_HPP_NAMESPACE::DispatchLoaderStatic +# endif +#endif + +#if defined( VULKAN_HPP_NO_DEFAULT_DISPATCHER ) +# define VULKAN_HPP_DEFAULT_ARGUMENT_ASSIGNMENT +# define VULKAN_HPP_DEFAULT_ARGUMENT_NULLPTR_ASSIGNMENT +# define VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT +#else +# define VULKAN_HPP_DEFAULT_ARGUMENT_ASSIGNMENT = {} +# define VULKAN_HPP_DEFAULT_ARGUMENT_NULLPTR_ASSIGNMENT = nullptr +# define VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT = VULKAN_HPP_DEFAULT_DISPATCHER +#endif + +#endif
\ No newline at end of file diff --git a/thirdparty/vulkan/include/vulkan/vulkan_raii.hpp b/thirdparty/vulkan/include/vulkan/vulkan_raii.hpp index f065519ebf..f217921c91 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_raii.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_raii.hpp @@ -1663,6 +1663,13 @@ namespace VULKAN_HPP_NAMESPACE vkGetDynamicRenderingTilePropertiesQCOM = PFN_vkGetDynamicRenderingTilePropertiesQCOM( vkGetDeviceProcAddr( device, "vkGetDynamicRenderingTilePropertiesQCOM" ) ); + //=== VK_NV_low_latency2 === + vkSetLatencySleepModeNV = PFN_vkSetLatencySleepModeNV( vkGetDeviceProcAddr( device, "vkSetLatencySleepModeNV" ) ); + vkLatencySleepNV = PFN_vkLatencySleepNV( vkGetDeviceProcAddr( device, "vkLatencySleepNV" ) ); + vkSetLatencyMarkerNV = PFN_vkSetLatencyMarkerNV( vkGetDeviceProcAddr( device, "vkSetLatencyMarkerNV" ) ); + vkGetLatencyTimingsNV = PFN_vkGetLatencyTimingsNV( vkGetDeviceProcAddr( device, "vkGetLatencyTimingsNV" ) ); + vkQueueNotifyOutOfBandNV = PFN_vkQueueNotifyOutOfBandNV( vkGetDeviceProcAddr( device, "vkQueueNotifyOutOfBandNV" ) ); + //=== VK_EXT_attachment_feedback_loop_dynamic_state === vkCmdSetAttachmentFeedbackLoopEnableEXT = PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT( vkGetDeviceProcAddr( device, "vkCmdSetAttachmentFeedbackLoopEnableEXT" ) ); @@ -2507,6 +2514,13 @@ namespace VULKAN_HPP_NAMESPACE PFN_vkGetFramebufferTilePropertiesQCOM vkGetFramebufferTilePropertiesQCOM = 0; PFN_vkGetDynamicRenderingTilePropertiesQCOM vkGetDynamicRenderingTilePropertiesQCOM = 0; + //=== VK_NV_low_latency2 === + PFN_vkSetLatencySleepModeNV vkSetLatencySleepModeNV = 0; + PFN_vkLatencySleepNV vkLatencySleepNV = 0; + PFN_vkSetLatencyMarkerNV vkSetLatencyMarkerNV = 0; + PFN_vkGetLatencyTimingsNV vkGetLatencyTimingsNV = 0; + PFN_vkQueueNotifyOutOfBandNV vkQueueNotifyOutOfBandNV = 0; + //=== VK_EXT_attachment_feedback_loop_dynamic_state === PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT vkCmdSetAttachmentFeedbackLoopEnableEXT = 0; @@ -2694,7 +2708,8 @@ namespace VULKAN_HPP_NAMESPACE class Instance { public: - using CType = VkInstance; + using CType = VkInstance; + using CppType = vk::Instance; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eInstance; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -2953,7 +2968,8 @@ namespace VULKAN_HPP_NAMESPACE class PhysicalDevice { public: - using CType = VkPhysicalDevice; + using CType = VkPhysicalDevice; + using CppType = vk::PhysicalDevice; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::ePhysicalDevice; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -3411,7 +3427,8 @@ namespace VULKAN_HPP_NAMESPACE class Device { public: - using CType = VkDevice; + using CType = VkDevice; + using CppType = vk::Device; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDevice; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -4178,6 +4195,8 @@ namespace VULKAN_HPP_NAMESPACE //=== VK_EXT_descriptor_buffer === + void getDescriptorEXT( const VULKAN_HPP_NAMESPACE::DescriptorGetInfoEXT & descriptorInfo, size_t dataSize, void * pDescriptor ) const VULKAN_HPP_NOEXCEPT; + template <typename DescriptorType> VULKAN_HPP_NODISCARD DescriptorType getDescriptorEXT( const VULKAN_HPP_NAMESPACE::DescriptorGetInfoEXT & descriptorInfo ) const VULKAN_HPP_NOEXCEPT; @@ -4369,7 +4388,8 @@ namespace VULKAN_HPP_NAMESPACE class AccelerationStructureKHR { public: - using CType = VkAccelerationStructureKHR; + using CType = VkAccelerationStructureKHR; + using CppType = vk::AccelerationStructureKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eAccelerationStructureKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -4489,7 +4509,8 @@ namespace VULKAN_HPP_NAMESPACE class AccelerationStructureNV { public: - using CType = VkAccelerationStructureNV; + using CType = VkAccelerationStructureNV; + using CppType = vk::AccelerationStructureNV; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eAccelerationStructureNV; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -4617,7 +4638,8 @@ namespace VULKAN_HPP_NAMESPACE class Buffer { public: - using CType = VkBuffer; + using CType = VkBuffer; + using CppType = vk::Buffer; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eBuffer; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -4743,7 +4765,8 @@ namespace VULKAN_HPP_NAMESPACE class BufferCollectionFUCHSIA { public: - using CType = VkBufferCollectionFUCHSIA; + using CType = VkBufferCollectionFUCHSIA; + using CppType = vk::BufferCollectionFUCHSIA; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eBufferCollectionFUCHSIA; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -4872,7 +4895,8 @@ namespace VULKAN_HPP_NAMESPACE class BufferView { public: - using CType = VkBufferView; + using CType = VkBufferView; + using CppType = vk::BufferView; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eBufferView; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -4991,7 +5015,8 @@ namespace VULKAN_HPP_NAMESPACE class CommandPool { public: - using CType = VkCommandPool; + using CType = VkCommandPool; + using CppType = vk::CommandPool; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eCommandPool; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -5122,7 +5147,8 @@ namespace VULKAN_HPP_NAMESPACE class CommandBuffer { public: - using CType = VkCommandBuffer; + using CType = VkCommandBuffer; + using CppType = vk::CommandBuffer; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eCommandBuffer; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -6159,7 +6185,8 @@ namespace VULKAN_HPP_NAMESPACE class CuFunctionNVX { public: - using CType = VkCuFunctionNVX; + using CType = VkCuFunctionNVX; + using CppType = vk::CuFunctionNVX; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eCuFunctionNVX; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -6278,7 +6305,8 @@ namespace VULKAN_HPP_NAMESPACE class CuModuleNVX { public: - using CType = VkCuModuleNVX; + using CType = VkCuModuleNVX; + using CppType = vk::CuModuleNVX; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eCuModuleNVX; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -6397,7 +6425,8 @@ namespace VULKAN_HPP_NAMESPACE class DebugReportCallbackEXT { public: - using CType = VkDebugReportCallbackEXT; + using CType = VkDebugReportCallbackEXT; + using CppType = vk::DebugReportCallbackEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDebugReportCallbackEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -6517,7 +6546,8 @@ namespace VULKAN_HPP_NAMESPACE class DebugUtilsMessengerEXT { public: - using CType = VkDebugUtilsMessengerEXT; + using CType = VkDebugUtilsMessengerEXT; + using CppType = vk::DebugUtilsMessengerEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDebugUtilsMessengerEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -6637,7 +6667,8 @@ namespace VULKAN_HPP_NAMESPACE class DeferredOperationKHR { public: - using CType = VkDeferredOperationKHR; + using CType = VkDeferredOperationKHR; + using CppType = vk::DeferredOperationKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDeferredOperationKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -6763,7 +6794,8 @@ namespace VULKAN_HPP_NAMESPACE class DescriptorPool { public: - using CType = VkDescriptorPool; + using CType = VkDescriptorPool; + using CppType = vk::DescriptorPool; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDescriptorPool; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -6887,7 +6919,8 @@ namespace VULKAN_HPP_NAMESPACE class DescriptorSet { public: - using CType = VkDescriptorSet; + using CType = VkDescriptorSet; + using CppType = vk::DescriptorSet; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDescriptorSet; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -7032,7 +7065,8 @@ namespace VULKAN_HPP_NAMESPACE class DescriptorSetLayout { public: - using CType = VkDescriptorSetLayout; + using CType = VkDescriptorSetLayout; + using CppType = vk::DescriptorSetLayout; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDescriptorSetLayout; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -7158,7 +7192,8 @@ namespace VULKAN_HPP_NAMESPACE class DescriptorUpdateTemplate { public: - using CType = VkDescriptorUpdateTemplate; + using CType = VkDescriptorUpdateTemplate; + using CppType = vk::DescriptorUpdateTemplate; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDescriptorUpdateTemplate; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -7278,7 +7313,8 @@ namespace VULKAN_HPP_NAMESPACE class DeviceMemory { public: - using CType = VkDeviceMemory; + using CType = VkDeviceMemory; + using CppType = vk::DeviceMemory; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDeviceMemory; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -7417,7 +7453,8 @@ namespace VULKAN_HPP_NAMESPACE class DisplayKHR { public: - using CType = VkDisplayKHR; + using CType = VkDisplayKHR; + using CppType = vk::DisplayKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDisplayKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -7605,7 +7642,8 @@ namespace VULKAN_HPP_NAMESPACE class DisplayModeKHR { public: - using CType = VkDisplayModeKHR; + using CType = VkDisplayModeKHR; + using CppType = vk::DisplayModeKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eDisplayModeKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -7711,7 +7749,8 @@ namespace VULKAN_HPP_NAMESPACE class Event { public: - using CType = VkEvent; + using CType = VkEvent; + using CppType = vk::Event; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eEvent; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -7838,7 +7877,8 @@ namespace VULKAN_HPP_NAMESPACE class Fence { public: - using CType = VkFence; + using CType = VkFence; + using CppType = vk::Fence; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eFence; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -7999,7 +8039,8 @@ namespace VULKAN_HPP_NAMESPACE class Framebuffer { public: - using CType = VkFramebuffer; + using CType = VkFramebuffer; + using CppType = vk::Framebuffer; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eFramebuffer; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -8122,7 +8163,8 @@ namespace VULKAN_HPP_NAMESPACE class Image { public: - using CType = VkImage; + using CType = VkImage; + using CppType = vk::Image; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eImage; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -8274,7 +8316,8 @@ namespace VULKAN_HPP_NAMESPACE class ImageView { public: - using CType = VkImageView; + using CType = VkImageView; + using CppType = vk::ImageView; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eImageView; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -8397,7 +8440,8 @@ namespace VULKAN_HPP_NAMESPACE class IndirectCommandsLayoutNV { public: - using CType = VkIndirectCommandsLayoutNV; + using CType = VkIndirectCommandsLayoutNV; + using CppType = vk::IndirectCommandsLayoutNV; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eIndirectCommandsLayoutNV; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -8517,7 +8561,8 @@ namespace VULKAN_HPP_NAMESPACE class MicromapEXT { public: - using CType = VkMicromapEXT; + using CType = VkMicromapEXT; + using CppType = vk::MicromapEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eMicromapEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -8636,7 +8681,8 @@ namespace VULKAN_HPP_NAMESPACE class OpticalFlowSessionNV { public: - using CType = VkOpticalFlowSessionNV; + using CType = VkOpticalFlowSessionNV; + using CppType = vk::OpticalFlowSessionNV; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eOpticalFlowSessionNV; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -8762,7 +8808,8 @@ namespace VULKAN_HPP_NAMESPACE class PerformanceConfigurationINTEL { public: - using CType = VkPerformanceConfigurationINTEL; + using CType = VkPerformanceConfigurationINTEL; + using CppType = vk::PerformanceConfigurationINTEL; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::ePerformanceConfigurationINTEL; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -8866,7 +8913,8 @@ namespace VULKAN_HPP_NAMESPACE class PipelineCache { public: - using CType = VkPipelineCache; + using CType = VkPipelineCache; + using CppType = vk::PipelineCache; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::ePipelineCache; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -8992,7 +9040,8 @@ namespace VULKAN_HPP_NAMESPACE class Pipeline { public: - using CType = VkPipeline; + using CType = VkPipeline; + using CppType = vk::Pipeline; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::ePipeline; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -9420,7 +9469,8 @@ namespace VULKAN_HPP_NAMESPACE class PipelineLayout { public: - using CType = VkPipelineLayout; + using CType = VkPipelineLayout; + using CppType = vk::PipelineLayout; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::ePipelineLayout; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -9540,7 +9590,8 @@ namespace VULKAN_HPP_NAMESPACE class PrivateDataSlot { public: - using CType = VkPrivateDataSlot; + using CType = VkPrivateDataSlot; + using CppType = vk::PrivateDataSlot; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::ePrivateDataSlot; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -9660,7 +9711,8 @@ namespace VULKAN_HPP_NAMESPACE class QueryPool { public: - using CType = VkQueryPool; + using CType = VkQueryPool; + using CppType = vk::QueryPool; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eQueryPool; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -9804,7 +9856,8 @@ namespace VULKAN_HPP_NAMESPACE class Queue { public: - using CType = VkQueue; + using CType = VkQueue; + using CppType = vk::Queue; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eQueue; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -9929,6 +9982,10 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NODISCARD std::vector<VULKAN_HPP_NAMESPACE::CheckpointData2NV> getCheckpointData2NV() const; + //=== VK_NV_low_latency2 === + + void notifyOutOfBandNV( const VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV & queueTypeInfo ) const VULKAN_HPP_NOEXCEPT; + private: VULKAN_HPP_NAMESPACE::Queue m_queue = {}; VULKAN_HPP_NAMESPACE::VULKAN_HPP_RAII_NAMESPACE::DeviceDispatcher const * m_dispatcher = nullptr; @@ -9937,7 +9994,8 @@ namespace VULKAN_HPP_NAMESPACE class RenderPass { public: - using CType = VkRenderPass; + using CType = VkRenderPass; + using CppType = vk::RenderPass; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eRenderPass; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -10082,7 +10140,8 @@ namespace VULKAN_HPP_NAMESPACE class Sampler { public: - using CType = VkSampler; + using CType = VkSampler; + using CppType = vk::Sampler; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eSampler; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -10201,7 +10260,8 @@ namespace VULKAN_HPP_NAMESPACE class SamplerYcbcrConversion { public: - using CType = VkSamplerYcbcrConversion; + using CType = VkSamplerYcbcrConversion; + using CppType = vk::SamplerYcbcrConversion; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eSamplerYcbcrConversion; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -10321,7 +10381,8 @@ namespace VULKAN_HPP_NAMESPACE class Semaphore { public: - using CType = VkSemaphore; + using CType = VkSemaphore; + using CppType = vk::Semaphore; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eSemaphore; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -10448,7 +10509,8 @@ namespace VULKAN_HPP_NAMESPACE class ShaderEXT { public: - using CType = VkShaderEXT; + using CType = VkShaderEXT; + using CppType = vk::ShaderEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eShaderEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -10610,7 +10672,8 @@ namespace VULKAN_HPP_NAMESPACE class ShaderModule { public: - using CType = VkShaderModule; + using CType = VkShaderModule; + using CppType = vk::ShaderModule; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eShaderModule; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -10733,7 +10796,8 @@ namespace VULKAN_HPP_NAMESPACE class SurfaceKHR { public: - using CType = VkSurfaceKHR; + using CType = VkSurfaceKHR; + using CppType = vk::SurfaceKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eSurfaceKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -11130,7 +11194,8 @@ namespace VULKAN_HPP_NAMESPACE class SwapchainKHR { public: - using CType = VkSwapchainKHR; + using CType = VkSwapchainKHR; + using CppType = vk::SwapchainKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eSwapchainKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -11278,6 +11343,16 @@ namespace VULKAN_HPP_NAMESPACE void releaseFullScreenExclusiveModeEXT() const; # endif /*VK_USE_PLATFORM_WIN32_KHR*/ + //=== VK_NV_low_latency2 === + + void setLatencySleepModeNV( const VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV & sleepModeInfo ) const; + + void latencySleepNV( const VULKAN_HPP_NAMESPACE::LatencySleepInfoNV & sleepInfo ) const; + + void setLatencyMarkerNV( const VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV & latencyMarkerInfo ) const VULKAN_HPP_NOEXCEPT; + + VULKAN_HPP_NODISCARD std::pair<uint32_t, VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV> getLatencyTimingsNV() const VULKAN_HPP_NOEXCEPT; + private: VULKAN_HPP_NAMESPACE::Device m_device = {}; VULKAN_HPP_NAMESPACE::SwapchainKHR m_swapchain = {}; @@ -11326,7 +11401,8 @@ namespace VULKAN_HPP_NAMESPACE class ValidationCacheEXT { public: - using CType = VkValidationCacheEXT; + using CType = VkValidationCacheEXT; + using CppType = vk::ValidationCacheEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eValidationCacheEXT; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -11452,7 +11528,8 @@ namespace VULKAN_HPP_NAMESPACE class VideoSessionKHR { public: - using CType = VkVideoSessionKHR; + using CType = VkVideoSessionKHR; + using CppType = vk::VideoSessionKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eVideoSessionKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -11578,7 +11655,8 @@ namespace VULKAN_HPP_NAMESPACE class VideoSessionParametersKHR { public: - using CType = VkVideoSessionParametersKHR; + using CType = VkVideoSessionParametersKHR; + using CppType = vk::VideoSessionParametersKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eVideoSessionParametersKHR; static VULKAN_HPP_CONST_OR_CONSTEXPR VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT debugReportObjectType = @@ -18975,6 +19053,16 @@ namespace VULKAN_HPP_NAMESPACE return offset; } + VULKAN_HPP_INLINE void Device::getDescriptorEXT( const VULKAN_HPP_NAMESPACE::DescriptorGetInfoEXT & descriptorInfo, + size_t dataSize, + void * pDescriptor ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( getDispatcher()->vkGetDescriptorEXT && "Function <vkGetDescriptorEXT> requires <VK_EXT_descriptor_buffer>" ); + + getDispatcher()->vkGetDescriptorEXT( + static_cast<VkDevice>( m_device ), reinterpret_cast<const VkDescriptorGetInfoEXT *>( &descriptorInfo ), dataSize, pDescriptor ); + } + template <typename DescriptorType> VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE DescriptorType Device::getDescriptorEXT( const VULKAN_HPP_NAMESPACE::DescriptorGetInfoEXT & descriptorInfo ) const VULKAN_HPP_NOEXCEPT @@ -20639,6 +20727,58 @@ namespace VULKAN_HPP_NAMESPACE return properties; } + //=== VK_NV_low_latency2 === + + VULKAN_HPP_INLINE void SwapchainKHR::setLatencySleepModeNV( const VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV & sleepModeInfo ) const + { + VULKAN_HPP_ASSERT( getDispatcher()->vkSetLatencySleepModeNV && "Function <vkSetLatencySleepModeNV> requires <VK_NV_low_latency2>" ); + + VkResult result = getDispatcher()->vkSetLatencySleepModeNV( + static_cast<VkDevice>( m_device ), static_cast<VkSwapchainKHR>( m_swapchain ), reinterpret_cast<const VkLatencySleepModeInfoNV *>( &sleepModeInfo ) ); + resultCheck( static_cast<VULKAN_HPP_NAMESPACE::Result>( result ), VULKAN_HPP_NAMESPACE_STRING "::SwapchainKHR::setLatencySleepModeNV" ); + } + + VULKAN_HPP_INLINE void SwapchainKHR::latencySleepNV( const VULKAN_HPP_NAMESPACE::LatencySleepInfoNV & sleepInfo ) const + { + VULKAN_HPP_ASSERT( getDispatcher()->vkLatencySleepNV && "Function <vkLatencySleepNV> requires <VK_NV_low_latency2>" ); + + VkResult result = getDispatcher()->vkLatencySleepNV( + static_cast<VkDevice>( m_device ), static_cast<VkSwapchainKHR>( m_swapchain ), reinterpret_cast<const VkLatencySleepInfoNV *>( &sleepInfo ) ); + resultCheck( static_cast<VULKAN_HPP_NAMESPACE::Result>( result ), VULKAN_HPP_NAMESPACE_STRING "::SwapchainKHR::latencySleepNV" ); + } + + VULKAN_HPP_INLINE void SwapchainKHR::setLatencyMarkerNV( const VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV & latencyMarkerInfo ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( getDispatcher()->vkSetLatencyMarkerNV && "Function <vkSetLatencyMarkerNV> requires <VK_NV_low_latency2>" ); + + getDispatcher()->vkSetLatencyMarkerNV( static_cast<VkDevice>( m_device ), + static_cast<VkSwapchainKHR>( m_swapchain ), + reinterpret_cast<const VkSetLatencyMarkerInfoNV *>( &latencyMarkerInfo ) ); + } + + VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE std::pair<uint32_t, VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV> + SwapchainKHR::getLatencyTimingsNV() const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( getDispatcher()->vkGetLatencyTimingsNV && "Function <vkGetLatencyTimingsNV> requires <VK_NV_low_latency2>" ); + + std::pair<uint32_t, VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV> data_; + uint32_t & timingCount = data_.first; + VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV & latencyMarkerInfo = data_.second; + getDispatcher()->vkGetLatencyTimingsNV( static_cast<VkDevice>( m_device ), + static_cast<VkSwapchainKHR>( m_swapchain ), + &timingCount, + reinterpret_cast<VkGetLatencyMarkerInfoNV *>( &latencyMarkerInfo ) ); + + return data_; + } + + VULKAN_HPP_INLINE void Queue::notifyOutOfBandNV( const VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV & queueTypeInfo ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( getDispatcher()->vkQueueNotifyOutOfBandNV && "Function <vkQueueNotifyOutOfBandNV> requires <VK_NV_low_latency2>" ); + + getDispatcher()->vkQueueNotifyOutOfBandNV( static_cast<VkQueue>( m_queue ), reinterpret_cast<const VkOutOfBandQueueTypeInfoNV *>( &queueTypeInfo ) ); + } + //=== VK_KHR_cooperative_matrix === VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE std::vector<VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesKHR> @@ -20715,6 +20855,32 @@ namespace VULKAN_HPP_NAMESPACE } # endif /*VK_USE_PLATFORM_SCREEN_QNX*/ + //==================== + //=== RAII Helpers === + //==================== + + template <typename RAIIType> + std::vector<typename RAIIType::CppType> filterCppTypes( std::vector<RAIIType> const & raiiTypes ) + { + std::vector<typename RAIIType::CppType> cppTypes( raiiTypes.size() ); + std::transform( raiiTypes.begin(), raiiTypes.end(), cppTypes.begin(), []( RAIIType const & d ) { return *d; } ); + return cppTypes; + } + + template <typename RAIIType, class UnaryPredicate> + std::vector<typename RAIIType::CppType> filterCppTypes( std::vector<RAIIType> const & raiiTypes, UnaryPredicate p ) + { + std::vector<typename RAIIType::CppType> cppTypes; + for ( auto const & t : raiiTypes ) + { + if ( p( t ) ) + { + cppTypes.push_back( *t ); + } + } + return cppTypes; + } + } // namespace VULKAN_HPP_RAII_NAMESPACE } // namespace VULKAN_HPP_NAMESPACE #endif diff --git a/thirdparty/vulkan/include/vulkan/vulkan_shared.hpp b/thirdparty/vulkan/include/vulkan/vulkan_shared.hpp new file mode 100644 index 0000000000..7b1bb2338c --- /dev/null +++ b/thirdparty/vulkan/include/vulkan/vulkan_shared.hpp @@ -0,0 +1,988 @@ +// Copyright 2015-2023 The Khronos Group Inc. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT +// + +// This header is generated from the Khronos Vulkan XML API Registry. + +#ifndef VULKAN_SHARED_HPP +#define VULKAN_SHARED_HPP + +#include <atomic> // std::atomic_size_t +#include <vulkan/vulkan.hpp> + +namespace VULKAN_HPP_NAMESPACE +{ +#if !defined( VULKAN_HPP_NO_SMART_HANDLE ) + + template <typename HandleType> + class SharedHandleTraits; + + class NoDestructor + { + }; + + template <typename HandleType, typename = void> + struct HasDestructorType : std::false_type + { + }; + + template <typename HandleType> + struct HasDestructorType<HandleType, decltype( (void)typename SharedHandleTraits<HandleType>::DestructorType() )> : std::true_type + { + }; + + template <typename HandleType, typename Enable = void> + struct GetDestructorType + { + using type = NoDestructor; + }; + + template <typename HandleType> + struct GetDestructorType<HandleType, typename std::enable_if<HasDestructorType<HandleType>::value>::type> + { + using type = typename SharedHandleTraits<HandleType>::DestructorType; + }; + + template <class HandleType> + using DestructorTypeOf = typename GetDestructorType<HandleType>::type; + + template <class HandleType> + struct HasDestructor : std::integral_constant<bool, !std::is_same<DestructorTypeOf<HandleType>, NoDestructor>::value> + { + }; + + //===================================================================================================================== + + template <typename HandleType> + class SharedHandle; + + template <typename DestructorType, typename Deleter> + struct SharedHeader + { + SharedHeader( SharedHandle<DestructorType> parent, Deleter deleter = Deleter() ) VULKAN_HPP_NOEXCEPT + : parent( std::move( parent ) ) + , deleter( std::move( deleter ) ) + { + } + + SharedHandle<DestructorType> parent; + Deleter deleter; + }; + + template <typename Deleter> + struct SharedHeader<NoDestructor, Deleter> + { + SharedHeader( Deleter deleter = Deleter() ) VULKAN_HPP_NOEXCEPT : deleter( std::move( deleter ) ) {} + + Deleter deleter; + }; + + //===================================================================================================================== + + template <typename HeaderType> + class ReferenceCounter + { + public: + template <typename... Args> + ReferenceCounter( Args &&... control_args ) : m_header( std::forward<Args>( control_args )... ) + { + } + ReferenceCounter( const ReferenceCounter & ) = delete; + ReferenceCounter & operator=( const ReferenceCounter & ) = delete; + + public: + size_t addRef() VULKAN_HPP_NOEXCEPT + { + // Relaxed memory order is sufficient since this does not impose any ordering on other operations + return m_ref_cnt.fetch_add( 1, std::memory_order_relaxed ); + } + + size_t release() VULKAN_HPP_NOEXCEPT + { + // A release memory order to ensure that all releases are ordered + return m_ref_cnt.fetch_sub( 1, std::memory_order_release ); + } + + public: + std::atomic_size_t m_ref_cnt{ 1 }; + HeaderType m_header{}; + }; + + //===================================================================================================================== + + template <typename HandleType, typename HeaderType, typename ForwardType = SharedHandle<HandleType>> + class SharedHandleBase + { + public: + SharedHandleBase() = default; + + template <typename... Args> + SharedHandleBase( HandleType handle, Args &&... control_args ) + : m_control( new ReferenceCounter<HeaderType>( std::forward<Args>( control_args )... ) ), m_handle( handle ) + { + } + + SharedHandleBase( const SharedHandleBase & o ) VULKAN_HPP_NOEXCEPT + { + o.addRef(); + m_handle = o.m_handle; + m_control = o.m_control; + } + + SharedHandleBase( SharedHandleBase && o ) VULKAN_HPP_NOEXCEPT + : m_control( o.m_control ) + , m_handle( o.m_handle ) + { + o.m_handle = nullptr; + o.m_control = nullptr; + } + + SharedHandleBase & operator=( const SharedHandleBase & o ) VULKAN_HPP_NOEXCEPT + { + SharedHandleBase( o ).swap( *this ); + return *this; + } + + SharedHandleBase & operator=( SharedHandleBase && o ) VULKAN_HPP_NOEXCEPT + { + SharedHandleBase( std::move( o ) ).swap( *this ); + return *this; + } + + ~SharedHandleBase() + { + // only this function owns the last reference to the control block + // the same principle is used in the default deleter of std::shared_ptr + if ( m_control && ( m_control->release() == 1 ) ) + { + // noop in x86, but does thread synchronization in ARM + // it is required to ensure that last thread is getting to destroy the control block + // by ordering all atomic operations before this fence + std::atomic_thread_fence( std::memory_order_acquire ); + ForwardType::internalDestroy( getHeader(), m_handle ); + delete m_control; + } + } + + public: + HandleType get() const VULKAN_HPP_NOEXCEPT + { + return m_handle; + } + + HandleType operator*() const VULKAN_HPP_NOEXCEPT + { + return m_handle; + } + + explicit operator bool() const VULKAN_HPP_NOEXCEPT + { + return bool( m_handle ); + } + + const HandleType * operator->() const VULKAN_HPP_NOEXCEPT + { + return &m_handle; + } + + HandleType * operator->() VULKAN_HPP_NOEXCEPT + { + return &m_handle; + } + + void reset() VULKAN_HPP_NOEXCEPT + { + SharedHandleBase().swap( *this ); + } + + void swap( SharedHandleBase & o ) VULKAN_HPP_NOEXCEPT + { + std::swap( m_handle, o.m_handle ); + std::swap( m_control, o.m_control ); + } + + template <typename T = HandleType> + typename std::enable_if<HasDestructor<T>::value, const SharedHandle<DestructorTypeOf<HandleType>> &>::type getDestructorType() const VULKAN_HPP_NOEXCEPT + { + return getHeader().parent; + } + + protected: + template <typename T = HandleType> + static typename std::enable_if<!HasDestructor<T>::value, void>::type internalDestroy( const HeaderType & control, HandleType handle ) VULKAN_HPP_NOEXCEPT + { + control.deleter.destroy( handle ); + } + + template <typename T = HandleType> + static typename std::enable_if<HasDestructor<T>::value, void>::type internalDestroy( const HeaderType & control, HandleType handle ) VULKAN_HPP_NOEXCEPT + { + control.deleter.destroy( control.parent.get(), handle ); + } + + const HeaderType & getHeader() const VULKAN_HPP_NOEXCEPT + { + return m_control->m_header; + } + + private: + void addRef() const VULKAN_HPP_NOEXCEPT + { + if ( m_control ) + m_control->addRef(); + } + + protected: + ReferenceCounter<HeaderType> * m_control = nullptr; + HandleType m_handle{}; + }; + + template <typename HandleType> + class SharedHandle : public SharedHandleBase<HandleType, SharedHeader<DestructorTypeOf<HandleType>, typename SharedHandleTraits<HandleType>::deleter>> + { + private: + using BaseType = SharedHandleBase<HandleType, SharedHeader<DestructorTypeOf<HandleType>, typename SharedHandleTraits<HandleType>::deleter>>; + using DeleterType = typename SharedHandleTraits<HandleType>::deleter; + friend BaseType; + + public: + SharedHandle() = default; + + template <typename T = HandleType, typename = typename std::enable_if<HasDestructor<T>::value>::type> + explicit SharedHandle( HandleType handle, SharedHandle<DestructorTypeOf<HandleType>> parent, DeleterType deleter = DeleterType() ) VULKAN_HPP_NOEXCEPT + : BaseType( handle, std::move( parent ), std::move( deleter ) ) + { + } + + template <typename T = HandleType, typename = typename std::enable_if<!HasDestructor<T>::value>::type> + explicit SharedHandle( HandleType handle, DeleterType deleter = DeleterType() ) VULKAN_HPP_NOEXCEPT : BaseType( handle, std::move( deleter ) ) + { + } + + protected: + using BaseType::internalDestroy; + }; + + template <typename HandleType> + class SharedHandleTraits; + +// Silence the function cast warnings. +# if defined( __GNUC__ ) && !defined( __clang__ ) && !defined( __INTEL_COMPILER ) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wcast-function-type" +# endif + + template <typename HandleType> + class ObjectDestroyShared + { + public: + using DestructorType = typename SharedHandleTraits<HandleType>::DestructorType; + + template <class Dispatcher> + using DestroyFunctionPointerType = + typename std::conditional<HasDestructor<HandleType>::value, + void ( DestructorType::* )( HandleType, const AllocationCallbacks *, const Dispatcher & ) const, + void ( HandleType::* )( const AllocationCallbacks *, const Dispatcher & ) const>::type; + + using SelectorType = typename std::conditional<HasDestructor<HandleType>::value, DestructorType, HandleType>::type; + + template <typename Dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + ObjectDestroyShared( Optional<const AllocationCallbacks> allocationCallbacks VULKAN_HPP_DEFAULT_ARGUMENT_NULLPTR_ASSIGNMENT, + const Dispatcher & dispatch VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) + : m_destroy( reinterpret_cast<decltype( m_destroy )>( static_cast<DestroyFunctionPointerType<Dispatcher>>( &SelectorType::destroy ) ) ) + , m_dispatch( &dispatch ) + , m_allocationCallbacks( allocationCallbacks ) + { + } + + public: + template <typename T = HandleType> + typename std::enable_if<HasDestructor<T>::value, void>::type destroy( DestructorType parent, HandleType handle ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( m_destroy && m_dispatch ); + ( parent.*m_destroy )( handle, m_allocationCallbacks, *m_dispatch ); + } + + template <typename T = HandleType> + typename std::enable_if<!HasDestructor<T>::value, void>::type destroy( HandleType handle ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( m_destroy && m_dispatch ); + ( handle.*m_destroy )( m_allocationCallbacks, *m_dispatch ); + } + + private: + DestroyFunctionPointerType<DispatchLoaderBase> m_destroy = nullptr; + const DispatchLoaderBase * m_dispatch = nullptr; + Optional<const AllocationCallbacks> m_allocationCallbacks = nullptr; + }; + + template <typename HandleType> + class ObjectFreeShared + { + public: + using DestructorType = typename SharedHandleTraits<HandleType>::DestructorType; + + template <class Dispatcher> + using DestroyFunctionPointerType = void ( DestructorType::* )( HandleType, const AllocationCallbacks *, const Dispatcher & ) const; + + template <class Dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + ObjectFreeShared( Optional<const AllocationCallbacks> allocationCallbacks VULKAN_HPP_DEFAULT_ARGUMENT_NULLPTR_ASSIGNMENT, + const Dispatcher & dispatch VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) + : m_destroy( reinterpret_cast<decltype( m_destroy )>( static_cast<DestroyFunctionPointerType<Dispatcher>>( &DestructorType::free ) ) ) + , m_dispatch( &dispatch ) + , m_allocationCallbacks( allocationCallbacks ) + { + } + + public: + void destroy( DestructorType parent, HandleType handle ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( m_destroy && m_dispatch ); + ( parent.*m_destroy )( handle, m_allocationCallbacks, *m_dispatch ); + } + + private: + DestroyFunctionPointerType<DispatchLoaderBase> m_destroy = nullptr; + const DispatchLoaderBase * m_dispatch = nullptr; + Optional<const AllocationCallbacks> m_allocationCallbacks = nullptr; + }; + + template <typename HandleType> + class ObjectReleaseShared + { + public: + using DestructorType = typename SharedHandleTraits<HandleType>::DestructorType; + + template <class Dispatcher> + using DestroyFunctionPointerType = void ( DestructorType::* )( HandleType, const Dispatcher & ) const; + + template <class Dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + ObjectReleaseShared( const Dispatcher & dispatch VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) + : m_destroy( reinterpret_cast<decltype( m_destroy )>( static_cast<DestroyFunctionPointerType<Dispatcher>>( &DestructorType::release ) ) ) + , m_dispatch( &dispatch ) + { + } + + public: + void destroy( DestructorType parent, HandleType handle ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( m_destroy && m_dispatch ); + ( parent.*m_destroy )( handle, *m_dispatch ); + } + + private: + DestroyFunctionPointerType<DispatchLoaderBase> m_destroy = nullptr; + const DispatchLoaderBase * m_dispatch = nullptr; + }; + + template <typename HandleType, typename PoolType> + class PoolFreeShared + { + public: + using DestructorType = typename SharedHandleTraits<HandleType>::DestructorType; + + template <class Dispatcher> + using ReturnType = decltype( std::declval<DestructorType>().free( PoolType(), 0u, nullptr, Dispatcher() ) ); + + template <class Dispatcher> + using DestroyFunctionPointerType = ReturnType<Dispatcher> ( DestructorType::* )( PoolType, uint32_t, const HandleType *, const Dispatcher & ) const; + + PoolFreeShared() = default; + + template <class Dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> + PoolFreeShared( SharedHandle<PoolType> pool, const Dispatcher & dispatch VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) + : m_destroy( reinterpret_cast<decltype( m_destroy )>( static_cast<DestroyFunctionPointerType<Dispatcher>>( &DestructorType::free ) ) ) + , m_dispatch( &dispatch ) + , m_pool( std::move( pool ) ) + { + } + + public: + void destroy( DestructorType parent, HandleType handle ) const VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( m_destroy && m_dispatch ); + ( parent.*m_destroy )( m_pool.get(), 1u, &handle, *m_dispatch ); + } + + private: + DestroyFunctionPointerType<DispatchLoaderBase> m_destroy = nullptr; + const DispatchLoaderBase * m_dispatch = nullptr; + SharedHandle<PoolType> m_pool{}; + }; + +# if defined( __GNUC__ ) && !defined( __clang__ ) && !defined( __INTEL_COMPILER ) +# pragma GCC diagnostic pop +# endif + + //====================== + //=== SHARED HANDLEs === + //====================== + + //=== VK_VERSION_1_0 === + template <> + class SharedHandleTraits<Instance> + { + public: + using DestructorType = NoDestructor; + using deleter = ObjectDestroyShared<Instance>; + }; + using SharedInstance = SharedHandle<Instance>; + template <> + class SharedHandleTraits<Device> + { + public: + using DestructorType = NoDestructor; + using deleter = ObjectDestroyShared<Device>; + }; + using SharedDevice = SharedHandle<Device>; + template <> + class SharedHandleTraits<DeviceMemory> + { + public: + using DestructorType = Device; + using deleter = ObjectFreeShared<DeviceMemory>; + }; + using SharedDeviceMemory = SharedHandle<DeviceMemory>; + template <> + class SharedHandleTraits<Fence> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<Fence>; + }; + using SharedFence = SharedHandle<Fence>; + template <> + class SharedHandleTraits<Semaphore> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<Semaphore>; + }; + using SharedSemaphore = SharedHandle<Semaphore>; + template <> + class SharedHandleTraits<Event> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<Event>; + }; + using SharedEvent = SharedHandle<Event>; + template <> + class SharedHandleTraits<QueryPool> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<QueryPool>; + }; + using SharedQueryPool = SharedHandle<QueryPool>; + template <> + class SharedHandleTraits<Buffer> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<Buffer>; + }; + using SharedBuffer = SharedHandle<Buffer>; + template <> + class SharedHandleTraits<BufferView> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<BufferView>; + }; + using SharedBufferView = SharedHandle<BufferView>; + template <> + class SharedHandleTraits<Image> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<Image>; + }; + using SharedImage = SharedHandle<Image>; + template <> + class SharedHandleTraits<ImageView> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<ImageView>; + }; + using SharedImageView = SharedHandle<ImageView>; + template <> + class SharedHandleTraits<ShaderModule> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<ShaderModule>; + }; + using SharedShaderModule = SharedHandle<ShaderModule>; + template <> + class SharedHandleTraits<PipelineCache> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<PipelineCache>; + }; + using SharedPipelineCache = SharedHandle<PipelineCache>; + template <> + class SharedHandleTraits<Pipeline> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<Pipeline>; + }; + using SharedPipeline = SharedHandle<Pipeline>; + template <> + class SharedHandleTraits<PipelineLayout> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<PipelineLayout>; + }; + using SharedPipelineLayout = SharedHandle<PipelineLayout>; + template <> + class SharedHandleTraits<Sampler> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<Sampler>; + }; + using SharedSampler = SharedHandle<Sampler>; + template <> + class SharedHandleTraits<DescriptorPool> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<DescriptorPool>; + }; + using SharedDescriptorPool = SharedHandle<DescriptorPool>; + template <> + class SharedHandleTraits<DescriptorSet> + { + public: + using DestructorType = Device; + using deleter = PoolFreeShared<DescriptorSet, DescriptorPool>; + }; + using SharedDescriptorSet = SharedHandle<DescriptorSet>; + template <> + class SharedHandleTraits<DescriptorSetLayout> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<DescriptorSetLayout>; + }; + using SharedDescriptorSetLayout = SharedHandle<DescriptorSetLayout>; + template <> + class SharedHandleTraits<Framebuffer> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<Framebuffer>; + }; + using SharedFramebuffer = SharedHandle<Framebuffer>; + template <> + class SharedHandleTraits<RenderPass> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<RenderPass>; + }; + using SharedRenderPass = SharedHandle<RenderPass>; + template <> + class SharedHandleTraits<CommandPool> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<CommandPool>; + }; + using SharedCommandPool = SharedHandle<CommandPool>; + template <> + class SharedHandleTraits<CommandBuffer> + { + public: + using DestructorType = Device; + using deleter = PoolFreeShared<CommandBuffer, CommandPool>; + }; + using SharedCommandBuffer = SharedHandle<CommandBuffer>; + + //=== VK_VERSION_1_1 === + template <> + class SharedHandleTraits<SamplerYcbcrConversion> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<SamplerYcbcrConversion>; + }; + using SharedSamplerYcbcrConversion = SharedHandle<SamplerYcbcrConversion>; + using SharedSamplerYcbcrConversionKHR = SharedHandle<SamplerYcbcrConversion>; + template <> + class SharedHandleTraits<DescriptorUpdateTemplate> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<DescriptorUpdateTemplate>; + }; + using SharedDescriptorUpdateTemplate = SharedHandle<DescriptorUpdateTemplate>; + using SharedDescriptorUpdateTemplateKHR = SharedHandle<DescriptorUpdateTemplate>; + //=== VK_VERSION_1_3 === + template <> + class SharedHandleTraits<PrivateDataSlot> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<PrivateDataSlot>; + }; + using SharedPrivateDataSlot = SharedHandle<PrivateDataSlot>; + using SharedPrivateDataSlotEXT = SharedHandle<PrivateDataSlot>; + //=== VK_KHR_surface === + template <> + class SharedHandleTraits<SurfaceKHR> + { + public: + using DestructorType = Instance; + using deleter = ObjectDestroyShared<SurfaceKHR>; + }; + using SharedSurfaceKHR = SharedHandle<SurfaceKHR>; + + //=== VK_KHR_swapchain === + template <> + class SharedHandleTraits<SwapchainKHR> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<SwapchainKHR>; + }; + using SharedSwapchainKHR = SharedHandle<SwapchainKHR>; + + //=== VK_EXT_debug_report === + template <> + class SharedHandleTraits<DebugReportCallbackEXT> + { + public: + using DestructorType = Instance; + using deleter = ObjectDestroyShared<DebugReportCallbackEXT>; + }; + using SharedDebugReportCallbackEXT = SharedHandle<DebugReportCallbackEXT>; + + //=== VK_KHR_video_queue === + template <> + class SharedHandleTraits<VideoSessionKHR> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<VideoSessionKHR>; + }; + using SharedVideoSessionKHR = SharedHandle<VideoSessionKHR>; + template <> + class SharedHandleTraits<VideoSessionParametersKHR> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<VideoSessionParametersKHR>; + }; + using SharedVideoSessionParametersKHR = SharedHandle<VideoSessionParametersKHR>; + + //=== VK_NVX_binary_import === + template <> + class SharedHandleTraits<CuModuleNVX> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<CuModuleNVX>; + }; + using SharedCuModuleNVX = SharedHandle<CuModuleNVX>; + template <> + class SharedHandleTraits<CuFunctionNVX> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<CuFunctionNVX>; + }; + using SharedCuFunctionNVX = SharedHandle<CuFunctionNVX>; + + //=== VK_EXT_debug_utils === + template <> + class SharedHandleTraits<DebugUtilsMessengerEXT> + { + public: + using DestructorType = Instance; + using deleter = ObjectDestroyShared<DebugUtilsMessengerEXT>; + }; + using SharedDebugUtilsMessengerEXT = SharedHandle<DebugUtilsMessengerEXT>; + + //=== VK_KHR_acceleration_structure === + template <> + class SharedHandleTraits<AccelerationStructureKHR> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<AccelerationStructureKHR>; + }; + using SharedAccelerationStructureKHR = SharedHandle<AccelerationStructureKHR>; + + //=== VK_EXT_validation_cache === + template <> + class SharedHandleTraits<ValidationCacheEXT> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<ValidationCacheEXT>; + }; + using SharedValidationCacheEXT = SharedHandle<ValidationCacheEXT>; + + //=== VK_NV_ray_tracing === + template <> + class SharedHandleTraits<AccelerationStructureNV> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<AccelerationStructureNV>; + }; + using SharedAccelerationStructureNV = SharedHandle<AccelerationStructureNV>; + + //=== VK_KHR_deferred_host_operations === + template <> + class SharedHandleTraits<DeferredOperationKHR> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<DeferredOperationKHR>; + }; + using SharedDeferredOperationKHR = SharedHandle<DeferredOperationKHR>; + + //=== VK_NV_device_generated_commands === + template <> + class SharedHandleTraits<IndirectCommandsLayoutNV> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<IndirectCommandsLayoutNV>; + }; + using SharedIndirectCommandsLayoutNV = SharedHandle<IndirectCommandsLayoutNV>; + +# if defined( VK_USE_PLATFORM_FUCHSIA ) + //=== VK_FUCHSIA_buffer_collection === + template <> + class SharedHandleTraits<BufferCollectionFUCHSIA> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<BufferCollectionFUCHSIA>; + }; + using SharedBufferCollectionFUCHSIA = SharedHandle<BufferCollectionFUCHSIA>; +# endif /*VK_USE_PLATFORM_FUCHSIA*/ + + //=== VK_EXT_opacity_micromap === + template <> + class SharedHandleTraits<MicromapEXT> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<MicromapEXT>; + }; + using SharedMicromapEXT = SharedHandle<MicromapEXT>; + + //=== VK_NV_optical_flow === + template <> + class SharedHandleTraits<OpticalFlowSessionNV> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<OpticalFlowSessionNV>; + }; + using SharedOpticalFlowSessionNV = SharedHandle<OpticalFlowSessionNV>; + + //=== VK_EXT_shader_object === + template <> + class SharedHandleTraits<ShaderEXT> + { + public: + using DestructorType = Device; + using deleter = ObjectDestroyShared<ShaderEXT>; + }; + using SharedShaderEXT = SharedHandle<ShaderEXT>; + + enum class SwapchainOwns + { + no, + yes, + }; + + struct ImageHeader : SharedHeader<DestructorTypeOf<VULKAN_HPP_NAMESPACE::Image>, typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::Image>::deleter> + { + ImageHeader( + SharedHandle<DestructorTypeOf<VULKAN_HPP_NAMESPACE::Image>> parent, + typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::Image>::deleter deleter = typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::Image>::deleter(), + SwapchainOwns swapchainOwned = SwapchainOwns::no ) VULKAN_HPP_NOEXCEPT + : SharedHeader<DestructorTypeOf<VULKAN_HPP_NAMESPACE::Image>, typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::Image>::deleter>( std::move( parent ), + std::move( deleter ) ) + , swapchainOwned( swapchainOwned ) + { + } + + SwapchainOwns swapchainOwned = SwapchainOwns::no; + }; + + template <> + class SharedHandle<VULKAN_HPP_NAMESPACE::Image> : public SharedHandleBase<VULKAN_HPP_NAMESPACE::Image, ImageHeader> + { + using BaseType = SharedHandleBase<VULKAN_HPP_NAMESPACE::Image, ImageHeader>; + using DeleterType = typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::Image>::deleter; + friend BaseType; + + public: + SharedHandle() = default; + + explicit SharedHandle( VULKAN_HPP_NAMESPACE::Image handle, + SharedHandle<DestructorTypeOf<VULKAN_HPP_NAMESPACE::Image>> parent, + SwapchainOwns swapchain_owned = SwapchainOwns::no, + DeleterType deleter = DeleterType() ) VULKAN_HPP_NOEXCEPT + : BaseType( handle, std::move( parent ), std::move( deleter ), swapchain_owned ) + { + } + + protected: + static void internalDestroy( const ImageHeader & control, VULKAN_HPP_NAMESPACE::Image handle ) VULKAN_HPP_NOEXCEPT + { + if ( control.swapchainOwned == SwapchainOwns::no ) + { + control.deleter.destroy( control.parent.get(), handle ); + } + } + }; + + struct SwapchainHeader + { + SwapchainHeader( SharedHandle<VULKAN_HPP_NAMESPACE::SurfaceKHR> surface, + SharedHandle<DestructorTypeOf<VULKAN_HPP_NAMESPACE::SwapchainKHR>> parent, + typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::SwapchainKHR>::deleter deleter = + typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::SwapchainKHR>::deleter() ) VULKAN_HPP_NOEXCEPT + : surface( std::move( surface ) ) + , parent( std::move( parent ) ) + , deleter( std::move( deleter ) ) + { + } + + SharedHandle<VULKAN_HPP_NAMESPACE::SurfaceKHR> surface{}; + SharedHandle<DestructorTypeOf<VULKAN_HPP_NAMESPACE::SwapchainKHR>> parent{}; + typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::SwapchainKHR>::deleter deleter{}; + }; + + template <> + class SharedHandle<VULKAN_HPP_NAMESPACE::SwapchainKHR> : public SharedHandleBase<VULKAN_HPP_NAMESPACE::SwapchainKHR, SwapchainHeader> + { + using BaseType = SharedHandleBase<VULKAN_HPP_NAMESPACE::SwapchainKHR, SwapchainHeader>; + using DeleterType = typename SharedHandleTraits<VULKAN_HPP_NAMESPACE::SwapchainKHR>::deleter; + friend BaseType; + + public: + SharedHandle() = default; + + explicit SharedHandle( VULKAN_HPP_NAMESPACE::SwapchainKHR handle, + SharedHandle<DestructorTypeOf<VULKAN_HPP_NAMESPACE::SwapchainKHR>> parent, + SharedHandle<VULKAN_HPP_NAMESPACE::SurfaceKHR> surface, + DeleterType deleter = DeleterType() ) VULKAN_HPP_NOEXCEPT + : BaseType( handle, std::move( surface ), std::move( parent ), std::move( deleter ) ) + { + } + + public: + const SharedHandle<VULKAN_HPP_NAMESPACE::SurfaceKHR> & getSurface() const VULKAN_HPP_NOEXCEPT + { + return getHeader().surface; + } + + protected: + using BaseType::internalDestroy; + }; + + template <typename HandleType, typename DestructorType> + class SharedHandleBaseNoDestroy : public SharedHandleBase<HandleType, DestructorType> + { + public: + using SharedHandleBase<HandleType, DestructorType>::SharedHandleBase; + + const DestructorType & getDestructorType() const VULKAN_HPP_NOEXCEPT + { + return SharedHandleBase<HandleType, DestructorType>::getHeader(); + } + + protected: + static void internalDestroy( const DestructorType &, HandleType ) VULKAN_HPP_NOEXCEPT {} + }; + + //=== VK_VERSION_1_0 === + + template <> + class SharedHandle<PhysicalDevice> : public SharedHandleBaseNoDestroy<PhysicalDevice, SharedInstance> + { + friend SharedHandleBase<PhysicalDevice, SharedInstance>; + + public: + SharedHandle() = default; + explicit SharedHandle( PhysicalDevice handle, SharedInstance parent ) noexcept + : SharedHandleBaseNoDestroy<PhysicalDevice, SharedInstance>( handle, std::move( parent ) ) + { + } + }; + using SharedPhysicalDevice = SharedHandle<PhysicalDevice>; + + template <> + class SharedHandle<Queue> : public SharedHandleBaseNoDestroy<Queue, SharedDevice> + { + friend SharedHandleBase<Queue, SharedDevice>; + + public: + SharedHandle() = default; + explicit SharedHandle( Queue handle, SharedDevice parent ) noexcept : SharedHandleBaseNoDestroy<Queue, SharedDevice>( handle, std::move( parent ) ) {} + }; + using SharedQueue = SharedHandle<Queue>; + + //=== VK_KHR_display === + + template <> + class SharedHandle<DisplayKHR> : public SharedHandleBaseNoDestroy<DisplayKHR, SharedPhysicalDevice> + { + friend SharedHandleBase<DisplayKHR, SharedPhysicalDevice>; + + public: + SharedHandle() = default; + explicit SharedHandle( DisplayKHR handle, SharedPhysicalDevice parent ) noexcept + : SharedHandleBaseNoDestroy<DisplayKHR, SharedPhysicalDevice>( handle, std::move( parent ) ) + { + } + }; + using SharedDisplayKHR = SharedHandle<DisplayKHR>; + + template <> + class SharedHandle<DisplayModeKHR> : public SharedHandleBaseNoDestroy<DisplayModeKHR, SharedDisplayKHR> + { + friend SharedHandleBase<DisplayModeKHR, SharedDisplayKHR>; + + public: + SharedHandle() = default; + explicit SharedHandle( DisplayModeKHR handle, SharedDisplayKHR parent ) noexcept + : SharedHandleBaseNoDestroy<DisplayModeKHR, SharedDisplayKHR>( handle, std::move( parent ) ) + { + } + }; + using SharedDisplayModeKHR = SharedHandle<DisplayModeKHR>; + + //=== VK_INTEL_performance_query === + + template <> + class SharedHandle<PerformanceConfigurationINTEL> : public SharedHandleBaseNoDestroy<PerformanceConfigurationINTEL, SharedDevice> + { + friend SharedHandleBase<PerformanceConfigurationINTEL, SharedDevice>; + + public: + SharedHandle() = default; + explicit SharedHandle( PerformanceConfigurationINTEL handle, SharedDevice parent ) noexcept + : SharedHandleBaseNoDestroy<PerformanceConfigurationINTEL, SharedDevice>( handle, std::move( parent ) ) + { + } + }; + using SharedPerformanceConfigurationINTEL = SharedHandle<PerformanceConfigurationINTEL>; +#endif // !VULKAN_HPP_NO_SMART_HANDLE +} // namespace VULKAN_HPP_NAMESPACE +#endif // VULKAN_SHARED_HPP diff --git a/thirdparty/vulkan/include/vulkan/vulkan_static_assertions.hpp b/thirdparty/vulkan/include/vulkan/vulkan_static_assertions.hpp index 1fb34dbc25..a42e54d2cf 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_static_assertions.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_static_assertions.hpp @@ -5882,6 +5882,20 @@ VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::Physical VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDevicePipelinePropertiesFeaturesEXT>::value, "PhysicalDevicePipelinePropertiesFeaturesEXT is not nothrow_move_constructible!" ); +//=== VK_EXT_frame_boundary === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceFrameBoundaryFeaturesEXT ) == sizeof( VkPhysicalDeviceFrameBoundaryFeaturesEXT ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceFrameBoundaryFeaturesEXT>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceFrameBoundaryFeaturesEXT>::value, + "PhysicalDeviceFrameBoundaryFeaturesEXT is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::FrameBoundaryEXT ) == sizeof( VkFrameBoundaryEXT ), "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::FrameBoundaryEXT>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::FrameBoundaryEXT>::value, + "FrameBoundaryEXT is not nothrow_move_constructible!" ); + //=== VK_EXT_multisampled_render_to_single_sampled === VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT ) == @@ -6405,6 +6419,24 @@ VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::Physical VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessingPropertiesQCOM>::value, "PhysicalDeviceImageProcessingPropertiesQCOM is not nothrow_move_constructible!" ); +//=== VK_EXT_nested_command_buffer === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferFeaturesEXT ) == + sizeof( VkPhysicalDeviceNestedCommandBufferFeaturesEXT ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferFeaturesEXT>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferFeaturesEXT>::value, + "PhysicalDeviceNestedCommandBufferFeaturesEXT is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferPropertiesEXT ) == + sizeof( VkPhysicalDeviceNestedCommandBufferPropertiesEXT ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferPropertiesEXT>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferPropertiesEXT>::value, + "PhysicalDeviceNestedCommandBufferPropertiesEXT is not nothrow_move_constructible!" ); + //=== VK_EXT_external_memory_acquire_unmodified === VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::ExternalMemoryAcquireUnmodifiedEXT ) == sizeof( VkExternalMemoryAcquireUnmodifiedEXT ), @@ -6613,6 +6645,34 @@ VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::Physical VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDevicePipelineProtectedAccessFeaturesEXT>::value, "PhysicalDevicePipelineProtectedAccessFeaturesEXT is not nothrow_move_constructible!" ); +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) +//=== VK_ANDROID_external_format_resolve === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolveFeaturesANDROID ) == + sizeof( VkPhysicalDeviceExternalFormatResolveFeaturesANDROID ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolveFeaturesANDROID>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolveFeaturesANDROID>::value, + "PhysicalDeviceExternalFormatResolveFeaturesANDROID is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolvePropertiesANDROID ) == + sizeof( VkPhysicalDeviceExternalFormatResolvePropertiesANDROID ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolvePropertiesANDROID>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolvePropertiesANDROID>::value, + "PhysicalDeviceExternalFormatResolvePropertiesANDROID is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatResolvePropertiesANDROID ) == + sizeof( VkAndroidHardwareBufferFormatResolvePropertiesANDROID ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatResolvePropertiesANDROID>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatResolvePropertiesANDROID>::value, + "AndroidHardwareBufferFormatResolvePropertiesANDROID is not nothrow_move_constructible!" ); +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + //=== VK_KHR_maintenance5 === VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMaintenance5FeaturesKHR ) == sizeof( VkPhysicalDeviceMaintenance5FeaturesKHR ), @@ -6754,6 +6814,24 @@ VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::Physical VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingInvocationReorderFeaturesNV>::value, "PhysicalDeviceRayTracingInvocationReorderFeaturesNV is not nothrow_move_constructible!" ); +//=== VK_NV_extended_sparse_address_space === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV ) == + sizeof( VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV>::value, + "PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpacePropertiesNV ) == + sizeof( VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpacePropertiesNV>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpacePropertiesNV>::value, + "PhysicalDeviceExtendedSparseAddressSpacePropertiesNV is not nothrow_move_constructible!" ); + //=== VK_EXT_mutable_descriptor_type === VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMutableDescriptorTypeFeaturesEXT ) == @@ -6815,6 +6893,61 @@ VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::Physical VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT>::value, "PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT is not nothrow_move_constructible!" ); +//=== VK_NV_low_latency2 === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV ) == sizeof( VkLatencySleepModeInfoNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV>::value, + "LatencySleepModeInfoNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::LatencySleepInfoNV ) == sizeof( VkLatencySleepInfoNV ), "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::LatencySleepInfoNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::LatencySleepInfoNV>::value, + "LatencySleepInfoNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV ) == sizeof( VkSetLatencyMarkerInfoNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV>::value, + "SetLatencyMarkerInfoNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV ) == sizeof( VkGetLatencyMarkerInfoNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV>::value, + "GetLatencyMarkerInfoNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV ) == sizeof( VkLatencyTimingsFrameReportNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV>::value, + "LatencyTimingsFrameReportNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::LatencySubmissionPresentIdNV ) == sizeof( VkLatencySubmissionPresentIdNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::LatencySubmissionPresentIdNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::LatencySubmissionPresentIdNV>::value, + "LatencySubmissionPresentIdNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::SwapchainLatencyCreateInfoNV ) == sizeof( VkSwapchainLatencyCreateInfoNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::SwapchainLatencyCreateInfoNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::SwapchainLatencyCreateInfoNV>::value, + "SwapchainLatencyCreateInfoNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV ) == sizeof( VkOutOfBandQueueTypeInfoNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV>::value, + "OutOfBandQueueTypeInfoNV is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::LatencySurfaceCapabilitiesNV ) == sizeof( VkLatencySurfaceCapabilitiesNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::LatencySurfaceCapabilitiesNV>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::LatencySurfaceCapabilitiesNV>::value, + "LatencySurfaceCapabilitiesNV is not nothrow_move_constructible!" ); + //=== VK_KHR_cooperative_matrix === VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesKHR ) == sizeof( VkCooperativeMatrixPropertiesKHR ), @@ -6856,6 +6989,77 @@ VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::Multivie VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM>::value, "MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM is not nothrow_move_constructible!" ); +//=== VK_QCOM_image_processing2 === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2FeaturesQCOM ) == sizeof( VkPhysicalDeviceImageProcessing2FeaturesQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2FeaturesQCOM>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2FeaturesQCOM>::value, + "PhysicalDeviceImageProcessing2FeaturesQCOM is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2PropertiesQCOM ) == + sizeof( VkPhysicalDeviceImageProcessing2PropertiesQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2PropertiesQCOM>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2PropertiesQCOM>::value, + "PhysicalDeviceImageProcessing2PropertiesQCOM is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::SamplerBlockMatchWindowCreateInfoQCOM ) == sizeof( VkSamplerBlockMatchWindowCreateInfoQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::SamplerBlockMatchWindowCreateInfoQCOM>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::SamplerBlockMatchWindowCreateInfoQCOM>::value, + "SamplerBlockMatchWindowCreateInfoQCOM is not nothrow_move_constructible!" ); + +//=== VK_QCOM_filter_cubic_weights === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicWeightsFeaturesQCOM ) == sizeof( VkPhysicalDeviceCubicWeightsFeaturesQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicWeightsFeaturesQCOM>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicWeightsFeaturesQCOM>::value, + "PhysicalDeviceCubicWeightsFeaturesQCOM is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::SamplerCubicWeightsCreateInfoQCOM ) == sizeof( VkSamplerCubicWeightsCreateInfoQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::SamplerCubicWeightsCreateInfoQCOM>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::SamplerCubicWeightsCreateInfoQCOM>::value, + "SamplerCubicWeightsCreateInfoQCOM is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::BlitImageCubicWeightsInfoQCOM ) == sizeof( VkBlitImageCubicWeightsInfoQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::BlitImageCubicWeightsInfoQCOM>::value, "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::BlitImageCubicWeightsInfoQCOM>::value, + "BlitImageCubicWeightsInfoQCOM is not nothrow_move_constructible!" ); + +//=== VK_QCOM_ycbcr_degamma === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrDegammaFeaturesQCOM ) == sizeof( VkPhysicalDeviceYcbcrDegammaFeaturesQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrDegammaFeaturesQCOM>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrDegammaFeaturesQCOM>::value, + "PhysicalDeviceYcbcrDegammaFeaturesQCOM is not nothrow_move_constructible!" ); + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM ) == + sizeof( VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM>::value, + "SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM is not nothrow_move_constructible!" ); + +//=== VK_QCOM_filter_cubic_clamp === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicClampFeaturesQCOM ) == sizeof( VkPhysicalDeviceCubicClampFeaturesQCOM ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicClampFeaturesQCOM>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicClampFeaturesQCOM>::value, + "PhysicalDeviceCubicClampFeaturesQCOM is not nothrow_move_constructible!" ); + //=== VK_EXT_attachment_feedback_loop_dynamic_state === VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT ) == @@ -6901,4 +7105,23 @@ VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPAC "PhysicalDeviceExternalMemoryScreenBufferFeaturesQNX is not nothrow_move_constructible!" ); #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ +//=== VK_MSFT_layered_driver === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceLayeredDriverPropertiesMSFT ) == sizeof( VkPhysicalDeviceLayeredDriverPropertiesMSFT ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceLayeredDriverPropertiesMSFT>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceLayeredDriverPropertiesMSFT>::value, + "PhysicalDeviceLayeredDriverPropertiesMSFT is not nothrow_move_constructible!" ); + +//=== VK_NV_descriptor_pool_overallocation === + +VULKAN_HPP_STATIC_ASSERT( sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorPoolOverallocationFeaturesNV ) == + sizeof( VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV ), + "struct and wrapper have different size!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_standard_layout<VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorPoolOverallocationFeaturesNV>::value, + "struct wrapper is not a standard layout!" ); +VULKAN_HPP_STATIC_ASSERT( std::is_nothrow_move_constructible<VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorPoolOverallocationFeaturesNV>::value, + "PhysicalDeviceDescriptorPoolOverallocationFeaturesNV is not nothrow_move_constructible!" ); + #endif diff --git a/thirdparty/vulkan/include/vulkan/vulkan_structs.hpp b/thirdparty/vulkan/include/vulkan/vulkan_structs.hpp index 8ffe8f2e68..b7bf6450eb 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_structs.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_structs.hpp @@ -5098,6 +5098,94 @@ namespace VULKAN_HPP_NAMESPACE #endif /*VK_USE_PLATFORM_ANDROID_KHR*/ #if defined( VK_USE_PLATFORM_ANDROID_KHR ) + struct AndroidHardwareBufferFormatResolvePropertiesANDROID + { + using NativeType = VkAndroidHardwareBufferFormatResolvePropertiesANDROID; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eAndroidHardwareBufferFormatResolvePropertiesANDROID; + +# if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR + AndroidHardwareBufferFormatResolvePropertiesANDROID( VULKAN_HPP_NAMESPACE::Format colorAttachmentFormat_ = VULKAN_HPP_NAMESPACE::Format::eUndefined, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , colorAttachmentFormat( colorAttachmentFormat_ ) + { + } + + VULKAN_HPP_CONSTEXPR + AndroidHardwareBufferFormatResolvePropertiesANDROID( AndroidHardwareBufferFormatResolvePropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + AndroidHardwareBufferFormatResolvePropertiesANDROID( VkAndroidHardwareBufferFormatResolvePropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT + : AndroidHardwareBufferFormatResolvePropertiesANDROID( *reinterpret_cast<AndroidHardwareBufferFormatResolvePropertiesANDROID const *>( &rhs ) ) + { + } + + AndroidHardwareBufferFormatResolvePropertiesANDROID & + operator=( AndroidHardwareBufferFormatResolvePropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT = default; +# endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + AndroidHardwareBufferFormatResolvePropertiesANDROID & operator=( VkAndroidHardwareBufferFormatResolvePropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatResolvePropertiesANDROID const *>( &rhs ); + return *this; + } + + operator VkAndroidHardwareBufferFormatResolvePropertiesANDROID const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkAndroidHardwareBufferFormatResolvePropertiesANDROID *>( this ); + } + + operator VkAndroidHardwareBufferFormatResolvePropertiesANDROID &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkAndroidHardwareBufferFormatResolvePropertiesANDROID *>( this ); + } + +# if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Format const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, colorAttachmentFormat ); + } +# endif + +# if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( AndroidHardwareBufferFormatResolvePropertiesANDROID const & ) const = default; +# else + bool operator==( AndroidHardwareBufferFormatResolvePropertiesANDROID const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( colorAttachmentFormat == rhs.colorAttachmentFormat ); +# endif + } + + bool operator!=( AndroidHardwareBufferFormatResolvePropertiesANDROID const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +# endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAndroidHardwareBufferFormatResolvePropertiesANDROID; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Format colorAttachmentFormat = VULKAN_HPP_NAMESPACE::Format::eUndefined; + }; + + template <> + struct CppType<StructureType, StructureType::eAndroidHardwareBufferFormatResolvePropertiesANDROID> + { + using Type = AndroidHardwareBufferFormatResolvePropertiesANDROID; + }; +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) struct AndroidHardwareBufferPropertiesANDROID { using NativeType = VkAndroidHardwareBufferPropertiesANDROID; @@ -9691,6 +9779,104 @@ namespace VULKAN_HPP_NAMESPACE using Type = BindVideoSessionMemoryInfoKHR; }; + struct BlitImageCubicWeightsInfoQCOM + { + using NativeType = VkBlitImageCubicWeightsInfoQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eBlitImageCubicWeightsInfoQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR + BlitImageCubicWeightsInfoQCOM( VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM cubicWeights_ = VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM::eCatmullRom, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , cubicWeights( cubicWeights_ ) + { + } + + VULKAN_HPP_CONSTEXPR BlitImageCubicWeightsInfoQCOM( BlitImageCubicWeightsInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + BlitImageCubicWeightsInfoQCOM( VkBlitImageCubicWeightsInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : BlitImageCubicWeightsInfoQCOM( *reinterpret_cast<BlitImageCubicWeightsInfoQCOM const *>( &rhs ) ) + { + } + + BlitImageCubicWeightsInfoQCOM & operator=( BlitImageCubicWeightsInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + BlitImageCubicWeightsInfoQCOM & operator=( VkBlitImageCubicWeightsInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BlitImageCubicWeightsInfoQCOM const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 BlitImageCubicWeightsInfoQCOM & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 BlitImageCubicWeightsInfoQCOM & setCubicWeights( VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM cubicWeights_ ) VULKAN_HPP_NOEXCEPT + { + cubicWeights = cubicWeights_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkBlitImageCubicWeightsInfoQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkBlitImageCubicWeightsInfoQCOM *>( this ); + } + + operator VkBlitImageCubicWeightsInfoQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkBlitImageCubicWeightsInfoQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, cubicWeights ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( BlitImageCubicWeightsInfoQCOM const & ) const = default; +#else + bool operator==( BlitImageCubicWeightsInfoQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( cubicWeights == rhs.cubicWeights ); +# endif + } + + bool operator!=( BlitImageCubicWeightsInfoQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBlitImageCubicWeightsInfoQCOM; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM cubicWeights = VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM::eCatmullRom; + }; + + template <> + struct CppType<StructureType, StructureType::eBlitImageCubicWeightsInfoQCOM> + { + using Type = BlitImageCubicWeightsInfoQCOM; + }; + struct ImageSubresourceLayers { using NativeType = VkImageSubresourceLayers; @@ -36596,6 +36782,235 @@ namespace VULKAN_HPP_NAMESPACE using Type = FragmentShadingRateAttachmentInfoKHR; }; + struct FrameBoundaryEXT + { + using NativeType = VkFrameBoundaryEXT; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eFrameBoundaryEXT; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR FrameBoundaryEXT( VULKAN_HPP_NAMESPACE::FrameBoundaryFlagsEXT flags_ = {}, + uint64_t frameID_ = {}, + uint32_t imageCount_ = {}, + const VULKAN_HPP_NAMESPACE::Image * pImages_ = {}, + uint32_t bufferCount_ = {}, + const VULKAN_HPP_NAMESPACE::Buffer * pBuffers_ = {}, + uint64_t tagName_ = {}, + size_t tagSize_ = {}, + const void * pTag_ = {}, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , flags( flags_ ) + , frameID( frameID_ ) + , imageCount( imageCount_ ) + , pImages( pImages_ ) + , bufferCount( bufferCount_ ) + , pBuffers( pBuffers_ ) + , tagName( tagName_ ) + , tagSize( tagSize_ ) + , pTag( pTag_ ) + { + } + + VULKAN_HPP_CONSTEXPR FrameBoundaryEXT( FrameBoundaryEXT const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + FrameBoundaryEXT( VkFrameBoundaryEXT const & rhs ) VULKAN_HPP_NOEXCEPT : FrameBoundaryEXT( *reinterpret_cast<FrameBoundaryEXT const *>( &rhs ) ) {} + +# if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) + template <typename T> + FrameBoundaryEXT( VULKAN_HPP_NAMESPACE::FrameBoundaryFlagsEXT flags_, + uint64_t frameID_, + VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<const VULKAN_HPP_NAMESPACE::Image> const & images_, + VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<const VULKAN_HPP_NAMESPACE::Buffer> const & buffers_ = {}, + uint64_t tagName_ = {}, + VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<const T> const & tag_ = {}, + const void * pNext_ = nullptr ) + : pNext( pNext_ ) + , flags( flags_ ) + , frameID( frameID_ ) + , imageCount( static_cast<uint32_t>( images_.size() ) ) + , pImages( images_.data() ) + , bufferCount( static_cast<uint32_t>( buffers_.size() ) ) + , pBuffers( buffers_.data() ) + , tagName( tagName_ ) + , tagSize( tag_.size() * sizeof( T ) ) + , pTag( tag_.data() ) + { + } +# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ + + FrameBoundaryEXT & operator=( FrameBoundaryEXT const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + FrameBoundaryEXT & operator=( VkFrameBoundaryEXT const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FrameBoundaryEXT const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setFlags( VULKAN_HPP_NAMESPACE::FrameBoundaryFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT + { + flags = flags_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setFrameID( uint64_t frameID_ ) VULKAN_HPP_NOEXCEPT + { + frameID = frameID_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setImageCount( uint32_t imageCount_ ) VULKAN_HPP_NOEXCEPT + { + imageCount = imageCount_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setPImages( const VULKAN_HPP_NAMESPACE::Image * pImages_ ) VULKAN_HPP_NOEXCEPT + { + pImages = pImages_; + return *this; + } + +# if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) + FrameBoundaryEXT & setImages( VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<const VULKAN_HPP_NAMESPACE::Image> const & images_ ) VULKAN_HPP_NOEXCEPT + { + imageCount = static_cast<uint32_t>( images_.size() ); + pImages = images_.data(); + return *this; + } +# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setBufferCount( uint32_t bufferCount_ ) VULKAN_HPP_NOEXCEPT + { + bufferCount = bufferCount_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setPBuffers( const VULKAN_HPP_NAMESPACE::Buffer * pBuffers_ ) VULKAN_HPP_NOEXCEPT + { + pBuffers = pBuffers_; + return *this; + } + +# if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) + FrameBoundaryEXT & setBuffers( VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<const VULKAN_HPP_NAMESPACE::Buffer> const & buffers_ ) VULKAN_HPP_NOEXCEPT + { + bufferCount = static_cast<uint32_t>( buffers_.size() ); + pBuffers = buffers_.data(); + return *this; + } +# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setTagName( uint64_t tagName_ ) VULKAN_HPP_NOEXCEPT + { + tagName = tagName_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setTagSize( size_t tagSize_ ) VULKAN_HPP_NOEXCEPT + { + tagSize = tagSize_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 FrameBoundaryEXT & setPTag( const void * pTag_ ) VULKAN_HPP_NOEXCEPT + { + pTag = pTag_; + return *this; + } + +# if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) + template <typename T> + FrameBoundaryEXT & setTag( VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<const T> const & tag_ ) VULKAN_HPP_NOEXCEPT + { + tagSize = tag_.size() * sizeof( T ); + pTag = tag_.data(); + return *this; + } +# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkFrameBoundaryEXT const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkFrameBoundaryEXT *>( this ); + } + + operator VkFrameBoundaryEXT &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkFrameBoundaryEXT *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, + const void * const &, + VULKAN_HPP_NAMESPACE::FrameBoundaryFlagsEXT const &, + uint64_t const &, + uint32_t const &, + const VULKAN_HPP_NAMESPACE::Image * const &, + uint32_t const &, + const VULKAN_HPP_NAMESPACE::Buffer * const &, + uint64_t const &, + size_t const &, + const void * const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, flags, frameID, imageCount, pImages, bufferCount, pBuffers, tagName, tagSize, pTag ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( FrameBoundaryEXT const & ) const = default; +#else + bool operator==( FrameBoundaryEXT const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( flags == rhs.flags ) && ( frameID == rhs.frameID ) && ( imageCount == rhs.imageCount ) && + ( pImages == rhs.pImages ) && ( bufferCount == rhs.bufferCount ) && ( pBuffers == rhs.pBuffers ) && ( tagName == rhs.tagName ) && + ( tagSize == rhs.tagSize ) && ( pTag == rhs.pTag ); +# endif + } + + bool operator!=( FrameBoundaryEXT const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFrameBoundaryEXT; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::FrameBoundaryFlagsEXT flags = {}; + uint64_t frameID = {}; + uint32_t imageCount = {}; + const VULKAN_HPP_NAMESPACE::Image * pImages = {}; + uint32_t bufferCount = {}; + const VULKAN_HPP_NAMESPACE::Buffer * pBuffers = {}; + uint64_t tagName = {}; + size_t tagSize = {}; + const void * pTag = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eFrameBoundaryEXT> + { + using Type = FrameBoundaryEXT; + }; + struct FramebufferAttachmentImageInfo { using NativeType = VkFramebufferAttachmentImageInfo; @@ -37713,6 +38128,352 @@ namespace VULKAN_HPP_NAMESPACE using Type = GeneratedCommandsMemoryRequirementsInfoNV; }; + struct LatencyTimingsFrameReportNV + { + using NativeType = VkLatencyTimingsFrameReportNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eLatencyTimingsFrameReportNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR LatencyTimingsFrameReportNV( uint64_t presentID_ = {}, + uint64_t inputSampleTimeUs_ = {}, + uint64_t simStartTimeUs_ = {}, + uint64_t simEndTimeUs_ = {}, + uint64_t renderSubmitStartTimeUs_ = {}, + uint64_t renderSubmitEndTimeUs_ = {}, + uint64_t presentStartTimeUs_ = {}, + uint64_t presentEndTimeUs_ = {}, + uint64_t driverStartTimeUs_ = {}, + uint64_t driverEndTimeUs_ = {}, + uint64_t osRenderQueueStartTimeUs_ = {}, + uint64_t osRenderQueueEndTimeUs_ = {}, + uint64_t gpuRenderStartTimeUs_ = {}, + uint64_t gpuRenderEndTimeUs_ = {}, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , presentID( presentID_ ) + , inputSampleTimeUs( inputSampleTimeUs_ ) + , simStartTimeUs( simStartTimeUs_ ) + , simEndTimeUs( simEndTimeUs_ ) + , renderSubmitStartTimeUs( renderSubmitStartTimeUs_ ) + , renderSubmitEndTimeUs( renderSubmitEndTimeUs_ ) + , presentStartTimeUs( presentStartTimeUs_ ) + , presentEndTimeUs( presentEndTimeUs_ ) + , driverStartTimeUs( driverStartTimeUs_ ) + , driverEndTimeUs( driverEndTimeUs_ ) + , osRenderQueueStartTimeUs( osRenderQueueStartTimeUs_ ) + , osRenderQueueEndTimeUs( osRenderQueueEndTimeUs_ ) + , gpuRenderStartTimeUs( gpuRenderStartTimeUs_ ) + , gpuRenderEndTimeUs( gpuRenderEndTimeUs_ ) + { + } + + VULKAN_HPP_CONSTEXPR LatencyTimingsFrameReportNV( LatencyTimingsFrameReportNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + LatencyTimingsFrameReportNV( VkLatencyTimingsFrameReportNV const & rhs ) VULKAN_HPP_NOEXCEPT + : LatencyTimingsFrameReportNV( *reinterpret_cast<LatencyTimingsFrameReportNV const *>( &rhs ) ) + { + } + + LatencyTimingsFrameReportNV & operator=( LatencyTimingsFrameReportNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + LatencyTimingsFrameReportNV & operator=( VkLatencyTimingsFrameReportNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setPresentID( uint64_t presentID_ ) VULKAN_HPP_NOEXCEPT + { + presentID = presentID_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setInputSampleTimeUs( uint64_t inputSampleTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + inputSampleTimeUs = inputSampleTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setSimStartTimeUs( uint64_t simStartTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + simStartTimeUs = simStartTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setSimEndTimeUs( uint64_t simEndTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + simEndTimeUs = simEndTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setRenderSubmitStartTimeUs( uint64_t renderSubmitStartTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + renderSubmitStartTimeUs = renderSubmitStartTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setRenderSubmitEndTimeUs( uint64_t renderSubmitEndTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + renderSubmitEndTimeUs = renderSubmitEndTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setPresentStartTimeUs( uint64_t presentStartTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + presentStartTimeUs = presentStartTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setPresentEndTimeUs( uint64_t presentEndTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + presentEndTimeUs = presentEndTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setDriverStartTimeUs( uint64_t driverStartTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + driverStartTimeUs = driverStartTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setDriverEndTimeUs( uint64_t driverEndTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + driverEndTimeUs = driverEndTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setOsRenderQueueStartTimeUs( uint64_t osRenderQueueStartTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + osRenderQueueStartTimeUs = osRenderQueueStartTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setOsRenderQueueEndTimeUs( uint64_t osRenderQueueEndTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + osRenderQueueEndTimeUs = osRenderQueueEndTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setGpuRenderStartTimeUs( uint64_t gpuRenderStartTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + gpuRenderStartTimeUs = gpuRenderStartTimeUs_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencyTimingsFrameReportNV & setGpuRenderEndTimeUs( uint64_t gpuRenderEndTimeUs_ ) VULKAN_HPP_NOEXCEPT + { + gpuRenderEndTimeUs = gpuRenderEndTimeUs_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkLatencyTimingsFrameReportNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkLatencyTimingsFrameReportNV *>( this ); + } + + operator VkLatencyTimingsFrameReportNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkLatencyTimingsFrameReportNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, + const void * const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &, + uint64_t const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, + pNext, + presentID, + inputSampleTimeUs, + simStartTimeUs, + simEndTimeUs, + renderSubmitStartTimeUs, + renderSubmitEndTimeUs, + presentStartTimeUs, + presentEndTimeUs, + driverStartTimeUs, + driverEndTimeUs, + osRenderQueueStartTimeUs, + osRenderQueueEndTimeUs, + gpuRenderStartTimeUs, + gpuRenderEndTimeUs ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( LatencyTimingsFrameReportNV const & ) const = default; +#else + bool operator==( LatencyTimingsFrameReportNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( presentID == rhs.presentID ) && ( inputSampleTimeUs == rhs.inputSampleTimeUs ) && + ( simStartTimeUs == rhs.simStartTimeUs ) && ( simEndTimeUs == rhs.simEndTimeUs ) && ( renderSubmitStartTimeUs == rhs.renderSubmitStartTimeUs ) && + ( renderSubmitEndTimeUs == rhs.renderSubmitEndTimeUs ) && ( presentStartTimeUs == rhs.presentStartTimeUs ) && + ( presentEndTimeUs == rhs.presentEndTimeUs ) && ( driverStartTimeUs == rhs.driverStartTimeUs ) && ( driverEndTimeUs == rhs.driverEndTimeUs ) && + ( osRenderQueueStartTimeUs == rhs.osRenderQueueStartTimeUs ) && ( osRenderQueueEndTimeUs == rhs.osRenderQueueEndTimeUs ) && + ( gpuRenderStartTimeUs == rhs.gpuRenderStartTimeUs ) && ( gpuRenderEndTimeUs == rhs.gpuRenderEndTimeUs ); +# endif + } + + bool operator!=( LatencyTimingsFrameReportNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eLatencyTimingsFrameReportNV; + const void * pNext = {}; + uint64_t presentID = {}; + uint64_t inputSampleTimeUs = {}; + uint64_t simStartTimeUs = {}; + uint64_t simEndTimeUs = {}; + uint64_t renderSubmitStartTimeUs = {}; + uint64_t renderSubmitEndTimeUs = {}; + uint64_t presentStartTimeUs = {}; + uint64_t presentEndTimeUs = {}; + uint64_t driverStartTimeUs = {}; + uint64_t driverEndTimeUs = {}; + uint64_t osRenderQueueStartTimeUs = {}; + uint64_t osRenderQueueEndTimeUs = {}; + uint64_t gpuRenderStartTimeUs = {}; + uint64_t gpuRenderEndTimeUs = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eLatencyTimingsFrameReportNV> + { + using Type = LatencyTimingsFrameReportNV; + }; + + struct GetLatencyMarkerInfoNV + { + using NativeType = VkGetLatencyMarkerInfoNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eGetLatencyMarkerInfoNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR GetLatencyMarkerInfoNV( VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV * pTimings_ = {}, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , pTimings( pTimings_ ) + { + } + + VULKAN_HPP_CONSTEXPR GetLatencyMarkerInfoNV( GetLatencyMarkerInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + GetLatencyMarkerInfoNV( VkGetLatencyMarkerInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + : GetLatencyMarkerInfoNV( *reinterpret_cast<GetLatencyMarkerInfoNV const *>( &rhs ) ) + { + } + + GetLatencyMarkerInfoNV & operator=( GetLatencyMarkerInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + GetLatencyMarkerInfoNV & operator=( VkGetLatencyMarkerInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GetLatencyMarkerInfoNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 GetLatencyMarkerInfoNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 GetLatencyMarkerInfoNV & setPTimings( VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV * pTimings_ ) VULKAN_HPP_NOEXCEPT + { + pTimings = pTimings_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkGetLatencyMarkerInfoNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkGetLatencyMarkerInfoNV *>( this ); + } + + operator VkGetLatencyMarkerInfoNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkGetLatencyMarkerInfoNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV * const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, pTimings ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( GetLatencyMarkerInfoNV const & ) const = default; +#else + bool operator==( GetLatencyMarkerInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( pTimings == rhs.pTimings ); +# endif + } + + bool operator!=( GetLatencyMarkerInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGetLatencyMarkerInfoNV; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::LatencyTimingsFrameReportNV * pTimings = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eGetLatencyMarkerInfoNV> + { + using Type = GetLatencyMarkerInfoNV; + }; + struct VertexInputBindingDescription { using NativeType = VkVertexInputBindingDescription; @@ -47598,6 +48359,448 @@ namespace VULKAN_HPP_NAMESPACE using Type = InstanceCreateInfo; }; + struct LatencySleepInfoNV + { + using NativeType = VkLatencySleepInfoNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eLatencySleepInfoNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR + LatencySleepInfoNV( VULKAN_HPP_NAMESPACE::Semaphore signalSemaphore_ = {}, uint64_t value_ = {}, const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , signalSemaphore( signalSemaphore_ ) + , value( value_ ) + { + } + + VULKAN_HPP_CONSTEXPR LatencySleepInfoNV( LatencySleepInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + LatencySleepInfoNV( VkLatencySleepInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT : LatencySleepInfoNV( *reinterpret_cast<LatencySleepInfoNV const *>( &rhs ) ) {} + + LatencySleepInfoNV & operator=( LatencySleepInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + LatencySleepInfoNV & operator=( VkLatencySleepInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::LatencySleepInfoNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 LatencySleepInfoNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencySleepInfoNV & setSignalSemaphore( VULKAN_HPP_NAMESPACE::Semaphore signalSemaphore_ ) VULKAN_HPP_NOEXCEPT + { + signalSemaphore = signalSemaphore_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencySleepInfoNV & setValue( uint64_t value_ ) VULKAN_HPP_NOEXCEPT + { + value = value_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkLatencySleepInfoNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkLatencySleepInfoNV *>( this ); + } + + operator VkLatencySleepInfoNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkLatencySleepInfoNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, VULKAN_HPP_NAMESPACE::Semaphore const &, uint64_t const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, signalSemaphore, value ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( LatencySleepInfoNV const & ) const = default; +#else + bool operator==( LatencySleepInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( signalSemaphore == rhs.signalSemaphore ) && ( value == rhs.value ); +# endif + } + + bool operator!=( LatencySleepInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eLatencySleepInfoNV; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::Semaphore signalSemaphore = {}; + uint64_t value = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eLatencySleepInfoNV> + { + using Type = LatencySleepInfoNV; + }; + + struct LatencySleepModeInfoNV + { + using NativeType = VkLatencySleepModeInfoNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eLatencySleepModeInfoNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR LatencySleepModeInfoNV( VULKAN_HPP_NAMESPACE::Bool32 lowLatencyMode_ = {}, + VULKAN_HPP_NAMESPACE::Bool32 lowLatencyBoost_ = {}, + uint32_t minimumIntervalUs_ = {}, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , lowLatencyMode( lowLatencyMode_ ) + , lowLatencyBoost( lowLatencyBoost_ ) + , minimumIntervalUs( minimumIntervalUs_ ) + { + } + + VULKAN_HPP_CONSTEXPR LatencySleepModeInfoNV( LatencySleepModeInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + LatencySleepModeInfoNV( VkLatencySleepModeInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + : LatencySleepModeInfoNV( *reinterpret_cast<LatencySleepModeInfoNV const *>( &rhs ) ) + { + } + + LatencySleepModeInfoNV & operator=( LatencySleepModeInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + LatencySleepModeInfoNV & operator=( VkLatencySleepModeInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::LatencySleepModeInfoNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 LatencySleepModeInfoNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencySleepModeInfoNV & setLowLatencyMode( VULKAN_HPP_NAMESPACE::Bool32 lowLatencyMode_ ) VULKAN_HPP_NOEXCEPT + { + lowLatencyMode = lowLatencyMode_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencySleepModeInfoNV & setLowLatencyBoost( VULKAN_HPP_NAMESPACE::Bool32 lowLatencyBoost_ ) VULKAN_HPP_NOEXCEPT + { + lowLatencyBoost = lowLatencyBoost_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencySleepModeInfoNV & setMinimumIntervalUs( uint32_t minimumIntervalUs_ ) VULKAN_HPP_NOEXCEPT + { + minimumIntervalUs = minimumIntervalUs_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkLatencySleepModeInfoNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkLatencySleepModeInfoNV *>( this ); + } + + operator VkLatencySleepModeInfoNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkLatencySleepModeInfoNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, + const void * const &, + VULKAN_HPP_NAMESPACE::Bool32 const &, + VULKAN_HPP_NAMESPACE::Bool32 const &, + uint32_t const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, lowLatencyMode, lowLatencyBoost, minimumIntervalUs ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( LatencySleepModeInfoNV const & ) const = default; +#else + bool operator==( LatencySleepModeInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( lowLatencyMode == rhs.lowLatencyMode ) && ( lowLatencyBoost == rhs.lowLatencyBoost ) && + ( minimumIntervalUs == rhs.minimumIntervalUs ); +# endif + } + + bool operator!=( LatencySleepModeInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eLatencySleepModeInfoNV; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 lowLatencyMode = {}; + VULKAN_HPP_NAMESPACE::Bool32 lowLatencyBoost = {}; + uint32_t minimumIntervalUs = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eLatencySleepModeInfoNV> + { + using Type = LatencySleepModeInfoNV; + }; + + struct LatencySubmissionPresentIdNV + { + using NativeType = VkLatencySubmissionPresentIdNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eLatencySubmissionPresentIdNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR LatencySubmissionPresentIdNV( uint64_t presentID_ = {}, const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , presentID( presentID_ ) + { + } + + VULKAN_HPP_CONSTEXPR LatencySubmissionPresentIdNV( LatencySubmissionPresentIdNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + LatencySubmissionPresentIdNV( VkLatencySubmissionPresentIdNV const & rhs ) VULKAN_HPP_NOEXCEPT + : LatencySubmissionPresentIdNV( *reinterpret_cast<LatencySubmissionPresentIdNV const *>( &rhs ) ) + { + } + + LatencySubmissionPresentIdNV & operator=( LatencySubmissionPresentIdNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + LatencySubmissionPresentIdNV & operator=( VkLatencySubmissionPresentIdNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::LatencySubmissionPresentIdNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 LatencySubmissionPresentIdNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencySubmissionPresentIdNV & setPresentID( uint64_t presentID_ ) VULKAN_HPP_NOEXCEPT + { + presentID = presentID_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkLatencySubmissionPresentIdNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkLatencySubmissionPresentIdNV *>( this ); + } + + operator VkLatencySubmissionPresentIdNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkLatencySubmissionPresentIdNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, uint64_t const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, presentID ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( LatencySubmissionPresentIdNV const & ) const = default; +#else + bool operator==( LatencySubmissionPresentIdNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( presentID == rhs.presentID ); +# endif + } + + bool operator!=( LatencySubmissionPresentIdNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eLatencySubmissionPresentIdNV; + const void * pNext = {}; + uint64_t presentID = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eLatencySubmissionPresentIdNV> + { + using Type = LatencySubmissionPresentIdNV; + }; + + struct LatencySurfaceCapabilitiesNV + { + using NativeType = VkLatencySurfaceCapabilitiesNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eLatencySurfaceCapabilitiesNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR LatencySurfaceCapabilitiesNV( uint32_t presentModeCount_ = {}, + VULKAN_HPP_NAMESPACE::PresentModeKHR * pPresentModes_ = {}, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , presentModeCount( presentModeCount_ ) + , pPresentModes( pPresentModes_ ) + { + } + + VULKAN_HPP_CONSTEXPR LatencySurfaceCapabilitiesNV( LatencySurfaceCapabilitiesNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + LatencySurfaceCapabilitiesNV( VkLatencySurfaceCapabilitiesNV const & rhs ) VULKAN_HPP_NOEXCEPT + : LatencySurfaceCapabilitiesNV( *reinterpret_cast<LatencySurfaceCapabilitiesNV const *>( &rhs ) ) + { + } + +# if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) + LatencySurfaceCapabilitiesNV( VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<VULKAN_HPP_NAMESPACE::PresentModeKHR> const & presentModes_, + const void * pNext_ = nullptr ) + : pNext( pNext_ ), presentModeCount( static_cast<uint32_t>( presentModes_.size() ) ), pPresentModes( presentModes_.data() ) + { + } +# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ + + LatencySurfaceCapabilitiesNV & operator=( LatencySurfaceCapabilitiesNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + LatencySurfaceCapabilitiesNV & operator=( VkLatencySurfaceCapabilitiesNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::LatencySurfaceCapabilitiesNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 LatencySurfaceCapabilitiesNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencySurfaceCapabilitiesNV & setPresentModeCount( uint32_t presentModeCount_ ) VULKAN_HPP_NOEXCEPT + { + presentModeCount = presentModeCount_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 LatencySurfaceCapabilitiesNV & setPPresentModes( VULKAN_HPP_NAMESPACE::PresentModeKHR * pPresentModes_ ) VULKAN_HPP_NOEXCEPT + { + pPresentModes = pPresentModes_; + return *this; + } + +# if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) + LatencySurfaceCapabilitiesNV & + setPresentModes( VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<VULKAN_HPP_NAMESPACE::PresentModeKHR> const & presentModes_ ) VULKAN_HPP_NOEXCEPT + { + presentModeCount = static_cast<uint32_t>( presentModes_.size() ); + pPresentModes = presentModes_.data(); + return *this; + } +# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkLatencySurfaceCapabilitiesNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkLatencySurfaceCapabilitiesNV *>( this ); + } + + operator VkLatencySurfaceCapabilitiesNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkLatencySurfaceCapabilitiesNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, uint32_t const &, VULKAN_HPP_NAMESPACE::PresentModeKHR * const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, presentModeCount, pPresentModes ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( LatencySurfaceCapabilitiesNV const & ) const = default; +#else + bool operator==( LatencySurfaceCapabilitiesNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( presentModeCount == rhs.presentModeCount ) && ( pPresentModes == rhs.pPresentModes ); +# endif + } + + bool operator!=( LatencySurfaceCapabilitiesNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eLatencySurfaceCapabilitiesNV; + const void * pNext = {}; + uint32_t presentModeCount = {}; + VULKAN_HPP_NAMESPACE::PresentModeKHR * pPresentModes = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eLatencySurfaceCapabilitiesNV> + { + using Type = LatencySurfaceCapabilitiesNV; + }; + struct LayerProperties { using NativeType = VkLayerProperties; @@ -52383,6 +53586,103 @@ namespace VULKAN_HPP_NAMESPACE using Type = OpticalFlowSessionCreatePrivateDataInfoNV; }; + struct OutOfBandQueueTypeInfoNV + { + using NativeType = VkOutOfBandQueueTypeInfoNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eOutOfBandQueueTypeInfoNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR OutOfBandQueueTypeInfoNV( VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeNV queueType_ = VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeNV::eRender, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , queueType( queueType_ ) + { + } + + VULKAN_HPP_CONSTEXPR OutOfBandQueueTypeInfoNV( OutOfBandQueueTypeInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + OutOfBandQueueTypeInfoNV( VkOutOfBandQueueTypeInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + : OutOfBandQueueTypeInfoNV( *reinterpret_cast<OutOfBandQueueTypeInfoNV const *>( &rhs ) ) + { + } + + OutOfBandQueueTypeInfoNV & operator=( OutOfBandQueueTypeInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + OutOfBandQueueTypeInfoNV & operator=( VkOutOfBandQueueTypeInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeInfoNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 OutOfBandQueueTypeInfoNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 OutOfBandQueueTypeInfoNV & setQueueType( VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeNV queueType_ ) VULKAN_HPP_NOEXCEPT + { + queueType = queueType_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkOutOfBandQueueTypeInfoNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkOutOfBandQueueTypeInfoNV *>( this ); + } + + operator VkOutOfBandQueueTypeInfoNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkOutOfBandQueueTypeInfoNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeNV const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, queueType ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( OutOfBandQueueTypeInfoNV const & ) const = default; +#else + bool operator==( OutOfBandQueueTypeInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( queueType == rhs.queueType ); +# endif + } + + bool operator!=( OutOfBandQueueTypeInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eOutOfBandQueueTypeInfoNV; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeNV queueType = VULKAN_HPP_NAMESPACE::OutOfBandQueueTypeNV::eRender; + }; + + template <> + struct CppType<StructureType, StructureType::eOutOfBandQueueTypeInfoNV> + { + using Type = OutOfBandQueueTypeInfoNV; + }; + struct PastPresentationTimingGOOGLE { using NativeType = VkPastPresentationTimingGOOGLE; @@ -56634,6 +57934,200 @@ namespace VULKAN_HPP_NAMESPACE using Type = PhysicalDeviceCoverageReductionModeFeaturesNV; }; + struct PhysicalDeviceCubicClampFeaturesQCOM + { + using NativeType = VkPhysicalDeviceCubicClampFeaturesQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceCubicClampFeaturesQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceCubicClampFeaturesQCOM( VULKAN_HPP_NAMESPACE::Bool32 cubicRangeClamp_ = {}, void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , cubicRangeClamp( cubicRangeClamp_ ) + { + } + + VULKAN_HPP_CONSTEXPR PhysicalDeviceCubicClampFeaturesQCOM( PhysicalDeviceCubicClampFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceCubicClampFeaturesQCOM( VkPhysicalDeviceCubicClampFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceCubicClampFeaturesQCOM( *reinterpret_cast<PhysicalDeviceCubicClampFeaturesQCOM const *>( &rhs ) ) + { + } + + PhysicalDeviceCubicClampFeaturesQCOM & operator=( PhysicalDeviceCubicClampFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceCubicClampFeaturesQCOM & operator=( VkPhysicalDeviceCubicClampFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicClampFeaturesQCOM const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceCubicClampFeaturesQCOM & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceCubicClampFeaturesQCOM & setCubicRangeClamp( VULKAN_HPP_NAMESPACE::Bool32 cubicRangeClamp_ ) VULKAN_HPP_NOEXCEPT + { + cubicRangeClamp = cubicRangeClamp_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceCubicClampFeaturesQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceCubicClampFeaturesQCOM *>( this ); + } + + operator VkPhysicalDeviceCubicClampFeaturesQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceCubicClampFeaturesQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, cubicRangeClamp ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceCubicClampFeaturesQCOM const & ) const = default; +#else + bool operator==( PhysicalDeviceCubicClampFeaturesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( cubicRangeClamp == rhs.cubicRangeClamp ); +# endif + } + + bool operator!=( PhysicalDeviceCubicClampFeaturesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceCubicClampFeaturesQCOM; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 cubicRangeClamp = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceCubicClampFeaturesQCOM> + { + using Type = PhysicalDeviceCubicClampFeaturesQCOM; + }; + + struct PhysicalDeviceCubicWeightsFeaturesQCOM + { + using NativeType = VkPhysicalDeviceCubicWeightsFeaturesQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceCubicWeightsFeaturesQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceCubicWeightsFeaturesQCOM( VULKAN_HPP_NAMESPACE::Bool32 selectableCubicWeights_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , selectableCubicWeights( selectableCubicWeights_ ) + { + } + + VULKAN_HPP_CONSTEXPR PhysicalDeviceCubicWeightsFeaturesQCOM( PhysicalDeviceCubicWeightsFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceCubicWeightsFeaturesQCOM( VkPhysicalDeviceCubicWeightsFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceCubicWeightsFeaturesQCOM( *reinterpret_cast<PhysicalDeviceCubicWeightsFeaturesQCOM const *>( &rhs ) ) + { + } + + PhysicalDeviceCubicWeightsFeaturesQCOM & operator=( PhysicalDeviceCubicWeightsFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceCubicWeightsFeaturesQCOM & operator=( VkPhysicalDeviceCubicWeightsFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceCubicWeightsFeaturesQCOM const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceCubicWeightsFeaturesQCOM & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceCubicWeightsFeaturesQCOM & + setSelectableCubicWeights( VULKAN_HPP_NAMESPACE::Bool32 selectableCubicWeights_ ) VULKAN_HPP_NOEXCEPT + { + selectableCubicWeights = selectableCubicWeights_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceCubicWeightsFeaturesQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceCubicWeightsFeaturesQCOM *>( this ); + } + + operator VkPhysicalDeviceCubicWeightsFeaturesQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceCubicWeightsFeaturesQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, selectableCubicWeights ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceCubicWeightsFeaturesQCOM const & ) const = default; +#else + bool operator==( PhysicalDeviceCubicWeightsFeaturesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( selectableCubicWeights == rhs.selectableCubicWeights ); +# endif + } + + bool operator!=( PhysicalDeviceCubicWeightsFeaturesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceCubicWeightsFeaturesQCOM; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 selectableCubicWeights = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceCubicWeightsFeaturesQCOM> + { + using Type = PhysicalDeviceCubicWeightsFeaturesQCOM; + }; + struct PhysicalDeviceCustomBorderColorFeaturesEXT { using NativeType = VkPhysicalDeviceCustomBorderColorFeaturesEXT; @@ -58523,6 +60017,106 @@ namespace VULKAN_HPP_NAMESPACE }; using PhysicalDeviceDescriptorIndexingPropertiesEXT = PhysicalDeviceDescriptorIndexingProperties; + struct PhysicalDeviceDescriptorPoolOverallocationFeaturesNV + { + using NativeType = VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceDescriptorPoolOverallocationFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 descriptorPoolOverallocation_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , descriptorPoolOverallocation( descriptorPoolOverallocation_ ) + { + } + + VULKAN_HPP_CONSTEXPR + PhysicalDeviceDescriptorPoolOverallocationFeaturesNV( PhysicalDeviceDescriptorPoolOverallocationFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceDescriptorPoolOverallocationFeaturesNV( VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceDescriptorPoolOverallocationFeaturesNV( *reinterpret_cast<PhysicalDeviceDescriptorPoolOverallocationFeaturesNV const *>( &rhs ) ) + { + } + + PhysicalDeviceDescriptorPoolOverallocationFeaturesNV & + operator=( PhysicalDeviceDescriptorPoolOverallocationFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceDescriptorPoolOverallocationFeaturesNV & operator=( VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorPoolOverallocationFeaturesNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceDescriptorPoolOverallocationFeaturesNV & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceDescriptorPoolOverallocationFeaturesNV & + setDescriptorPoolOverallocation( VULKAN_HPP_NAMESPACE::Bool32 descriptorPoolOverallocation_ ) VULKAN_HPP_NOEXCEPT + { + descriptorPoolOverallocation = descriptorPoolOverallocation_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV *>( this ); + } + + operator VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, descriptorPoolOverallocation ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceDescriptorPoolOverallocationFeaturesNV const & ) const = default; +#else + bool operator==( PhysicalDeviceDescriptorPoolOverallocationFeaturesNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( descriptorPoolOverallocation == rhs.descriptorPoolOverallocation ); +# endif + } + + bool operator!=( PhysicalDeviceDescriptorPoolOverallocationFeaturesNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 descriptorPoolOverallocation = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceDescriptorPoolOverallocationFeaturesNV> + { + using Type = PhysicalDeviceDescriptorPoolOverallocationFeaturesNV; + }; + struct PhysicalDeviceDescriptorSetHostMappingFeaturesVALVE { using NativeType = VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE; @@ -60770,6 +62364,202 @@ namespace VULKAN_HPP_NAMESPACE using Type = PhysicalDeviceExtendedDynamicStateFeaturesEXT; }; + struct PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV + { + using NativeType = VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 extendedSparseAddressSpace_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , extendedSparseAddressSpace( extendedSparseAddressSpace_ ) + { + } + + VULKAN_HPP_CONSTEXPR + PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV( PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV( VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV( *reinterpret_cast<PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const *>( &rhs ) ) + { + } + + PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV & + operator=( PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV & operator=( VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV & + setExtendedSparseAddressSpace( VULKAN_HPP_NAMESPACE::Bool32 extendedSparseAddressSpace_ ) VULKAN_HPP_NOEXCEPT + { + extendedSparseAddressSpace = extendedSparseAddressSpace_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV *>( this ); + } + + operator VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceExtendedSparseAddressSpaceFeaturesNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, extendedSparseAddressSpace ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const & ) const = default; +#else + bool operator==( PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( extendedSparseAddressSpace == rhs.extendedSparseAddressSpace ); +# endif + } + + bool operator!=( PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 extendedSparseAddressSpace = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceExtendedSparseAddressSpaceFeaturesNV> + { + using Type = PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV; + }; + + struct PhysicalDeviceExtendedSparseAddressSpacePropertiesNV + { + using NativeType = VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceExtendedSparseAddressSpacePropertiesNV( VULKAN_HPP_NAMESPACE::DeviceSize extendedSparseAddressSpaceSize_ = {}, + VULKAN_HPP_NAMESPACE::ImageUsageFlags extendedSparseImageUsageFlags_ = {}, + VULKAN_HPP_NAMESPACE::BufferUsageFlags extendedSparseBufferUsageFlags_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , extendedSparseAddressSpaceSize( extendedSparseAddressSpaceSize_ ) + , extendedSparseImageUsageFlags( extendedSparseImageUsageFlags_ ) + , extendedSparseBufferUsageFlags( extendedSparseBufferUsageFlags_ ) + { + } + + VULKAN_HPP_CONSTEXPR + PhysicalDeviceExtendedSparseAddressSpacePropertiesNV( PhysicalDeviceExtendedSparseAddressSpacePropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceExtendedSparseAddressSpacePropertiesNV( VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceExtendedSparseAddressSpacePropertiesNV( *reinterpret_cast<PhysicalDeviceExtendedSparseAddressSpacePropertiesNV const *>( &rhs ) ) + { + } + + PhysicalDeviceExtendedSparseAddressSpacePropertiesNV & + operator=( PhysicalDeviceExtendedSparseAddressSpacePropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceExtendedSparseAddressSpacePropertiesNV & operator=( VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExtendedSparseAddressSpacePropertiesNV const *>( &rhs ); + return *this; + } + + operator VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV *>( this ); + } + + operator VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceExtendedSparseAddressSpacePropertiesNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, + void * const &, + VULKAN_HPP_NAMESPACE::DeviceSize const &, + VULKAN_HPP_NAMESPACE::ImageUsageFlags const &, + VULKAN_HPP_NAMESPACE::BufferUsageFlags const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, extendedSparseAddressSpaceSize, extendedSparseImageUsageFlags, extendedSparseBufferUsageFlags ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceExtendedSparseAddressSpacePropertiesNV const & ) const = default; +#else + bool operator==( PhysicalDeviceExtendedSparseAddressSpacePropertiesNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( extendedSparseAddressSpaceSize == rhs.extendedSparseAddressSpaceSize ) && + ( extendedSparseImageUsageFlags == rhs.extendedSparseImageUsageFlags ) && ( extendedSparseBufferUsageFlags == rhs.extendedSparseBufferUsageFlags ); +# endif + } + + bool operator!=( PhysicalDeviceExtendedSparseAddressSpacePropertiesNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::DeviceSize extendedSparseAddressSpaceSize = {}; + VULKAN_HPP_NAMESPACE::ImageUsageFlags extendedSparseImageUsageFlags = {}; + VULKAN_HPP_NAMESPACE::BufferUsageFlags extendedSparseBufferUsageFlags = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceExtendedSparseAddressSpacePropertiesNV> + { + using Type = PhysicalDeviceExtendedSparseAddressSpacePropertiesNV; + }; + struct PhysicalDeviceExternalBufferInfo { using NativeType = VkPhysicalDeviceExternalBufferInfo; @@ -60992,6 +62782,209 @@ namespace VULKAN_HPP_NAMESPACE }; using PhysicalDeviceExternalFenceInfoKHR = PhysicalDeviceExternalFenceInfo; +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + struct PhysicalDeviceExternalFormatResolveFeaturesANDROID + { + using NativeType = VkPhysicalDeviceExternalFormatResolveFeaturesANDROID; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceExternalFormatResolveFeaturesANDROID; + +# if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalFormatResolveFeaturesANDROID( VULKAN_HPP_NAMESPACE::Bool32 externalFormatResolve_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , externalFormatResolve( externalFormatResolve_ ) + { + } + + VULKAN_HPP_CONSTEXPR + PhysicalDeviceExternalFormatResolveFeaturesANDROID( PhysicalDeviceExternalFormatResolveFeaturesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceExternalFormatResolveFeaturesANDROID( VkPhysicalDeviceExternalFormatResolveFeaturesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceExternalFormatResolveFeaturesANDROID( *reinterpret_cast<PhysicalDeviceExternalFormatResolveFeaturesANDROID const *>( &rhs ) ) + { + } + + PhysicalDeviceExternalFormatResolveFeaturesANDROID & + operator=( PhysicalDeviceExternalFormatResolveFeaturesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT = default; +# endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceExternalFormatResolveFeaturesANDROID & operator=( VkPhysicalDeviceExternalFormatResolveFeaturesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolveFeaturesANDROID const *>( &rhs ); + return *this; + } + +# if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceExternalFormatResolveFeaturesANDROID & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceExternalFormatResolveFeaturesANDROID & + setExternalFormatResolve( VULKAN_HPP_NAMESPACE::Bool32 externalFormatResolve_ ) VULKAN_HPP_NOEXCEPT + { + externalFormatResolve = externalFormatResolve_; + return *this; + } +# endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceExternalFormatResolveFeaturesANDROID const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceExternalFormatResolveFeaturesANDROID *>( this ); + } + + operator VkPhysicalDeviceExternalFormatResolveFeaturesANDROID &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceExternalFormatResolveFeaturesANDROID *>( this ); + } + +# if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, externalFormatResolve ); + } +# endif + +# if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceExternalFormatResolveFeaturesANDROID const & ) const = default; +# else + bool operator==( PhysicalDeviceExternalFormatResolveFeaturesANDROID const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( externalFormatResolve == rhs.externalFormatResolve ); +# endif + } + + bool operator!=( PhysicalDeviceExternalFormatResolveFeaturesANDROID const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +# endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExternalFormatResolveFeaturesANDROID; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 externalFormatResolve = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceExternalFormatResolveFeaturesANDROID> + { + using Type = PhysicalDeviceExternalFormatResolveFeaturesANDROID; + }; +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + struct PhysicalDeviceExternalFormatResolvePropertiesANDROID + { + using NativeType = VkPhysicalDeviceExternalFormatResolvePropertiesANDROID; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceExternalFormatResolvePropertiesANDROID; + +# if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalFormatResolvePropertiesANDROID( + VULKAN_HPP_NAMESPACE::Bool32 nullColorAttachmentWithExternalFormatResolve_ = {}, + VULKAN_HPP_NAMESPACE::ChromaLocation externalFormatResolveChromaOffsetX_ = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven, + VULKAN_HPP_NAMESPACE::ChromaLocation externalFormatResolveChromaOffsetY_ = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , nullColorAttachmentWithExternalFormatResolve( nullColorAttachmentWithExternalFormatResolve_ ) + , externalFormatResolveChromaOffsetX( externalFormatResolveChromaOffsetX_ ) + , externalFormatResolveChromaOffsetY( externalFormatResolveChromaOffsetY_ ) + { + } + + VULKAN_HPP_CONSTEXPR + PhysicalDeviceExternalFormatResolvePropertiesANDROID( PhysicalDeviceExternalFormatResolvePropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceExternalFormatResolvePropertiesANDROID( VkPhysicalDeviceExternalFormatResolvePropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceExternalFormatResolvePropertiesANDROID( *reinterpret_cast<PhysicalDeviceExternalFormatResolvePropertiesANDROID const *>( &rhs ) ) + { + } + + PhysicalDeviceExternalFormatResolvePropertiesANDROID & + operator=( PhysicalDeviceExternalFormatResolvePropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT = default; +# endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceExternalFormatResolvePropertiesANDROID & operator=( VkPhysicalDeviceExternalFormatResolvePropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFormatResolvePropertiesANDROID const *>( &rhs ); + return *this; + } + + operator VkPhysicalDeviceExternalFormatResolvePropertiesANDROID const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceExternalFormatResolvePropertiesANDROID *>( this ); + } + + operator VkPhysicalDeviceExternalFormatResolvePropertiesANDROID &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceExternalFormatResolvePropertiesANDROID *>( this ); + } + +# if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, + void * const &, + VULKAN_HPP_NAMESPACE::Bool32 const &, + VULKAN_HPP_NAMESPACE::ChromaLocation const &, + VULKAN_HPP_NAMESPACE::ChromaLocation const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, nullColorAttachmentWithExternalFormatResolve, externalFormatResolveChromaOffsetX, externalFormatResolveChromaOffsetY ); + } +# endif + +# if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceExternalFormatResolvePropertiesANDROID const & ) const = default; +# else + bool operator==( PhysicalDeviceExternalFormatResolvePropertiesANDROID const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && + ( nullColorAttachmentWithExternalFormatResolve == rhs.nullColorAttachmentWithExternalFormatResolve ) && + ( externalFormatResolveChromaOffsetX == rhs.externalFormatResolveChromaOffsetX ) && + ( externalFormatResolveChromaOffsetY == rhs.externalFormatResolveChromaOffsetY ); +# endif + } + + bool operator!=( PhysicalDeviceExternalFormatResolvePropertiesANDROID const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +# endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExternalFormatResolvePropertiesANDROID; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 nullColorAttachmentWithExternalFormatResolve = {}; + VULKAN_HPP_NAMESPACE::ChromaLocation externalFormatResolveChromaOffsetX = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven; + VULKAN_HPP_NAMESPACE::ChromaLocation externalFormatResolveChromaOffsetY = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceExternalFormatResolvePropertiesANDROID> + { + using Type = PhysicalDeviceExternalFormatResolvePropertiesANDROID; + }; +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ + struct PhysicalDeviceExternalImageFormatInfo { using NativeType = VkPhysicalDeviceExternalImageFormatInfo; @@ -63397,6 +65390,102 @@ namespace VULKAN_HPP_NAMESPACE using Type = PhysicalDeviceFragmentShadingRatePropertiesKHR; }; + struct PhysicalDeviceFrameBoundaryFeaturesEXT + { + using NativeType = VkPhysicalDeviceFrameBoundaryFeaturesEXT; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceFrameBoundaryFeaturesEXT; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceFrameBoundaryFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 frameBoundary_ = {}, void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , frameBoundary( frameBoundary_ ) + { + } + + VULKAN_HPP_CONSTEXPR PhysicalDeviceFrameBoundaryFeaturesEXT( PhysicalDeviceFrameBoundaryFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceFrameBoundaryFeaturesEXT( VkPhysicalDeviceFrameBoundaryFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceFrameBoundaryFeaturesEXT( *reinterpret_cast<PhysicalDeviceFrameBoundaryFeaturesEXT const *>( &rhs ) ) + { + } + + PhysicalDeviceFrameBoundaryFeaturesEXT & operator=( PhysicalDeviceFrameBoundaryFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceFrameBoundaryFeaturesEXT & operator=( VkPhysicalDeviceFrameBoundaryFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceFrameBoundaryFeaturesEXT const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceFrameBoundaryFeaturesEXT & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceFrameBoundaryFeaturesEXT & setFrameBoundary( VULKAN_HPP_NAMESPACE::Bool32 frameBoundary_ ) VULKAN_HPP_NOEXCEPT + { + frameBoundary = frameBoundary_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceFrameBoundaryFeaturesEXT const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceFrameBoundaryFeaturesEXT *>( this ); + } + + operator VkPhysicalDeviceFrameBoundaryFeaturesEXT &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceFrameBoundaryFeaturesEXT *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, frameBoundary ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceFrameBoundaryFeaturesEXT const & ) const = default; +#else + bool operator==( PhysicalDeviceFrameBoundaryFeaturesEXT const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( frameBoundary == rhs.frameBoundary ); +# endif + } + + bool operator!=( PhysicalDeviceFrameBoundaryFeaturesEXT const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceFrameBoundaryFeaturesEXT; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 frameBoundary = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceFrameBoundaryFeaturesEXT> + { + using Type = PhysicalDeviceFrameBoundaryFeaturesEXT; + }; + struct PhysicalDeviceGlobalPriorityQueryFeaturesKHR { using NativeType = VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR; @@ -64896,6 +66985,187 @@ namespace VULKAN_HPP_NAMESPACE }; using PhysicalDeviceImageFormatInfo2KHR = PhysicalDeviceImageFormatInfo2; + struct PhysicalDeviceImageProcessing2FeaturesQCOM + { + using NativeType = VkPhysicalDeviceImageProcessing2FeaturesQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceImageProcessing2FeaturesQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceImageProcessing2FeaturesQCOM( VULKAN_HPP_NAMESPACE::Bool32 textureBlockMatch2_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , textureBlockMatch2( textureBlockMatch2_ ) + { + } + + VULKAN_HPP_CONSTEXPR PhysicalDeviceImageProcessing2FeaturesQCOM( PhysicalDeviceImageProcessing2FeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceImageProcessing2FeaturesQCOM( VkPhysicalDeviceImageProcessing2FeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceImageProcessing2FeaturesQCOM( *reinterpret_cast<PhysicalDeviceImageProcessing2FeaturesQCOM const *>( &rhs ) ) + { + } + + PhysicalDeviceImageProcessing2FeaturesQCOM & operator=( PhysicalDeviceImageProcessing2FeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceImageProcessing2FeaturesQCOM & operator=( VkPhysicalDeviceImageProcessing2FeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2FeaturesQCOM const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceImageProcessing2FeaturesQCOM & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceImageProcessing2FeaturesQCOM & + setTextureBlockMatch2( VULKAN_HPP_NAMESPACE::Bool32 textureBlockMatch2_ ) VULKAN_HPP_NOEXCEPT + { + textureBlockMatch2 = textureBlockMatch2_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceImageProcessing2FeaturesQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceImageProcessing2FeaturesQCOM *>( this ); + } + + operator VkPhysicalDeviceImageProcessing2FeaturesQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceImageProcessing2FeaturesQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, textureBlockMatch2 ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceImageProcessing2FeaturesQCOM const & ) const = default; +#else + bool operator==( PhysicalDeviceImageProcessing2FeaturesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( textureBlockMatch2 == rhs.textureBlockMatch2 ); +# endif + } + + bool operator!=( PhysicalDeviceImageProcessing2FeaturesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceImageProcessing2FeaturesQCOM; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 textureBlockMatch2 = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceImageProcessing2FeaturesQCOM> + { + using Type = PhysicalDeviceImageProcessing2FeaturesQCOM; + }; + + struct PhysicalDeviceImageProcessing2PropertiesQCOM + { + using NativeType = VkPhysicalDeviceImageProcessing2PropertiesQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceImageProcessing2PropertiesQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceImageProcessing2PropertiesQCOM( VULKAN_HPP_NAMESPACE::Extent2D maxBlockMatchWindow_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , maxBlockMatchWindow( maxBlockMatchWindow_ ) + { + } + + VULKAN_HPP_CONSTEXPR PhysicalDeviceImageProcessing2PropertiesQCOM( PhysicalDeviceImageProcessing2PropertiesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceImageProcessing2PropertiesQCOM( VkPhysicalDeviceImageProcessing2PropertiesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceImageProcessing2PropertiesQCOM( *reinterpret_cast<PhysicalDeviceImageProcessing2PropertiesQCOM const *>( &rhs ) ) + { + } + + PhysicalDeviceImageProcessing2PropertiesQCOM & operator=( PhysicalDeviceImageProcessing2PropertiesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceImageProcessing2PropertiesQCOM & operator=( VkPhysicalDeviceImageProcessing2PropertiesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageProcessing2PropertiesQCOM const *>( &rhs ); + return *this; + } + + operator VkPhysicalDeviceImageProcessing2PropertiesQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceImageProcessing2PropertiesQCOM *>( this ); + } + + operator VkPhysicalDeviceImageProcessing2PropertiesQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceImageProcessing2PropertiesQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Extent2D const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, maxBlockMatchWindow ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceImageProcessing2PropertiesQCOM const & ) const = default; +#else + bool operator==( PhysicalDeviceImageProcessing2PropertiesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( maxBlockMatchWindow == rhs.maxBlockMatchWindow ); +# endif + } + + bool operator!=( PhysicalDeviceImageProcessing2PropertiesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceImageProcessing2PropertiesQCOM; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Extent2D maxBlockMatchWindow = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceImageProcessing2PropertiesQCOM> + { + using Type = PhysicalDeviceImageProcessing2PropertiesQCOM; + }; + struct PhysicalDeviceImageProcessingFeaturesQCOM { using NativeType = VkPhysicalDeviceImageProcessingFeaturesQCOM; @@ -66123,6 +68393,90 @@ namespace VULKAN_HPP_NAMESPACE using Type = PhysicalDeviceInvocationMaskFeaturesHUAWEI; }; + struct PhysicalDeviceLayeredDriverPropertiesMSFT + { + using NativeType = VkPhysicalDeviceLayeredDriverPropertiesMSFT; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceLayeredDriverPropertiesMSFT; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceLayeredDriverPropertiesMSFT( + VULKAN_HPP_NAMESPACE::LayeredDriverUnderlyingApiMSFT underlyingAPI_ = VULKAN_HPP_NAMESPACE::LayeredDriverUnderlyingApiMSFT::eNone, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , underlyingAPI( underlyingAPI_ ) + { + } + + VULKAN_HPP_CONSTEXPR PhysicalDeviceLayeredDriverPropertiesMSFT( PhysicalDeviceLayeredDriverPropertiesMSFT const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceLayeredDriverPropertiesMSFT( VkPhysicalDeviceLayeredDriverPropertiesMSFT const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceLayeredDriverPropertiesMSFT( *reinterpret_cast<PhysicalDeviceLayeredDriverPropertiesMSFT const *>( &rhs ) ) + { + } + + PhysicalDeviceLayeredDriverPropertiesMSFT & operator=( PhysicalDeviceLayeredDriverPropertiesMSFT const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceLayeredDriverPropertiesMSFT & operator=( VkPhysicalDeviceLayeredDriverPropertiesMSFT const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceLayeredDriverPropertiesMSFT const *>( &rhs ); + return *this; + } + + operator VkPhysicalDeviceLayeredDriverPropertiesMSFT const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceLayeredDriverPropertiesMSFT *>( this ); + } + + operator VkPhysicalDeviceLayeredDriverPropertiesMSFT &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceLayeredDriverPropertiesMSFT *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::LayeredDriverUnderlyingApiMSFT const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, underlyingAPI ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceLayeredDriverPropertiesMSFT const & ) const = default; +#else + bool operator==( PhysicalDeviceLayeredDriverPropertiesMSFT const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( underlyingAPI == rhs.underlyingAPI ); +# endif + } + + bool operator!=( PhysicalDeviceLayeredDriverPropertiesMSFT const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceLayeredDriverPropertiesMSFT; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::LayeredDriverUnderlyingApiMSFT underlyingAPI = VULKAN_HPP_NAMESPACE::LayeredDriverUnderlyingApiMSFT::eNone; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceLayeredDriverPropertiesMSFT> + { + using Type = PhysicalDeviceLayeredDriverPropertiesMSFT; + }; + struct PhysicalDeviceLegacyDitheringFeaturesEXT { using NativeType = VkPhysicalDeviceLegacyDitheringFeaturesEXT; @@ -69751,6 +72105,229 @@ namespace VULKAN_HPP_NAMESPACE }; using PhysicalDeviceMutableDescriptorTypeFeaturesVALVE = PhysicalDeviceMutableDescriptorTypeFeaturesEXT; + struct PhysicalDeviceNestedCommandBufferFeaturesEXT + { + using NativeType = VkPhysicalDeviceNestedCommandBufferFeaturesEXT; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceNestedCommandBufferFeaturesEXT; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceNestedCommandBufferFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBuffer_ = {}, + VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBufferRendering_ = {}, + VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBufferSimultaneousUse_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , nestedCommandBuffer( nestedCommandBuffer_ ) + , nestedCommandBufferRendering( nestedCommandBufferRendering_ ) + , nestedCommandBufferSimultaneousUse( nestedCommandBufferSimultaneousUse_ ) + { + } + + VULKAN_HPP_CONSTEXPR PhysicalDeviceNestedCommandBufferFeaturesEXT( PhysicalDeviceNestedCommandBufferFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceNestedCommandBufferFeaturesEXT( VkPhysicalDeviceNestedCommandBufferFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceNestedCommandBufferFeaturesEXT( *reinterpret_cast<PhysicalDeviceNestedCommandBufferFeaturesEXT const *>( &rhs ) ) + { + } + + PhysicalDeviceNestedCommandBufferFeaturesEXT & operator=( PhysicalDeviceNestedCommandBufferFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceNestedCommandBufferFeaturesEXT & operator=( VkPhysicalDeviceNestedCommandBufferFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferFeaturesEXT const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceNestedCommandBufferFeaturesEXT & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceNestedCommandBufferFeaturesEXT & + setNestedCommandBuffer( VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBuffer_ ) VULKAN_HPP_NOEXCEPT + { + nestedCommandBuffer = nestedCommandBuffer_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceNestedCommandBufferFeaturesEXT & + setNestedCommandBufferRendering( VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBufferRendering_ ) VULKAN_HPP_NOEXCEPT + { + nestedCommandBufferRendering = nestedCommandBufferRendering_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceNestedCommandBufferFeaturesEXT & + setNestedCommandBufferSimultaneousUse( VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBufferSimultaneousUse_ ) VULKAN_HPP_NOEXCEPT + { + nestedCommandBufferSimultaneousUse = nestedCommandBufferSimultaneousUse_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceNestedCommandBufferFeaturesEXT const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceNestedCommandBufferFeaturesEXT *>( this ); + } + + operator VkPhysicalDeviceNestedCommandBufferFeaturesEXT &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceNestedCommandBufferFeaturesEXT *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, + void * const &, + VULKAN_HPP_NAMESPACE::Bool32 const &, + VULKAN_HPP_NAMESPACE::Bool32 const &, + VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, nestedCommandBuffer, nestedCommandBufferRendering, nestedCommandBufferSimultaneousUse ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceNestedCommandBufferFeaturesEXT const & ) const = default; +#else + bool operator==( PhysicalDeviceNestedCommandBufferFeaturesEXT const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( nestedCommandBuffer == rhs.nestedCommandBuffer ) && + ( nestedCommandBufferRendering == rhs.nestedCommandBufferRendering ) && + ( nestedCommandBufferSimultaneousUse == rhs.nestedCommandBufferSimultaneousUse ); +# endif + } + + bool operator!=( PhysicalDeviceNestedCommandBufferFeaturesEXT const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceNestedCommandBufferFeaturesEXT; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBuffer = {}; + VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBufferRendering = {}; + VULKAN_HPP_NAMESPACE::Bool32 nestedCommandBufferSimultaneousUse = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceNestedCommandBufferFeaturesEXT> + { + using Type = PhysicalDeviceNestedCommandBufferFeaturesEXT; + }; + + struct PhysicalDeviceNestedCommandBufferPropertiesEXT + { + using NativeType = VkPhysicalDeviceNestedCommandBufferPropertiesEXT; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceNestedCommandBufferPropertiesEXT; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceNestedCommandBufferPropertiesEXT( uint32_t maxCommandBufferNestingLevel_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , maxCommandBufferNestingLevel( maxCommandBufferNestingLevel_ ) + { + } + + VULKAN_HPP_CONSTEXPR + PhysicalDeviceNestedCommandBufferPropertiesEXT( PhysicalDeviceNestedCommandBufferPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceNestedCommandBufferPropertiesEXT( VkPhysicalDeviceNestedCommandBufferPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceNestedCommandBufferPropertiesEXT( *reinterpret_cast<PhysicalDeviceNestedCommandBufferPropertiesEXT const *>( &rhs ) ) + { + } + + PhysicalDeviceNestedCommandBufferPropertiesEXT & operator=( PhysicalDeviceNestedCommandBufferPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceNestedCommandBufferPropertiesEXT & operator=( VkPhysicalDeviceNestedCommandBufferPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceNestedCommandBufferPropertiesEXT const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceNestedCommandBufferPropertiesEXT & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceNestedCommandBufferPropertiesEXT & + setMaxCommandBufferNestingLevel( uint32_t maxCommandBufferNestingLevel_ ) VULKAN_HPP_NOEXCEPT + { + maxCommandBufferNestingLevel = maxCommandBufferNestingLevel_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceNestedCommandBufferPropertiesEXT const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceNestedCommandBufferPropertiesEXT *>( this ); + } + + operator VkPhysicalDeviceNestedCommandBufferPropertiesEXT &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceNestedCommandBufferPropertiesEXT *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, uint32_t const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, maxCommandBufferNestingLevel ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceNestedCommandBufferPropertiesEXT const & ) const = default; +#else + bool operator==( PhysicalDeviceNestedCommandBufferPropertiesEXT const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( maxCommandBufferNestingLevel == rhs.maxCommandBufferNestingLevel ); +# endif + } + + bool operator!=( PhysicalDeviceNestedCommandBufferPropertiesEXT const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceNestedCommandBufferPropertiesEXT; + void * pNext = {}; + uint32_t maxCommandBufferNestingLevel = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceNestedCommandBufferPropertiesEXT> + { + using Type = PhysicalDeviceNestedCommandBufferPropertiesEXT; + }; + struct PhysicalDeviceNonSeamlessCubeMapFeaturesEXT { using NativeType = VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT; @@ -84338,6 +86915,102 @@ namespace VULKAN_HPP_NAMESPACE using Type = PhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT; }; + struct PhysicalDeviceYcbcrDegammaFeaturesQCOM + { + using NativeType = VkPhysicalDeviceYcbcrDegammaFeaturesQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::ePhysicalDeviceYcbcrDegammaFeaturesQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR PhysicalDeviceYcbcrDegammaFeaturesQCOM( VULKAN_HPP_NAMESPACE::Bool32 ycbcrDegamma_ = {}, void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , ycbcrDegamma( ycbcrDegamma_ ) + { + } + + VULKAN_HPP_CONSTEXPR PhysicalDeviceYcbcrDegammaFeaturesQCOM( PhysicalDeviceYcbcrDegammaFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + PhysicalDeviceYcbcrDegammaFeaturesQCOM( VkPhysicalDeviceYcbcrDegammaFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : PhysicalDeviceYcbcrDegammaFeaturesQCOM( *reinterpret_cast<PhysicalDeviceYcbcrDegammaFeaturesQCOM const *>( &rhs ) ) + { + } + + PhysicalDeviceYcbcrDegammaFeaturesQCOM & operator=( PhysicalDeviceYcbcrDegammaFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + PhysicalDeviceYcbcrDegammaFeaturesQCOM & operator=( VkPhysicalDeviceYcbcrDegammaFeaturesQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrDegammaFeaturesQCOM const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceYcbcrDegammaFeaturesQCOM & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceYcbcrDegammaFeaturesQCOM & setYcbcrDegamma( VULKAN_HPP_NAMESPACE::Bool32 ycbcrDegamma_ ) VULKAN_HPP_NOEXCEPT + { + ycbcrDegamma = ycbcrDegamma_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkPhysicalDeviceYcbcrDegammaFeaturesQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkPhysicalDeviceYcbcrDegammaFeaturesQCOM *>( this ); + } + + operator VkPhysicalDeviceYcbcrDegammaFeaturesQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkPhysicalDeviceYcbcrDegammaFeaturesQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, ycbcrDegamma ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( PhysicalDeviceYcbcrDegammaFeaturesQCOM const & ) const = default; +#else + bool operator==( PhysicalDeviceYcbcrDegammaFeaturesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( ycbcrDegamma == rhs.ycbcrDegamma ); +# endif + } + + bool operator!=( PhysicalDeviceYcbcrDegammaFeaturesQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceYcbcrDegammaFeaturesQCOM; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 ycbcrDegamma = {}; + }; + + template <> + struct CppType<StructureType, StructureType::ePhysicalDeviceYcbcrDegammaFeaturesQCOM> + { + using Type = PhysicalDeviceYcbcrDegammaFeaturesQCOM; + }; + struct PhysicalDeviceYcbcrImageArraysFeaturesEXT { using NativeType = VkPhysicalDeviceYcbcrImageArraysFeaturesEXT; @@ -92616,10 +95289,10 @@ namespace VULKAN_HPP_NAMESPACE #if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) VULKAN_HPP_CONSTEXPR RayTracingShaderGroupCreateInfoKHR( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type_ = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR::eGeneral, - uint32_t generalShader_ = {}, - uint32_t closestHitShader_ = {}, - uint32_t anyHitShader_ = {}, - uint32_t intersectionShader_ = {}, + uint32_t generalShader_ = VULKAN_HPP_NAMESPACE::ShaderUnusedKHR, + uint32_t closestHitShader_ = VULKAN_HPP_NAMESPACE::ShaderUnusedKHR, + uint32_t anyHitShader_ = VULKAN_HPP_NAMESPACE::ShaderUnusedKHR, + uint32_t intersectionShader_ = VULKAN_HPP_NAMESPACE::ShaderUnusedKHR, const void * pShaderGroupCaptureReplayHandle_ = {}, const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT : pNext( pNext_ ) @@ -92746,10 +95419,10 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRayTracingShaderGroupCreateInfoKHR; const void * pNext = {}; VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR::eGeneral; - uint32_t generalShader = {}; - uint32_t closestHitShader = {}; - uint32_t anyHitShader = {}; - uint32_t intersectionShader = {}; + uint32_t generalShader = VULKAN_HPP_NAMESPACE::ShaderUnusedKHR; + uint32_t closestHitShader = VULKAN_HPP_NAMESPACE::ShaderUnusedKHR; + uint32_t anyHitShader = VULKAN_HPP_NAMESPACE::ShaderUnusedKHR; + uint32_t intersectionShader = VULKAN_HPP_NAMESPACE::ShaderUnusedKHR; const void * pShaderGroupCaptureReplayHandle = {}; }; @@ -93157,10 +95830,10 @@ namespace VULKAN_HPP_NAMESPACE #if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) VULKAN_HPP_CONSTEXPR RayTracingShaderGroupCreateInfoNV( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type_ = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR::eGeneral, - uint32_t generalShader_ = {}, - uint32_t closestHitShader_ = {}, - uint32_t anyHitShader_ = {}, - uint32_t intersectionShader_ = {}, + uint32_t generalShader_ = VULKAN_HPP_NAMESPACE::ShaderUnusedNV, + uint32_t closestHitShader_ = VULKAN_HPP_NAMESPACE::ShaderUnusedNV, + uint32_t anyHitShader_ = VULKAN_HPP_NAMESPACE::ShaderUnusedNV, + uint32_t intersectionShader_ = VULKAN_HPP_NAMESPACE::ShaderUnusedNV, const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT : pNext( pNext_ ) , type( type_ ) @@ -93276,10 +95949,10 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRayTracingShaderGroupCreateInfoNV; const void * pNext = {}; VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR::eGeneral; - uint32_t generalShader = {}; - uint32_t closestHitShader = {}; - uint32_t anyHitShader = {}; - uint32_t intersectionShader = {}; + uint32_t generalShader = VULKAN_HPP_NAMESPACE::ShaderUnusedNV; + uint32_t closestHitShader = VULKAN_HPP_NAMESPACE::ShaderUnusedNV; + uint32_t anyHitShader = VULKAN_HPP_NAMESPACE::ShaderUnusedNV; + uint32_t intersectionShader = VULKAN_HPP_NAMESPACE::ShaderUnusedNV; }; template <> @@ -97483,6 +100156,117 @@ namespace VULKAN_HPP_NAMESPACE }; using ResolveImageInfo2KHR = ResolveImageInfo2; + struct SamplerBlockMatchWindowCreateInfoQCOM + { + using NativeType = VkSamplerBlockMatchWindowCreateInfoQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eSamplerBlockMatchWindowCreateInfoQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR SamplerBlockMatchWindowCreateInfoQCOM( + VULKAN_HPP_NAMESPACE::Extent2D windowExtent_ = {}, + VULKAN_HPP_NAMESPACE::BlockMatchWindowCompareModeQCOM windowCompareMode_ = VULKAN_HPP_NAMESPACE::BlockMatchWindowCompareModeQCOM::eMin, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , windowExtent( windowExtent_ ) + , windowCompareMode( windowCompareMode_ ) + { + } + + VULKAN_HPP_CONSTEXPR SamplerBlockMatchWindowCreateInfoQCOM( SamplerBlockMatchWindowCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + SamplerBlockMatchWindowCreateInfoQCOM( VkSamplerBlockMatchWindowCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : SamplerBlockMatchWindowCreateInfoQCOM( *reinterpret_cast<SamplerBlockMatchWindowCreateInfoQCOM const *>( &rhs ) ) + { + } + + SamplerBlockMatchWindowCreateInfoQCOM & operator=( SamplerBlockMatchWindowCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + SamplerBlockMatchWindowCreateInfoQCOM & operator=( VkSamplerBlockMatchWindowCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SamplerBlockMatchWindowCreateInfoQCOM const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 SamplerBlockMatchWindowCreateInfoQCOM & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 SamplerBlockMatchWindowCreateInfoQCOM & setWindowExtent( VULKAN_HPP_NAMESPACE::Extent2D const & windowExtent_ ) VULKAN_HPP_NOEXCEPT + { + windowExtent = windowExtent_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 SamplerBlockMatchWindowCreateInfoQCOM & + setWindowCompareMode( VULKAN_HPP_NAMESPACE::BlockMatchWindowCompareModeQCOM windowCompareMode_ ) VULKAN_HPP_NOEXCEPT + { + windowCompareMode = windowCompareMode_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkSamplerBlockMatchWindowCreateInfoQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkSamplerBlockMatchWindowCreateInfoQCOM *>( this ); + } + + operator VkSamplerBlockMatchWindowCreateInfoQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkSamplerBlockMatchWindowCreateInfoQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, + const void * const &, + VULKAN_HPP_NAMESPACE::Extent2D const &, + VULKAN_HPP_NAMESPACE::BlockMatchWindowCompareModeQCOM const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, windowExtent, windowCompareMode ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( SamplerBlockMatchWindowCreateInfoQCOM const & ) const = default; +#else + bool operator==( SamplerBlockMatchWindowCreateInfoQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( windowExtent == rhs.windowExtent ) && ( windowCompareMode == rhs.windowCompareMode ); +# endif + } + + bool operator!=( SamplerBlockMatchWindowCreateInfoQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSamplerBlockMatchWindowCreateInfoQCOM; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::Extent2D windowExtent = {}; + VULKAN_HPP_NAMESPACE::BlockMatchWindowCompareModeQCOM windowCompareMode = VULKAN_HPP_NAMESPACE::BlockMatchWindowCompareModeQCOM::eMin; + }; + + template <> + struct CppType<StructureType, StructureType::eSamplerBlockMatchWindowCreateInfoQCOM> + { + using Type = SamplerBlockMatchWindowCreateInfoQCOM; + }; + struct SamplerBorderColorComponentMappingCreateInfoEXT { using NativeType = VkSamplerBorderColorComponentMappingCreateInfoEXT; @@ -97957,6 +100741,105 @@ namespace VULKAN_HPP_NAMESPACE using Type = SamplerCreateInfo; }; + struct SamplerCubicWeightsCreateInfoQCOM + { + using NativeType = VkSamplerCubicWeightsCreateInfoQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eSamplerCubicWeightsCreateInfoQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR + SamplerCubicWeightsCreateInfoQCOM( VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM cubicWeights_ = VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM::eCatmullRom, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , cubicWeights( cubicWeights_ ) + { + } + + VULKAN_HPP_CONSTEXPR SamplerCubicWeightsCreateInfoQCOM( SamplerCubicWeightsCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + SamplerCubicWeightsCreateInfoQCOM( VkSamplerCubicWeightsCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : SamplerCubicWeightsCreateInfoQCOM( *reinterpret_cast<SamplerCubicWeightsCreateInfoQCOM const *>( &rhs ) ) + { + } + + SamplerCubicWeightsCreateInfoQCOM & operator=( SamplerCubicWeightsCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + SamplerCubicWeightsCreateInfoQCOM & operator=( VkSamplerCubicWeightsCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SamplerCubicWeightsCreateInfoQCOM const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 SamplerCubicWeightsCreateInfoQCOM & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 SamplerCubicWeightsCreateInfoQCOM & + setCubicWeights( VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM cubicWeights_ ) VULKAN_HPP_NOEXCEPT + { + cubicWeights = cubicWeights_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkSamplerCubicWeightsCreateInfoQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkSamplerCubicWeightsCreateInfoQCOM *>( this ); + } + + operator VkSamplerCubicWeightsCreateInfoQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkSamplerCubicWeightsCreateInfoQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, cubicWeights ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( SamplerCubicWeightsCreateInfoQCOM const & ) const = default; +#else + bool operator==( SamplerCubicWeightsCreateInfoQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( cubicWeights == rhs.cubicWeights ); +# endif + } + + bool operator!=( SamplerCubicWeightsCreateInfoQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSamplerCubicWeightsCreateInfoQCOM; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM cubicWeights = VULKAN_HPP_NAMESPACE::CubicFilterWeightsQCOM::eCatmullRom; + }; + + template <> + struct CppType<StructureType, StructureType::eSamplerCubicWeightsCreateInfoQCOM> + { + using Type = SamplerCubicWeightsCreateInfoQCOM; + }; + struct SamplerCustomBorderColorCreateInfoEXT { using NativeType = VkSamplerCustomBorderColorCreateInfoEXT; @@ -98506,6 +101389,115 @@ namespace VULKAN_HPP_NAMESPACE }; using SamplerYcbcrConversionInfoKHR = SamplerYcbcrConversionInfo; + struct SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM + { + using NativeType = VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM( VULKAN_HPP_NAMESPACE::Bool32 enableYDegamma_ = {}, + VULKAN_HPP_NAMESPACE::Bool32 enableCbCrDegamma_ = {}, + void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , enableYDegamma( enableYDegamma_ ) + , enableCbCrDegamma( enableCbCrDegamma_ ) + { + } + + VULKAN_HPP_CONSTEXPR + SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM( SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM( VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + : SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM( *reinterpret_cast<SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const *>( &rhs ) ) + { + } + + SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM & operator=( SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM & operator=( VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM & setPNext( void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM & + setEnableYDegamma( VULKAN_HPP_NAMESPACE::Bool32 enableYDegamma_ ) VULKAN_HPP_NOEXCEPT + { + enableYDegamma = enableYDegamma_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM & + setEnableCbCrDegamma( VULKAN_HPP_NAMESPACE::Bool32 enableCbCrDegamma_ ) VULKAN_HPP_NOEXCEPT + { + enableCbCrDegamma = enableCbCrDegamma_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM *>( this ); + } + + operator VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, enableYDegamma, enableCbCrDegamma ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const & ) const = default; +#else + bool operator==( SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( enableYDegamma == rhs.enableYDegamma ) && ( enableCbCrDegamma == rhs.enableCbCrDegamma ); +# endif + } + + bool operator!=( SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; + void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 enableYDegamma = {}; + VULKAN_HPP_NAMESPACE::Bool32 enableCbCrDegamma = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM> + { + using Type = SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM; + }; + #if defined( VK_USE_PLATFORM_SCREEN_QNX ) struct ScreenBufferFormatPropertiesQNX { @@ -99791,6 +102783,112 @@ namespace VULKAN_HPP_NAMESPACE }; using SemaphoreWaitInfoKHR = SemaphoreWaitInfo; + struct SetLatencyMarkerInfoNV + { + using NativeType = VkSetLatencyMarkerInfoNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eSetLatencyMarkerInfoNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR SetLatencyMarkerInfoNV( uint64_t presentID_ = {}, + VULKAN_HPP_NAMESPACE::LatencyMarkerNV marker_ = VULKAN_HPP_NAMESPACE::LatencyMarkerNV::eSimulationStart, + const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , presentID( presentID_ ) + , marker( marker_ ) + { + } + + VULKAN_HPP_CONSTEXPR SetLatencyMarkerInfoNV( SetLatencyMarkerInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + SetLatencyMarkerInfoNV( VkSetLatencyMarkerInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + : SetLatencyMarkerInfoNV( *reinterpret_cast<SetLatencyMarkerInfoNV const *>( &rhs ) ) + { + } + + SetLatencyMarkerInfoNV & operator=( SetLatencyMarkerInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + SetLatencyMarkerInfoNV & operator=( VkSetLatencyMarkerInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SetLatencyMarkerInfoNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 SetLatencyMarkerInfoNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 SetLatencyMarkerInfoNV & setPresentID( uint64_t presentID_ ) VULKAN_HPP_NOEXCEPT + { + presentID = presentID_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 SetLatencyMarkerInfoNV & setMarker( VULKAN_HPP_NAMESPACE::LatencyMarkerNV marker_ ) VULKAN_HPP_NOEXCEPT + { + marker = marker_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkSetLatencyMarkerInfoNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkSetLatencyMarkerInfoNV *>( this ); + } + + operator VkSetLatencyMarkerInfoNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkSetLatencyMarkerInfoNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, uint64_t const &, VULKAN_HPP_NAMESPACE::LatencyMarkerNV const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, presentID, marker ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( SetLatencyMarkerInfoNV const & ) const = default; +#else + bool operator==( SetLatencyMarkerInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( presentID == rhs.presentID ) && ( marker == rhs.marker ); +# endif + } + + bool operator!=( SetLatencyMarkerInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSetLatencyMarkerInfoNV; + const void * pNext = {}; + uint64_t presentID = {}; + VULKAN_HPP_NAMESPACE::LatencyMarkerNV marker = VULKAN_HPP_NAMESPACE::LatencyMarkerNV::eSimulationStart; + }; + + template <> + struct CppType<StructureType, StructureType::eSetLatencyMarkerInfoNV> + { + using Type = SetLatencyMarkerInfoNV; + }; + struct SetStateFlagsIndirectCommandNV { using NativeType = VkSetStateFlagsIndirectCommandNV; @@ -104396,6 +107494,102 @@ namespace VULKAN_HPP_NAMESPACE using Type = SwapchainDisplayNativeHdrCreateInfoAMD; }; + struct SwapchainLatencyCreateInfoNV + { + using NativeType = VkSwapchainLatencyCreateInfoNV; + + static const bool allowDuplicate = false; + static VULKAN_HPP_CONST_OR_CONSTEXPR StructureType structureType = StructureType::eSwapchainLatencyCreateInfoNV; + +#if !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) + VULKAN_HPP_CONSTEXPR SwapchainLatencyCreateInfoNV( VULKAN_HPP_NAMESPACE::Bool32 latencyModeEnable_ = {}, const void * pNext_ = nullptr ) VULKAN_HPP_NOEXCEPT + : pNext( pNext_ ) + , latencyModeEnable( latencyModeEnable_ ) + { + } + + VULKAN_HPP_CONSTEXPR SwapchainLatencyCreateInfoNV( SwapchainLatencyCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; + + SwapchainLatencyCreateInfoNV( VkSwapchainLatencyCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + : SwapchainLatencyCreateInfoNV( *reinterpret_cast<SwapchainLatencyCreateInfoNV const *>( &rhs ) ) + { + } + + SwapchainLatencyCreateInfoNV & operator=( SwapchainLatencyCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT = default; +#endif /*VULKAN_HPP_NO_STRUCT_CONSTRUCTORS*/ + + SwapchainLatencyCreateInfoNV & operator=( VkSwapchainLatencyCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT + { + *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SwapchainLatencyCreateInfoNV const *>( &rhs ); + return *this; + } + +#if !defined( VULKAN_HPP_NO_STRUCT_SETTERS ) + VULKAN_HPP_CONSTEXPR_14 SwapchainLatencyCreateInfoNV & setPNext( const void * pNext_ ) VULKAN_HPP_NOEXCEPT + { + pNext = pNext_; + return *this; + } + + VULKAN_HPP_CONSTEXPR_14 SwapchainLatencyCreateInfoNV & setLatencyModeEnable( VULKAN_HPP_NAMESPACE::Bool32 latencyModeEnable_ ) VULKAN_HPP_NOEXCEPT + { + latencyModeEnable = latencyModeEnable_; + return *this; + } +#endif /*VULKAN_HPP_NO_STRUCT_SETTERS*/ + + operator VkSwapchainLatencyCreateInfoNV const &() const VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<const VkSwapchainLatencyCreateInfoNV *>( this ); + } + + operator VkSwapchainLatencyCreateInfoNV &() VULKAN_HPP_NOEXCEPT + { + return *reinterpret_cast<VkSwapchainLatencyCreateInfoNV *>( this ); + } + +#if defined( VULKAN_HPP_USE_REFLECT ) +# if 14 <= VULKAN_HPP_CPP_VERSION + auto +# else + std::tuple<VULKAN_HPP_NAMESPACE::StructureType const &, const void * const &, VULKAN_HPP_NAMESPACE::Bool32 const &> +# endif + reflect() const VULKAN_HPP_NOEXCEPT + { + return std::tie( sType, pNext, latencyModeEnable ); + } +#endif + +#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR ) + auto operator<=>( SwapchainLatencyCreateInfoNV const & ) const = default; +#else + bool operator==( SwapchainLatencyCreateInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { +# if defined( VULKAN_HPP_USE_REFLECT ) + return this->reflect() == rhs.reflect(); +# else + return ( sType == rhs.sType ) && ( pNext == rhs.pNext ) && ( latencyModeEnable == rhs.latencyModeEnable ); +# endif + } + + bool operator!=( SwapchainLatencyCreateInfoNV const & rhs ) const VULKAN_HPP_NOEXCEPT + { + return !operator==( rhs ); + } +#endif + + public: + VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSwapchainLatencyCreateInfoNV; + const void * pNext = {}; + VULKAN_HPP_NAMESPACE::Bool32 latencyModeEnable = {}; + }; + + template <> + struct CppType<StructureType, StructureType::eSwapchainLatencyCreateInfoNV> + { + using Type = SwapchainLatencyCreateInfoNV; + }; + struct SwapchainPresentBarrierCreateInfoNV { using NativeType = VkSwapchainPresentBarrierCreateInfoNV; diff --git a/thirdparty/vulkan/include/vulkan/vulkan_to_string.hpp b/thirdparty/vulkan/include/vulkan/vulkan_to_string.hpp index 3eac3e833f..3a34b36460 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_to_string.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_to_string.hpp @@ -935,6 +935,10 @@ namespace VULKAN_HPP_NAMESPACE result += "UpdateAfterBind | "; if ( value & DescriptorPoolCreateFlagBits::eHostOnlyEXT ) result += "HostOnlyEXT | "; + if ( value & DescriptorPoolCreateFlagBits::eAllowOverallocationSetsNV ) + result += "AllowOverallocationSetsNV | "; + if ( value & DescriptorPoolCreateFlagBits::eAllowOverallocationPoolsNV ) + result += "AllowOverallocationPoolsNV | "; return "{ " + result.substr( 0, result.size() - 3 ) + " }"; } @@ -1456,6 +1460,10 @@ namespace VULKAN_HPP_NAMESPACE result += "Min | "; if ( value & ResolveModeFlagBits::eMax ) result += "Max | "; +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + if ( value & ResolveModeFlagBits::eExternalFormatDownsampleANDROID ) + result += "ExternalFormatDownsampleANDROID | "; +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ return "{ " + result.substr( 0, result.size() - 3 ) + " }"; } @@ -1733,6 +1741,8 @@ namespace VULKAN_HPP_NAMESPACE result += "Suspending | "; if ( value & RenderingFlagBits::eResuming ) result += "Resuming | "; + if ( value & RenderingFlagBits::eContentsInlineEXT ) + result += "ContentsInlineEXT | "; if ( value & RenderingFlagBits::eEnableLegacyDitheringEXT ) result += "EnableLegacyDitheringEXT | "; @@ -2256,6 +2266,10 @@ namespace VULKAN_HPP_NAMESPACE result += "DeblockingFilterEnabled | "; if ( value & VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterPartial ) result += "DeblockingFilterPartial | "; + if ( value & VideoEncodeH264StdFlagBitsEXT::eSliceQpDelta ) + result += "SliceQpDelta | "; + if ( value & VideoEncodeH264StdFlagBitsEXT::eDifferentSliceQpDelta ) + result += "DifferentSliceQpDelta | "; return "{ " + result.substr( 0, result.size() - 3 ) + " }"; } @@ -2358,6 +2372,10 @@ namespace VULKAN_HPP_NAMESPACE result += "DependentSliceSegmentsEnabledFlagSet | "; if ( value & VideoEncodeH265StdFlagBitsEXT::eDependentSliceSegmentFlagSet ) result += "DependentSliceSegmentFlagSet | "; + if ( value & VideoEncodeH265StdFlagBitsEXT::eSliceQpDelta ) + result += "SliceQpDelta | "; + if ( value & VideoEncodeH265StdFlagBitsEXT::eDifferentSliceQpDelta ) + result += "DifferentSliceQpDelta | "; return "{ " + result.substr( 0, result.size() - 3 ) + " }"; } @@ -2893,6 +2911,8 @@ namespace VULKAN_HPP_NAMESPACE std::string result; if ( value & VideoEncodeCapabilityFlagBitsKHR::ePrecedingExternallyEncodedBytes ) result += "PrecedingExternallyEncodedBytes | "; + if ( value & VideoEncodeCapabilityFlagBitsKHR::eInsufficientstreamBufferRangeDetectionBit ) + result += "InsufficientstreamBufferRangeDetectionBit | "; return "{ " + result.substr( 0, result.size() - 3 ) + " }"; } @@ -3175,6 +3195,20 @@ namespace VULKAN_HPP_NAMESPACE } #endif /*VK_USE_PLATFORM_FUCHSIA*/ + //=== VK_EXT_frame_boundary === + + VULKAN_HPP_INLINE std::string to_string( FrameBoundaryFlagsEXT value ) + { + if ( !value ) + return "{}"; + + std::string result; + if ( value & FrameBoundaryFlagBitsEXT::eFrameEnd ) + result += "FrameEnd | "; + + return "{ " + result.substr( 0, result.size() - 3 ) + " }"; + } + #if defined( VK_USE_PLATFORM_SCREEN_QNX ) //=== VK_QNX_screen_surface === @@ -4304,6 +4338,8 @@ namespace VULKAN_HPP_NAMESPACE case StructureType::ePhysicalDeviceExternalMemoryRdmaFeaturesNV: return "PhysicalDeviceExternalMemoryRdmaFeaturesNV"; case StructureType::ePipelinePropertiesIdentifierEXT: return "PipelinePropertiesIdentifierEXT"; case StructureType::ePhysicalDevicePipelinePropertiesFeaturesEXT: return "PhysicalDevicePipelinePropertiesFeaturesEXT"; + case StructureType::ePhysicalDeviceFrameBoundaryFeaturesEXT: return "PhysicalDeviceFrameBoundaryFeaturesEXT"; + case StructureType::eFrameBoundaryEXT: return "FrameBoundaryEXT"; case StructureType::ePhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT: return "PhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT"; case StructureType::eSubpassResolvePerformanceQueryEXT: return "SubpassResolvePerformanceQueryEXT"; case StructureType::eMultisampledRenderToSingleSampledInfoEXT: return "MultisampledRenderToSingleSampledInfoEXT"; @@ -4365,6 +4401,8 @@ namespace VULKAN_HPP_NAMESPACE case StructureType::ePhysicalDeviceImageProcessingFeaturesQCOM: return "PhysicalDeviceImageProcessingFeaturesQCOM"; case StructureType::ePhysicalDeviceImageProcessingPropertiesQCOM: return "PhysicalDeviceImageProcessingPropertiesQCOM"; case StructureType::eImageViewSampleWeightCreateInfoQCOM: return "ImageViewSampleWeightCreateInfoQCOM"; + case StructureType::ePhysicalDeviceNestedCommandBufferFeaturesEXT: return "PhysicalDeviceNestedCommandBufferFeaturesEXT"; + case StructureType::ePhysicalDeviceNestedCommandBufferPropertiesEXT: return "PhysicalDeviceNestedCommandBufferPropertiesEXT"; case StructureType::eExternalMemoryAcquireUnmodifiedEXT: return "ExternalMemoryAcquireUnmodifiedEXT"; case StructureType::ePhysicalDeviceExtendedDynamicState3FeaturesEXT: return "PhysicalDeviceExtendedDynamicState3FeaturesEXT"; case StructureType::ePhysicalDeviceExtendedDynamicState3PropertiesEXT: return "PhysicalDeviceExtendedDynamicState3PropertiesEXT"; @@ -4388,6 +4426,11 @@ namespace VULKAN_HPP_NAMESPACE case StructureType::eOpticalFlowSessionCreatePrivateDataInfoNV: return "OpticalFlowSessionCreatePrivateDataInfoNV"; case StructureType::ePhysicalDeviceLegacyDitheringFeaturesEXT: return "PhysicalDeviceLegacyDitheringFeaturesEXT"; case StructureType::ePhysicalDevicePipelineProtectedAccessFeaturesEXT: return "PhysicalDevicePipelineProtectedAccessFeaturesEXT"; +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + case StructureType::ePhysicalDeviceExternalFormatResolveFeaturesANDROID: return "PhysicalDeviceExternalFormatResolveFeaturesANDROID"; + case StructureType::ePhysicalDeviceExternalFormatResolvePropertiesANDROID: return "PhysicalDeviceExternalFormatResolvePropertiesANDROID"; + case StructureType::eAndroidHardwareBufferFormatResolvePropertiesANDROID: return "AndroidHardwareBufferFormatResolvePropertiesANDROID"; +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ case StructureType::ePhysicalDeviceMaintenance5FeaturesKHR: return "PhysicalDeviceMaintenance5FeaturesKHR"; case StructureType::ePhysicalDeviceMaintenance5PropertiesKHR: return "PhysicalDeviceMaintenance5PropertiesKHR"; case StructureType::eRenderingAreaInfoKHR: return "RenderingAreaInfoKHR"; @@ -4407,17 +4450,37 @@ namespace VULKAN_HPP_NAMESPACE case StructureType::ePhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM: return "PhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM"; case StructureType::ePhysicalDeviceRayTracingInvocationReorderFeaturesNV: return "PhysicalDeviceRayTracingInvocationReorderFeaturesNV"; case StructureType::ePhysicalDeviceRayTracingInvocationReorderPropertiesNV: return "PhysicalDeviceRayTracingInvocationReorderPropertiesNV"; + case StructureType::ePhysicalDeviceExtendedSparseAddressSpaceFeaturesNV: return "PhysicalDeviceExtendedSparseAddressSpaceFeaturesNV"; + case StructureType::ePhysicalDeviceExtendedSparseAddressSpacePropertiesNV: return "PhysicalDeviceExtendedSparseAddressSpacePropertiesNV"; case StructureType::ePhysicalDeviceMutableDescriptorTypeFeaturesEXT: return "PhysicalDeviceMutableDescriptorTypeFeaturesEXT"; case StructureType::eMutableDescriptorTypeCreateInfoEXT: return "MutableDescriptorTypeCreateInfoEXT"; case StructureType::ePhysicalDeviceShaderCoreBuiltinsFeaturesARM: return "PhysicalDeviceShaderCoreBuiltinsFeaturesARM"; case StructureType::ePhysicalDeviceShaderCoreBuiltinsPropertiesARM: return "PhysicalDeviceShaderCoreBuiltinsPropertiesARM"; case StructureType::ePhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT: return "PhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT"; case StructureType::ePhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT: return "PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT"; + case StructureType::eLatencySleepModeInfoNV: return "LatencySleepModeInfoNV"; + case StructureType::eLatencySleepInfoNV: return "LatencySleepInfoNV"; + case StructureType::eSetLatencyMarkerInfoNV: return "SetLatencyMarkerInfoNV"; + case StructureType::eGetLatencyMarkerInfoNV: return "GetLatencyMarkerInfoNV"; + case StructureType::eLatencyTimingsFrameReportNV: return "LatencyTimingsFrameReportNV"; + case StructureType::eLatencySubmissionPresentIdNV: return "LatencySubmissionPresentIdNV"; + case StructureType::eOutOfBandQueueTypeInfoNV: return "OutOfBandQueueTypeInfoNV"; + case StructureType::eSwapchainLatencyCreateInfoNV: return "SwapchainLatencyCreateInfoNV"; + case StructureType::eLatencySurfaceCapabilitiesNV: return "LatencySurfaceCapabilitiesNV"; case StructureType::ePhysicalDeviceCooperativeMatrixFeaturesKHR: return "PhysicalDeviceCooperativeMatrixFeaturesKHR"; case StructureType::eCooperativeMatrixPropertiesKHR: return "CooperativeMatrixPropertiesKHR"; case StructureType::ePhysicalDeviceCooperativeMatrixPropertiesKHR: return "PhysicalDeviceCooperativeMatrixPropertiesKHR"; case StructureType::ePhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM: return "PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM"; case StructureType::eMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM: return "MultiviewPerViewRenderAreasRenderPassBeginInfoQCOM"; + case StructureType::ePhysicalDeviceImageProcessing2FeaturesQCOM: return "PhysicalDeviceImageProcessing2FeaturesQCOM"; + case StructureType::ePhysicalDeviceImageProcessing2PropertiesQCOM: return "PhysicalDeviceImageProcessing2PropertiesQCOM"; + case StructureType::eSamplerBlockMatchWindowCreateInfoQCOM: return "SamplerBlockMatchWindowCreateInfoQCOM"; + case StructureType::eSamplerCubicWeightsCreateInfoQCOM: return "SamplerCubicWeightsCreateInfoQCOM"; + case StructureType::ePhysicalDeviceCubicWeightsFeaturesQCOM: return "PhysicalDeviceCubicWeightsFeaturesQCOM"; + case StructureType::eBlitImageCubicWeightsInfoQCOM: return "BlitImageCubicWeightsInfoQCOM"; + case StructureType::ePhysicalDeviceYcbcrDegammaFeaturesQCOM: return "PhysicalDeviceYcbcrDegammaFeaturesQCOM"; + case StructureType::eSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM: return "SamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM"; + case StructureType::ePhysicalDeviceCubicClampFeaturesQCOM: return "PhysicalDeviceCubicClampFeaturesQCOM"; case StructureType::ePhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT: return "PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT"; #if defined( VK_USE_PLATFORM_SCREEN_QNX ) case StructureType::eScreenBufferPropertiesQNX: return "ScreenBufferPropertiesQNX"; @@ -4426,6 +4489,8 @@ namespace VULKAN_HPP_NAMESPACE case StructureType::eExternalFormatQNX: return "ExternalFormatQNX"; case StructureType::ePhysicalDeviceExternalMemoryScreenBufferFeaturesQNX: return "PhysicalDeviceExternalMemoryScreenBufferFeaturesQNX"; #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ + case StructureType::ePhysicalDeviceLayeredDriverPropertiesMSFT: return "PhysicalDeviceLayeredDriverPropertiesMSFT"; + case StructureType::ePhysicalDeviceDescriptorPoolOverallocationFeaturesNV: return "PhysicalDeviceDescriptorPoolOverallocationFeaturesNV"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -5002,6 +5067,15 @@ namespace VULKAN_HPP_NAMESPACE return "(void)"; } + VULKAN_HPP_INLINE std::string to_string( DeviceQueueCreateFlagBits value ) + { + switch ( value ) + { + case DeviceQueueCreateFlagBits::eProtected: return "Protected"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + VULKAN_HPP_INLINE std::string to_string( PipelineStageFlagBits value ) { switch ( value ) @@ -5323,6 +5397,15 @@ namespace VULKAN_HPP_NAMESPACE return "(void)"; } + VULKAN_HPP_INLINE std::string to_string( PipelineCacheCreateFlagBits value ) + { + switch ( value ) + { + case PipelineCacheCreateFlagBits::eExternallySynchronized: return "ExternallySynchronized"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + VULKAN_HPP_INLINE std::string to_string( BlendFactor value ) { switch ( value ) @@ -5697,6 +5780,25 @@ namespace VULKAN_HPP_NAMESPACE } } + VULKAN_HPP_INLINE std::string to_string( PipelineColorBlendStateCreateFlagBits value ) + { + switch ( value ) + { + case PipelineColorBlendStateCreateFlagBits::eRasterizationOrderAttachmentAccessEXT: return "RasterizationOrderAttachmentAccessEXT"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + + VULKAN_HPP_INLINE std::string to_string( PipelineDepthStencilStateCreateFlagBits value ) + { + switch ( value ) + { + case PipelineDepthStencilStateCreateFlagBits::eRasterizationOrderAttachmentDepthAccessEXT: return "RasterizationOrderAttachmentDepthAccessEXT"; + case PipelineDepthStencilStateCreateFlagBits::eRasterizationOrderAttachmentStencilAccessEXT: return "RasterizationOrderAttachmentStencilAccessEXT"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + VULKAN_HPP_INLINE std::string to_string( PipelineDynamicStateCreateFlagBits ) { return "(void)"; @@ -5707,6 +5809,15 @@ namespace VULKAN_HPP_NAMESPACE return "(void)"; } + VULKAN_HPP_INLINE std::string to_string( PipelineLayoutCreateFlagBits value ) + { + switch ( value ) + { + case PipelineLayoutCreateFlagBits::eIndependentSetsEXT: return "IndependentSetsEXT"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + VULKAN_HPP_INLINE std::string to_string( PipelineMultisampleStateCreateFlagBits ) { return "(void)"; @@ -5802,6 +5913,8 @@ namespace VULKAN_HPP_NAMESPACE case DescriptorPoolCreateFlagBits::eFreeDescriptorSet: return "FreeDescriptorSet"; case DescriptorPoolCreateFlagBits::eUpdateAfterBind: return "UpdateAfterBind"; case DescriptorPoolCreateFlagBits::eHostOnlyEXT: return "HostOnlyEXT"; + case DescriptorPoolCreateFlagBits::eAllowOverallocationSetsNV: return "AllowOverallocationSetsNV"; + case DescriptorPoolCreateFlagBits::eAllowOverallocationPoolsNV: return "AllowOverallocationPoolsNV"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -6068,6 +6181,7 @@ namespace VULKAN_HPP_NAMESPACE { case SubpassContents::eInline: return "Inline"; case SubpassContents::eSecondaryCommandBuffers: return "SecondaryCommandBuffers"; + case SubpassContents::eInlineAndSecondaryCommandBuffersEXT: return "InlineAndSecondaryCommandBuffersEXT"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -6139,15 +6253,6 @@ namespace VULKAN_HPP_NAMESPACE } } - VULKAN_HPP_INLINE std::string to_string( DeviceQueueCreateFlagBits value ) - { - switch ( value ) - { - case DeviceQueueCreateFlagBits::eProtected: return "Protected"; - default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; - } - } - VULKAN_HPP_INLINE std::string to_string( SamplerYcbcrModelConversion value ) { switch ( value ) @@ -6332,6 +6437,7 @@ namespace VULKAN_HPP_NAMESPACE case DriverId::eMesaDozen: return "MesaDozen"; case DriverId::eMesaNvk: return "MesaNvk"; case DriverId::eImaginationOpenSourceMESA: return "ImaginationOpenSourceMESA"; + case DriverId::eMesaAgxv: return "MesaAgxv"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -6368,6 +6474,9 @@ namespace VULKAN_HPP_NAMESPACE case ResolveModeFlagBits::eAverage: return "Average"; case ResolveModeFlagBits::eMin: return "Min"; case ResolveModeFlagBits::eMax: return "Max"; +#if defined( VK_USE_PLATFORM_ANDROID_KHR ) + case ResolveModeFlagBits::eExternalFormatDownsampleANDROID: return "ExternalFormatDownsampleANDROID"; +#endif /*VK_USE_PLATFORM_ANDROID_KHR*/ default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -6379,6 +6488,7 @@ namespace VULKAN_HPP_NAMESPACE case SamplerReductionMode::eWeightedAverage: return "WeightedAverage"; case SamplerReductionMode::eMin: return "Min"; case SamplerReductionMode::eMax: return "Max"; + case SamplerReductionMode::eWeightedAverageRangeclampQCOM: return "WeightedAverageRangeclampQCOM"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -6556,6 +6666,7 @@ namespace VULKAN_HPP_NAMESPACE case RenderingFlagBits::eContentsSecondaryCommandBuffers: return "ContentsSecondaryCommandBuffers"; case RenderingFlagBits::eSuspending: return "Suspending"; case RenderingFlagBits::eResuming: return "Resuming"; + case RenderingFlagBits::eContentsInlineEXT: return "ContentsInlineEXT"; case RenderingFlagBits::eEnableLegacyDitheringEXT: return "EnableLegacyDitheringEXT"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } @@ -6939,6 +7050,9 @@ namespace VULKAN_HPP_NAMESPACE case QueryResultStatusKHR::eError: return "Error"; case QueryResultStatusKHR::eNotReady: return "NotReady"; case QueryResultStatusKHR::eComplete: return "Complete"; +#if defined( VK_ENABLE_BETA_EXTENSIONS ) + case QueryResultStatusKHR::eInsufficientBitstreamBufferRange: return "InsufficientBitstreamBufferRange"; +#endif /*VK_ENABLE_BETA_EXTENSIONS*/ default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -7036,6 +7150,8 @@ namespace VULKAN_HPP_NAMESPACE case VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterDisabled: return "DeblockingFilterDisabled"; case VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterEnabled: return "DeblockingFilterEnabled"; case VideoEncodeH264StdFlagBitsEXT::eDeblockingFilterPartial: return "DeblockingFilterPartial"; + case VideoEncodeH264StdFlagBitsEXT::eSliceQpDelta: return "SliceQpDelta"; + case VideoEncodeH264StdFlagBitsEXT::eDifferentSliceQpDelta: return "DifferentSliceQpDelta"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -7098,6 +7214,8 @@ namespace VULKAN_HPP_NAMESPACE case VideoEncodeH265StdFlagBitsEXT::eDeblockingFilterOverrideEnabledFlagSet: return "DeblockingFilterOverrideEnabledFlagSet"; case VideoEncodeH265StdFlagBitsEXT::eDependentSliceSegmentsEnabledFlagSet: return "DependentSliceSegmentsEnabledFlagSet"; case VideoEncodeH265StdFlagBitsEXT::eDependentSliceSegmentFlagSet: return "DependentSliceSegmentFlagSet"; + case VideoEncodeH265StdFlagBitsEXT::eSliceQpDelta: return "SliceQpDelta"; + case VideoEncodeH265StdFlagBitsEXT::eDifferentSliceQpDelta: return "DifferentSliceQpDelta"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -8097,17 +8215,6 @@ namespace VULKAN_HPP_NAMESPACE return "(void)"; } - //=== VK_EXT_pipeline_creation_cache_control === - - VULKAN_HPP_INLINE std::string to_string( PipelineCacheCreateFlagBits value ) - { - switch ( value ) - { - case PipelineCacheCreateFlagBits::eExternallySynchronized: return "ExternallySynchronized"; - default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; - } - } - #if defined( VK_ENABLE_BETA_EXTENSIONS ) //=== VK_KHR_video_encode_queue === @@ -8116,6 +8223,7 @@ namespace VULKAN_HPP_NAMESPACE switch ( value ) { case VideoEncodeCapabilityFlagBitsKHR::ePrecedingExternallyEncodedBytes: return "PrecedingExternallyEncodedBytes"; + case VideoEncodeCapabilityFlagBitsKHR::eInsufficientstreamBufferRangeDetectionBit: return "InsufficientstreamBufferRangeDetectionBit"; default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; } } @@ -8238,15 +8346,6 @@ namespace VULKAN_HPP_NAMESPACE } } - VULKAN_HPP_INLINE std::string to_string( PipelineLayoutCreateFlagBits value ) - { - switch ( value ) - { - case PipelineLayoutCreateFlagBits::eIndependentSetsEXT: return "IndependentSetsEXT"; - default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; - } - } - //=== VK_NV_fragment_shading_rate_enums === VULKAN_HPP_INLINE std::string to_string( FragmentShadingRateNV value ) @@ -8427,6 +8526,17 @@ namespace VULKAN_HPP_NAMESPACE } #endif /*VK_USE_PLATFORM_FUCHSIA*/ + //=== VK_EXT_frame_boundary === + + VULKAN_HPP_INLINE std::string to_string( FrameBoundaryFlagBitsEXT value ) + { + switch ( value ) + { + case FrameBoundaryFlagBitsEXT::eFrameEnd: return "FrameEnd"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + #if defined( VK_USE_PLATFORM_SCREEN_QNX ) //=== VK_QNX_screen_surface === @@ -8580,27 +8690,6 @@ namespace VULKAN_HPP_NAMESPACE return "(void)"; } - //=== VK_EXT_rasterization_order_attachment_access === - - VULKAN_HPP_INLINE std::string to_string( PipelineColorBlendStateCreateFlagBits value ) - { - switch ( value ) - { - case PipelineColorBlendStateCreateFlagBits::eRasterizationOrderAttachmentAccessEXT: return "RasterizationOrderAttachmentAccessEXT"; - default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; - } - } - - VULKAN_HPP_INLINE std::string to_string( PipelineDepthStencilStateCreateFlagBits value ) - { - switch ( value ) - { - case PipelineDepthStencilStateCreateFlagBits::eRasterizationOrderAttachmentDepthAccessEXT: return "RasterizationOrderAttachmentDepthAccessEXT"; - case PipelineDepthStencilStateCreateFlagBits::eRasterizationOrderAttachmentStencilAccessEXT: return "RasterizationOrderAttachmentStencilAccessEXT"; - default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; - } - } - //=== VK_NV_optical_flow === VULKAN_HPP_INLINE std::string to_string( OpticalFlowUsageFlagBitsNV value ) @@ -8799,6 +8888,38 @@ namespace VULKAN_HPP_NAMESPACE } } + //=== VK_NV_low_latency2 === + + VULKAN_HPP_INLINE std::string to_string( LatencyMarkerNV value ) + { + switch ( value ) + { + case LatencyMarkerNV::eSimulationStart: return "SimulationStart"; + case LatencyMarkerNV::eSimulationEnd: return "SimulationEnd"; + case LatencyMarkerNV::eRendersubmitStart: return "RendersubmitStart"; + case LatencyMarkerNV::eRendersubmitEnd: return "RendersubmitEnd"; + case LatencyMarkerNV::ePresentStart: return "PresentStart"; + case LatencyMarkerNV::ePresentEnd: return "PresentEnd"; + case LatencyMarkerNV::eInputSample: return "InputSample"; + case LatencyMarkerNV::eTriggerFlash: return "TriggerFlash"; + case LatencyMarkerNV::eOutOfBandRendersubmitStart: return "OutOfBandRendersubmitStart"; + case LatencyMarkerNV::eOutOfBandRendersubmitEnd: return "OutOfBandRendersubmitEnd"; + case LatencyMarkerNV::eOutOfBandPresentStart: return "OutOfBandPresentStart"; + case LatencyMarkerNV::eOutOfBandPresentEnd: return "OutOfBandPresentEnd"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + + VULKAN_HPP_INLINE std::string to_string( OutOfBandQueueTypeNV value ) + { + switch ( value ) + { + case OutOfBandQueueTypeNV::eRender: return "Render"; + case OutOfBandQueueTypeNV::ePresent: return "Present"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + //=== VK_KHR_cooperative_matrix === VULKAN_HPP_INLINE std::string to_string( ScopeKHR value ) @@ -8832,5 +8953,43 @@ namespace VULKAN_HPP_NAMESPACE } } + //=== VK_QCOM_image_processing2 === + + VULKAN_HPP_INLINE std::string to_string( BlockMatchWindowCompareModeQCOM value ) + { + switch ( value ) + { + case BlockMatchWindowCompareModeQCOM::eMin: return "Min"; + case BlockMatchWindowCompareModeQCOM::eMax: return "Max"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + + //=== VK_QCOM_filter_cubic_weights === + + VULKAN_HPP_INLINE std::string to_string( CubicFilterWeightsQCOM value ) + { + switch ( value ) + { + case CubicFilterWeightsQCOM::eCatmullRom: return "CatmullRom"; + case CubicFilterWeightsQCOM::eZeroTangentCardinal: return "ZeroTangentCardinal"; + case CubicFilterWeightsQCOM::eBSpline: return "BSpline"; + case CubicFilterWeightsQCOM::eMitchellNetravali: return "MitchellNetravali"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + + //=== VK_MSFT_layered_driver === + + VULKAN_HPP_INLINE std::string to_string( LayeredDriverUnderlyingApiMSFT value ) + { + switch ( value ) + { + case LayeredDriverUnderlyingApiMSFT::eNone: return "None"; + case LayeredDriverUnderlyingApiMSFT::eD3D12: return "D3D12"; + default: return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString( static_cast<uint32_t>( value ) ) + " )"; + } + } + } // namespace VULKAN_HPP_NAMESPACE #endif diff --git a/thirdparty/vulkan/include/vulkan/vulkan_video.hpp b/thirdparty/vulkan/include/vulkan/vulkan_video.hpp index 7465938270..76dc641aed 100644 --- a/thirdparty/vulkan/include/vulkan/vulkan_video.hpp +++ b/thirdparty/vulkan/include/vulkan/vulkan_video.hpp @@ -1028,9 +1028,9 @@ namespace VULKAN_HPP_NAMESPACE bool operator==( EncodeH264RefPicMarkingEntry const & rhs ) const VULKAN_HPP_NOEXCEPT { - return ( operation == rhs.operation ) && ( difference_of_pic_nums_minus1 == rhs.difference_of_pic_nums_minus1 ) && - ( long_term_pic_num == rhs.long_term_pic_num ) && ( long_term_frame_idx == rhs.long_term_frame_idx ) && - ( max_long_term_frame_idx_plus1 == rhs.max_long_term_frame_idx_plus1 ); + return ( memory_management_control_operation == rhs.memory_management_control_operation ) && + ( difference_of_pic_nums_minus1 == rhs.difference_of_pic_nums_minus1 ) && ( long_term_pic_num == rhs.long_term_pic_num ) && + ( long_term_frame_idx == rhs.long_term_frame_idx ) && ( max_long_term_frame_idx_plus1 == rhs.max_long_term_frame_idx_plus1 ); } bool operator!=( EncodeH264RefPicMarkingEntry const & rhs ) const VULKAN_HPP_NOEXCEPT @@ -1039,7 +1039,7 @@ namespace VULKAN_HPP_NAMESPACE } public: - VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H264MemMgmtControlOp operation = + VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H264MemMgmtControlOp memory_management_control_operation = VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H264MemMgmtControlOp::eEnd; uint16_t difference_of_pic_nums_minus1 = {}; uint16_t long_term_pic_num = {}; @@ -1185,7 +1185,7 @@ namespace VULKAN_HPP_NAMESPACE { return ( flags == rhs.flags ) && ( first_mb_in_slice == rhs.first_mb_in_slice ) && ( slice_type == rhs.slice_type ) && ( slice_alpha_c0_offset_div2 == rhs.slice_alpha_c0_offset_div2 ) && ( slice_beta_offset_div2 == rhs.slice_beta_offset_div2 ) && - ( reserved1 == rhs.reserved1 ) && ( cabac_init_idc == rhs.cabac_init_idc ) && + ( slice_qp_delta == rhs.slice_qp_delta ) && ( reserved1 == rhs.reserved1 ) && ( cabac_init_idc == rhs.cabac_init_idc ) && ( disable_deblocking_filter_idc == rhs.disable_deblocking_filter_idc ) && ( pWeightTable == rhs.pWeightTable ); } @@ -1200,7 +1200,8 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H264SliceType slice_type = VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H264SliceType::eP; int8_t slice_alpha_c0_offset_div2 = {}; int8_t slice_beta_offset_div2 = {}; - uint16_t reserved1 = {}; + int8_t slice_qp_delta = {}; + uint8_t reserved1 = {}; VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H264CabacInitIdc cabac_init_idc = VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H264CabacInitIdc::e0; VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H264DisableDeblockingFilterIdc disable_deblocking_filter_idc = @@ -2416,7 +2417,8 @@ namespace VULKAN_HPP_NAMESPACE ( slice_cb_qp_offset == rhs.slice_cb_qp_offset ) && ( slice_cr_qp_offset == rhs.slice_cr_qp_offset ) && ( slice_beta_offset_div2 == rhs.slice_beta_offset_div2 ) && ( slice_tc_offset_div2 == rhs.slice_tc_offset_div2 ) && ( slice_act_y_qp_offset == rhs.slice_act_y_qp_offset ) && ( slice_act_cb_qp_offset == rhs.slice_act_cb_qp_offset ) && - ( slice_act_cr_qp_offset == rhs.slice_act_cr_qp_offset ) && ( reserved1 == rhs.reserved1 ) && ( pWeightTable == rhs.pWeightTable ); + ( slice_act_cr_qp_offset == rhs.slice_act_cr_qp_offset ) && ( slice_qp_delta == rhs.slice_qp_delta ) && ( reserved1 == rhs.reserved1 ) && + ( pWeightTable == rhs.pWeightTable ); } bool operator!=( EncodeH265SliceSegmentHeader const & rhs ) const VULKAN_HPP_NOEXCEPT @@ -2437,7 +2439,8 @@ namespace VULKAN_HPP_NAMESPACE int8_t slice_act_y_qp_offset = {}; int8_t slice_act_cb_qp_offset = {}; int8_t slice_act_cr_qp_offset = {}; - VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, 3> reserved1 = {}; + int8_t slice_qp_delta = {}; + uint16_t reserved1 = {}; const VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::EncodeH265WeightTable * pWeightTable = {}; }; @@ -2550,28 +2553,28 @@ namespace VULKAN_HPP_NAMESPACE uint32_t reserved : 23; }; - struct EncodeH265SliceSegmentLongTermRefPics + struct EncodeH265LongTermRefPics { - using NativeType = StdVideoEncodeH265SliceSegmentLongTermRefPics; + using NativeType = StdVideoEncodeH265LongTermRefPics; - operator StdVideoEncodeH265SliceSegmentLongTermRefPics const &() const VULKAN_HPP_NOEXCEPT + operator StdVideoEncodeH265LongTermRefPics const &() const VULKAN_HPP_NOEXCEPT { - return *reinterpret_cast<const StdVideoEncodeH265SliceSegmentLongTermRefPics *>( this ); + return *reinterpret_cast<const StdVideoEncodeH265LongTermRefPics *>( this ); } - operator StdVideoEncodeH265SliceSegmentLongTermRefPics &() VULKAN_HPP_NOEXCEPT + operator StdVideoEncodeH265LongTermRefPics &() VULKAN_HPP_NOEXCEPT { - return *reinterpret_cast<StdVideoEncodeH265SliceSegmentLongTermRefPics *>( this ); + return *reinterpret_cast<StdVideoEncodeH265LongTermRefPics *>( this ); } - bool operator==( EncodeH265SliceSegmentLongTermRefPics const & rhs ) const VULKAN_HPP_NOEXCEPT + bool operator==( EncodeH265LongTermRefPics const & rhs ) const VULKAN_HPP_NOEXCEPT { return ( num_long_term_sps == rhs.num_long_term_sps ) && ( num_long_term_pics == rhs.num_long_term_pics ) && ( lt_idx_sps == rhs.lt_idx_sps ) && ( poc_lsb_lt == rhs.poc_lsb_lt ) && ( used_by_curr_pic_lt_flag == rhs.used_by_curr_pic_lt_flag ) && ( delta_poc_msb_present_flag == rhs.delta_poc_msb_present_flag ) && ( delta_poc_msb_cycle_lt == rhs.delta_poc_msb_cycle_lt ); } - bool operator!=( EncodeH265SliceSegmentLongTermRefPics const & rhs ) const VULKAN_HPP_NOEXCEPT + bool operator!=( EncodeH265LongTermRefPics const & rhs ) const VULKAN_HPP_NOEXCEPT { return !operator==( rhs ); } @@ -2617,16 +2620,16 @@ namespace VULKAN_HPP_NAMESPACE public: VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::EncodeH265PictureInfoFlags flags = {}; VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H265PictureType pic_type = VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H265PictureType::eP; - uint8_t sps_video_parameter_set_id = {}; - uint8_t pps_seq_parameter_set_id = {}; - uint8_t pps_pic_parameter_set_id = {}; - uint8_t short_term_ref_pic_set_idx = {}; - int32_t PicOrderCntVal = {}; - uint8_t TemporalId = {}; - VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, 7> reserved1 = {}; - const VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::EncodeH265ReferenceListsInfo * pRefLists = {}; - const VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H265ShortTermRefPicSet * pShortTermRefPicSet = {}; - const VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::EncodeH265SliceSegmentLongTermRefPics * pLongTermRefPics = {}; + uint8_t sps_video_parameter_set_id = {}; + uint8_t pps_seq_parameter_set_id = {}; + uint8_t pps_pic_parameter_set_id = {}; + uint8_t short_term_ref_pic_set_idx = {}; + int32_t PicOrderCntVal = {}; + uint8_t TemporalId = {}; + VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, 7> reserved1 = {}; + const VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::EncodeH265ReferenceListsInfo * pRefLists = {}; + const VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::H265ShortTermRefPicSet * pShortTermRefPicSet = {}; + const VULKAN_HPP_NAMESPACE::VULKAN_HPP_VIDEO_NAMESPACE::EncodeH265LongTermRefPics * pLongTermRefPics = {}; }; struct EncodeH265ReferenceInfoFlags diff --git a/thirdparty/vulkan/vk_enum_string_helper.h b/thirdparty/vulkan/vk_enum_string_helper.h index be968c091d..f0039db3f2 100644 --- a/thirdparty/vulkan/vk_enum_string_helper.h +++ b/thirdparty/vulkan/vk_enum_string_helper.h @@ -1,26 +1,11 @@ // *** THIS FILE IS GENERATED - DO NOT EDIT *** // See enum_string_helper_generator.py for modifications +// Copyright 2023 The Khronos Group Inc. +// Copyright 2023 Valve Corporation +// Copyright 2023 LunarG, Inc. +// +// SPDX-License-Identifier: Apache-2.0 -/*************************************************************************** -* -* Copyright (c) 2015-2023 The Khronos Group Inc. -* Copyright (c) 2015-2023 Valve Corporation -* Copyright (c) 2015-2023 LunarG, Inc. -* Copyright (c) 2015-2023 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -****************************************************************************/ -// NOLINTBEGIN #pragma once #include <string> #ifdef USE_VOLK @@ -29,24 +14,6 @@ #include <vulkan/vulkan.h> #endif -static inline bool IsDuplicatePnext(VkStructureType input_value) { - switch (input_value) { - case VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO: - case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT: - case VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT: - case VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT: - case VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT: - case VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT: - case VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT: - case VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT: - case VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT: - case VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT: - return true; - default: - return false; - } -} - static inline const char* string_VkResult(VkResult input_value) { switch (input_value) { case VK_SUCCESS: @@ -1645,6 +1612,10 @@ static inline const char* string_VkStructureType(VkStructureType input_value) { return "VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT: + return "VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT"; case VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT: @@ -1765,6 +1736,10 @@ static inline const char* string_VkStructureType(VkStructureType input_value) { return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM"; case VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM: return "VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT"; case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT: return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT: @@ -1811,6 +1786,12 @@ static inline const char* string_VkStructureType(VkStructureType input_value) { return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID"; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID: + return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR: @@ -1849,6 +1830,10 @@ static inline const char* string_VkStructureType(VkStructureType input_value) { return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT"; case VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT: @@ -1861,6 +1846,24 @@ static inline const char* string_VkStructureType(VkStructureType input_value) { return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV: + return "VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV"; + case VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV: + return "VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV"; + case VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV: + return "VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV"; + case VK_STRUCTURE_TYPE_GET_LATENCY_MARKER_INFO_NV: + return "VK_STRUCTURE_TYPE_GET_LATENCY_MARKER_INFO_NV"; + case VK_STRUCTURE_TYPE_LATENCY_TIMINGS_FRAME_REPORT_NV: + return "VK_STRUCTURE_TYPE_LATENCY_TIMINGS_FRAME_REPORT_NV"; + case VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV: + return "VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV"; + case VK_STRUCTURE_TYPE_OUT_OF_BAND_QUEUE_TYPE_INFO_NV: + return "VK_STRUCTURE_TYPE_OUT_OF_BAND_QUEUE_TYPE_INFO_NV"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV: + return "VK_STRUCTURE_TYPE_LATENCY_SURFACE_CAPABILITIES_NV"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR"; case VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR: @@ -1871,6 +1874,24 @@ static inline const char* string_VkStructureType(VkStructureType input_value) { return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM"; case VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM: return "VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM"; + case VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM: + return "VK_STRUCTURE_TYPE_SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM"; + case VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM: + return "VK_STRUCTURE_TYPE_SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM"; + case VK_STRUCTURE_TYPE_BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM: + return "VK_STRUCTURE_TYPE_BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM"; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM: + return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT"; case VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX: @@ -1883,6 +1904,10 @@ static inline const char* string_VkStructureType(VkStructureType input_value) { return "VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_QNX"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV"; default: return "Unhandled VkStructureType"; } @@ -3369,6 +3394,8 @@ static inline const char* string_VkSubpassContents(VkSubpassContents input_value return "VK_SUBPASS_CONTENTS_INLINE"; case VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS: return "VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS"; + case VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT: + return "VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT"; default: return "Unhandled VkSubpassContents"; } @@ -3491,6 +3518,8 @@ static inline const char* string_VkDriverId(VkDriverId input_value) { return "VK_DRIVER_ID_MESA_NVK"; case VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA: return "VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA"; + case VK_DRIVER_ID_MESA_AGXV: + return "VK_DRIVER_ID_MESA_AGXV"; default: return "Unhandled VkDriverId"; } @@ -3515,6 +3544,8 @@ static inline const char* string_VkSamplerReductionMode(VkSamplerReductionMode i return "VK_SAMPLER_REDUCTION_MODE_MIN"; case VK_SAMPLER_REDUCTION_MODE_MAX: return "VK_SAMPLER_REDUCTION_MODE_MAX"; + case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM: + return "VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM"; default: return "Unhandled VkSamplerReductionMode"; } @@ -3593,6 +3624,8 @@ static inline const char* string_VkQueryResultStatusKHR(VkQueryResultStatusKHR i return "VK_QUERY_RESULT_STATUS_NOT_READY_KHR"; case VK_QUERY_RESULT_STATUS_COMPLETE_KHR: return "VK_QUERY_RESULT_STATUS_COMPLETE_KHR"; + case VK_QUERY_RESULT_STATUS_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_KHR: + return "VK_QUERY_RESULT_STATUS_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_KHR"; default: return "Unhandled VkQueryResultStatusKHR"; } @@ -4623,6 +4656,80 @@ static inline const char* string_VkRayTracingInvocationReorderModeNV(VkRayTracin return "Unhandled VkRayTracingInvocationReorderModeNV"; } } +static inline const char* string_VkLatencyMarkerNV(VkLatencyMarkerNV input_value) { + switch (input_value) { + case VK_LATENCY_MARKER_SIMULATION_START_NV: + return "VK_LATENCY_MARKER_SIMULATION_START_NV"; + case VK_LATENCY_MARKER_SIMULATION_END_NV: + return "VK_LATENCY_MARKER_SIMULATION_END_NV"; + case VK_LATENCY_MARKER_RENDERSUBMIT_START_NV: + return "VK_LATENCY_MARKER_RENDERSUBMIT_START_NV"; + case VK_LATENCY_MARKER_RENDERSUBMIT_END_NV: + return "VK_LATENCY_MARKER_RENDERSUBMIT_END_NV"; + case VK_LATENCY_MARKER_PRESENT_START_NV: + return "VK_LATENCY_MARKER_PRESENT_START_NV"; + case VK_LATENCY_MARKER_PRESENT_END_NV: + return "VK_LATENCY_MARKER_PRESENT_END_NV"; + case VK_LATENCY_MARKER_INPUT_SAMPLE_NV: + return "VK_LATENCY_MARKER_INPUT_SAMPLE_NV"; + case VK_LATENCY_MARKER_TRIGGER_FLASH_NV: + return "VK_LATENCY_MARKER_TRIGGER_FLASH_NV"; + case VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_START_NV: + return "VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_START_NV"; + case VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_END_NV: + return "VK_LATENCY_MARKER_OUT_OF_BAND_RENDERSUBMIT_END_NV"; + case VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_START_NV: + return "VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_START_NV"; + case VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_END_NV: + return "VK_LATENCY_MARKER_OUT_OF_BAND_PRESENT_END_NV"; + default: + return "Unhandled VkLatencyMarkerNV"; + } +} +static inline const char* string_VkOutOfBandQueueTypeNV(VkOutOfBandQueueTypeNV input_value) { + switch (input_value) { + case VK_OUT_OF_BAND_QUEUE_TYPE_RENDER_NV: + return "VK_OUT_OF_BAND_QUEUE_TYPE_RENDER_NV"; + case VK_OUT_OF_BAND_QUEUE_TYPE_PRESENT_NV: + return "VK_OUT_OF_BAND_QUEUE_TYPE_PRESENT_NV"; + default: + return "Unhandled VkOutOfBandQueueTypeNV"; + } +} +static inline const char* string_VkBlockMatchWindowCompareModeQCOM(VkBlockMatchWindowCompareModeQCOM input_value) { + switch (input_value) { + case VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MIN_QCOM: + return "VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MIN_QCOM"; + case VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_QCOM: + return "VK_BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_QCOM"; + default: + return "Unhandled VkBlockMatchWindowCompareModeQCOM"; + } +} +static inline const char* string_VkCubicFilterWeightsQCOM(VkCubicFilterWeightsQCOM input_value) { + switch (input_value) { + case VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM: + return "VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM"; + case VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM: + return "VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM"; + case VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM: + return "VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM"; + case VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM: + return "VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM"; + default: + return "Unhandled VkCubicFilterWeightsQCOM"; + } +} +static inline const char* string_VkLayeredDriverUnderlyingApiMSFT(VkLayeredDriverUnderlyingApiMSFT input_value) { + switch (input_value) { + case VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT: + return "VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT"; + case VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT: + return "VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT"; + default: + return "Unhandled VkLayeredDriverUnderlyingApiMSFT"; + } +} static inline const char* string_VkBuildAccelerationStructureModeKHR(VkBuildAccelerationStructureModeKHR input_value) { switch (input_value) { case VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR: @@ -4713,6 +4820,7 @@ static inline const char* string_VkAccessFlagBits(VkAccessFlagBits input_value) } } +#ifdef __cplusplus static inline std::string string_VkAccessFlags(VkAccessFlags input_value) { std::string ret; int index = 0; @@ -4727,6 +4835,7 @@ static inline std::string string_VkAccessFlags(VkAccessFlags input_value) { if (ret.empty()) ret.append("VkAccessFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkImageAspectFlagBits(VkImageAspectFlagBits input_value) { switch (input_value) { case VK_IMAGE_ASPECT_COLOR_BIT: @@ -4758,6 +4867,7 @@ static inline const char* string_VkImageAspectFlagBits(VkImageAspectFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkImageAspectFlags(VkImageAspectFlags input_value) { std::string ret; int index = 0; @@ -4772,6 +4882,7 @@ static inline std::string string_VkImageAspectFlags(VkImageAspectFlags input_val if (ret.empty()) ret.append("VkImageAspectFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkFormatFeatureFlagBits(VkFormatFeatureFlagBits input_value) { switch (input_value) { case VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT: @@ -4845,6 +4956,7 @@ static inline const char* string_VkFormatFeatureFlagBits(VkFormatFeatureFlagBits } } +#ifdef __cplusplus static inline std::string string_VkFormatFeatureFlags(VkFormatFeatureFlags input_value) { std::string ret; int index = 0; @@ -4859,6 +4971,7 @@ static inline std::string string_VkFormatFeatureFlags(VkFormatFeatureFlags input if (ret.empty()) ret.append("VkFormatFeatureFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkImageCreateFlagBits(VkImageCreateFlagBits input_value) { switch (input_value) { case VK_IMAGE_CREATE_SPARSE_BINDING_BIT: @@ -4904,6 +5017,7 @@ static inline const char* string_VkImageCreateFlagBits(VkImageCreateFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkImageCreateFlags(VkImageCreateFlags input_value) { std::string ret; int index = 0; @@ -4918,6 +5032,7 @@ static inline std::string string_VkImageCreateFlags(VkImageCreateFlags input_val if (ret.empty()) ret.append("VkImageCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSampleCountFlagBits(VkSampleCountFlagBits input_value) { switch (input_value) { case VK_SAMPLE_COUNT_1_BIT: @@ -4939,6 +5054,7 @@ static inline const char* string_VkSampleCountFlagBits(VkSampleCountFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkSampleCountFlags(VkSampleCountFlags input_value) { std::string ret; int index = 0; @@ -4953,6 +5069,7 @@ static inline std::string string_VkSampleCountFlags(VkSampleCountFlags input_val if (ret.empty()) ret.append("VkSampleCountFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkImageUsageFlagBits(VkImageUsageFlagBits input_value) { switch (input_value) { case VK_IMAGE_USAGE_TRANSFER_SRC_BIT: @@ -5008,6 +5125,7 @@ static inline const char* string_VkImageUsageFlagBits(VkImageUsageFlagBits input } } +#ifdef __cplusplus static inline std::string string_VkImageUsageFlags(VkImageUsageFlags input_value) { std::string ret; int index = 0; @@ -5022,6 +5140,7 @@ static inline std::string string_VkImageUsageFlags(VkImageUsageFlags input_value if (ret.empty()) ret.append("VkImageUsageFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkInstanceCreateFlagBits(VkInstanceCreateFlagBits input_value) { switch (input_value) { case VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR: @@ -5031,6 +5150,7 @@ static inline const char* string_VkInstanceCreateFlagBits(VkInstanceCreateFlagBi } } +#ifdef __cplusplus static inline std::string string_VkInstanceCreateFlags(VkInstanceCreateFlags input_value) { std::string ret; int index = 0; @@ -5045,6 +5165,7 @@ static inline std::string string_VkInstanceCreateFlags(VkInstanceCreateFlags inp if (ret.empty()) ret.append("VkInstanceCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkMemoryHeapFlagBits(VkMemoryHeapFlagBits input_value) { switch (input_value) { case VK_MEMORY_HEAP_DEVICE_LOCAL_BIT: @@ -5056,6 +5177,7 @@ static inline const char* string_VkMemoryHeapFlagBits(VkMemoryHeapFlagBits input } } +#ifdef __cplusplus static inline std::string string_VkMemoryHeapFlags(VkMemoryHeapFlags input_value) { std::string ret; int index = 0; @@ -5070,6 +5192,7 @@ static inline std::string string_VkMemoryHeapFlags(VkMemoryHeapFlags input_value if (ret.empty()) ret.append("VkMemoryHeapFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkMemoryPropertyFlagBits(VkMemoryPropertyFlagBits input_value) { switch (input_value) { case VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT: @@ -5095,6 +5218,7 @@ static inline const char* string_VkMemoryPropertyFlagBits(VkMemoryPropertyFlagBi } } +#ifdef __cplusplus static inline std::string string_VkMemoryPropertyFlags(VkMemoryPropertyFlags input_value) { std::string ret; int index = 0; @@ -5109,6 +5233,7 @@ static inline std::string string_VkMemoryPropertyFlags(VkMemoryPropertyFlags inp if (ret.empty()) ret.append("VkMemoryPropertyFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkQueueFlagBits(VkQueueFlagBits input_value) { switch (input_value) { case VK_QUEUE_GRAPHICS_BIT: @@ -5134,6 +5259,7 @@ static inline const char* string_VkQueueFlagBits(VkQueueFlagBits input_value) { } } +#ifdef __cplusplus static inline std::string string_VkQueueFlags(VkQueueFlags input_value) { std::string ret; int index = 0; @@ -5148,6 +5274,7 @@ static inline std::string string_VkQueueFlags(VkQueueFlags input_value) { if (ret.empty()) ret.append("VkQueueFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDeviceQueueCreateFlagBits(VkDeviceQueueCreateFlagBits input_value) { switch (input_value) { case VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT: @@ -5157,6 +5284,7 @@ static inline const char* string_VkDeviceQueueCreateFlagBits(VkDeviceQueueCreate } } +#ifdef __cplusplus static inline std::string string_VkDeviceQueueCreateFlags(VkDeviceQueueCreateFlags input_value) { std::string ret; int index = 0; @@ -5171,6 +5299,7 @@ static inline std::string string_VkDeviceQueueCreateFlags(VkDeviceQueueCreateFla if (ret.empty()) ret.append("VkDeviceQueueCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineStageFlagBits(VkPipelineStageFlagBits input_value) { switch (input_value) { case VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: @@ -5232,6 +5361,7 @@ static inline const char* string_VkPipelineStageFlagBits(VkPipelineStageFlagBits } } +#ifdef __cplusplus static inline std::string string_VkPipelineStageFlags(VkPipelineStageFlags input_value) { std::string ret; int index = 0; @@ -5246,6 +5376,7 @@ static inline std::string string_VkPipelineStageFlags(VkPipelineStageFlags input if (ret.empty()) ret.append("VkPipelineStageFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSparseMemoryBindFlagBits(VkSparseMemoryBindFlagBits input_value) { switch (input_value) { case VK_SPARSE_MEMORY_BIND_METADATA_BIT: @@ -5255,6 +5386,7 @@ static inline const char* string_VkSparseMemoryBindFlagBits(VkSparseMemoryBindFl } } +#ifdef __cplusplus static inline std::string string_VkSparseMemoryBindFlags(VkSparseMemoryBindFlags input_value) { std::string ret; int index = 0; @@ -5269,6 +5401,7 @@ static inline std::string string_VkSparseMemoryBindFlags(VkSparseMemoryBindFlags if (ret.empty()) ret.append("VkSparseMemoryBindFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSparseImageFormatFlagBits(VkSparseImageFormatFlagBits input_value) { switch (input_value) { case VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT: @@ -5282,6 +5415,7 @@ static inline const char* string_VkSparseImageFormatFlagBits(VkSparseImageFormat } } +#ifdef __cplusplus static inline std::string string_VkSparseImageFormatFlags(VkSparseImageFormatFlags input_value) { std::string ret; int index = 0; @@ -5296,6 +5430,7 @@ static inline std::string string_VkSparseImageFormatFlags(VkSparseImageFormatFla if (ret.empty()) ret.append("VkSparseImageFormatFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkFenceCreateFlagBits(VkFenceCreateFlagBits input_value) { switch (input_value) { case VK_FENCE_CREATE_SIGNALED_BIT: @@ -5305,6 +5440,7 @@ static inline const char* string_VkFenceCreateFlagBits(VkFenceCreateFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkFenceCreateFlags(VkFenceCreateFlags input_value) { std::string ret; int index = 0; @@ -5319,6 +5455,7 @@ static inline std::string string_VkFenceCreateFlags(VkFenceCreateFlags input_val if (ret.empty()) ret.append("VkFenceCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkEventCreateFlagBits(VkEventCreateFlagBits input_value) { switch (input_value) { case VK_EVENT_CREATE_DEVICE_ONLY_BIT: @@ -5328,6 +5465,7 @@ static inline const char* string_VkEventCreateFlagBits(VkEventCreateFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkEventCreateFlags(VkEventCreateFlags input_value) { std::string ret; int index = 0; @@ -5342,6 +5480,7 @@ static inline std::string string_VkEventCreateFlags(VkEventCreateFlags input_val if (ret.empty()) ret.append("VkEventCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkQueryPipelineStatisticFlagBits(VkQueryPipelineStatisticFlagBits input_value) { switch (input_value) { case VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT: @@ -5377,6 +5516,7 @@ static inline const char* string_VkQueryPipelineStatisticFlagBits(VkQueryPipelin } } +#ifdef __cplusplus static inline std::string string_VkQueryPipelineStatisticFlags(VkQueryPipelineStatisticFlags input_value) { std::string ret; int index = 0; @@ -5391,6 +5531,7 @@ static inline std::string string_VkQueryPipelineStatisticFlags(VkQueryPipelineSt if (ret.empty()) ret.append("VkQueryPipelineStatisticFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkQueryResultFlagBits(VkQueryResultFlagBits input_value) { switch (input_value) { case VK_QUERY_RESULT_64_BIT: @@ -5408,6 +5549,7 @@ static inline const char* string_VkQueryResultFlagBits(VkQueryResultFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkQueryResultFlags(VkQueryResultFlags input_value) { std::string ret; int index = 0; @@ -5422,6 +5564,7 @@ static inline std::string string_VkQueryResultFlags(VkQueryResultFlags input_val if (ret.empty()) ret.append("VkQueryResultFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkBufferCreateFlagBits(VkBufferCreateFlagBits input_value) { switch (input_value) { case VK_BUFFER_CREATE_SPARSE_BINDING_BIT: @@ -5441,6 +5584,7 @@ static inline const char* string_VkBufferCreateFlagBits(VkBufferCreateFlagBits i } } +#ifdef __cplusplus static inline std::string string_VkBufferCreateFlags(VkBufferCreateFlags input_value) { std::string ret; int index = 0; @@ -5455,6 +5599,7 @@ static inline std::string string_VkBufferCreateFlags(VkBufferCreateFlags input_v if (ret.empty()) ret.append("VkBufferCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkBufferUsageFlagBits(VkBufferUsageFlagBits input_value) { switch (input_value) { case VK_BUFFER_USAGE_TRANSFER_SRC_BIT: @@ -5520,6 +5665,7 @@ static inline const char* string_VkBufferUsageFlagBits(VkBufferUsageFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkBufferUsageFlags(VkBufferUsageFlags input_value) { std::string ret; int index = 0; @@ -5534,6 +5680,7 @@ static inline std::string string_VkBufferUsageFlags(VkBufferUsageFlags input_val if (ret.empty()) ret.append("VkBufferUsageFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkImageViewCreateFlagBits(VkImageViewCreateFlagBits input_value) { switch (input_value) { case VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT: @@ -5547,6 +5694,7 @@ static inline const char* string_VkImageViewCreateFlagBits(VkImageViewCreateFlag } } +#ifdef __cplusplus static inline std::string string_VkImageViewCreateFlags(VkImageViewCreateFlags input_value) { std::string ret; int index = 0; @@ -5561,6 +5709,7 @@ static inline std::string string_VkImageViewCreateFlags(VkImageViewCreateFlags i if (ret.empty()) ret.append("VkImageViewCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineCacheCreateFlagBits(VkPipelineCacheCreateFlagBits input_value) { switch (input_value) { case VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT: @@ -5570,6 +5719,7 @@ static inline const char* string_VkPipelineCacheCreateFlagBits(VkPipelineCacheCr } } +#ifdef __cplusplus static inline std::string string_VkPipelineCacheCreateFlags(VkPipelineCacheCreateFlags input_value) { std::string ret; int index = 0; @@ -5584,6 +5734,7 @@ static inline std::string string_VkPipelineCacheCreateFlags(VkPipelineCacheCreat if (ret.empty()) ret.append("VkPipelineCacheCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkColorComponentFlagBits(VkColorComponentFlagBits input_value) { switch (input_value) { case VK_COLOR_COMPONENT_R_BIT: @@ -5599,6 +5750,7 @@ static inline const char* string_VkColorComponentFlagBits(VkColorComponentFlagBi } } +#ifdef __cplusplus static inline std::string string_VkColorComponentFlags(VkColorComponentFlags input_value) { std::string ret; int index = 0; @@ -5613,6 +5765,7 @@ static inline std::string string_VkColorComponentFlags(VkColorComponentFlags inp if (ret.empty()) ret.append("VkColorComponentFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineCreateFlagBits(VkPipelineCreateFlagBits input_value) { switch (input_value) { case VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT: @@ -5684,6 +5837,7 @@ static inline const char* string_VkPipelineCreateFlagBits(VkPipelineCreateFlagBi } } +#ifdef __cplusplus static inline std::string string_VkPipelineCreateFlags(VkPipelineCreateFlags input_value) { std::string ret; int index = 0; @@ -5698,6 +5852,7 @@ static inline std::string string_VkPipelineCreateFlags(VkPipelineCreateFlags inp if (ret.empty()) ret.append("VkPipelineCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineShaderStageCreateFlagBits(VkPipelineShaderStageCreateFlagBits input_value) { switch (input_value) { case VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT: @@ -5709,6 +5864,7 @@ static inline const char* string_VkPipelineShaderStageCreateFlagBits(VkPipelineS } } +#ifdef __cplusplus static inline std::string string_VkPipelineShaderStageCreateFlags(VkPipelineShaderStageCreateFlags input_value) { std::string ret; int index = 0; @@ -5723,6 +5879,7 @@ static inline std::string string_VkPipelineShaderStageCreateFlags(VkPipelineShad if (ret.empty()) ret.append("VkPipelineShaderStageCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkShaderStageFlagBits(VkShaderStageFlagBits input_value) { switch (input_value) { case VK_SHADER_STAGE_VERTEX_BIT: @@ -5762,6 +5919,7 @@ static inline const char* string_VkShaderStageFlagBits(VkShaderStageFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkShaderStageFlags(VkShaderStageFlags input_value) { if (input_value == VK_SHADER_STAGE_ALL_GRAPHICS) { return "VK_SHADER_STAGE_ALL_GRAPHICS"; } if (input_value == VK_SHADER_STAGE_ALL) { return "VK_SHADER_STAGE_ALL"; } @@ -5778,6 +5936,7 @@ static inline std::string string_VkShaderStageFlags(VkShaderStageFlags input_val if (ret.empty()) ret.append("VkShaderStageFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkCullModeFlagBits(VkCullModeFlagBits input_value) { switch (input_value) { case VK_CULL_MODE_NONE: @@ -5791,6 +5950,7 @@ static inline const char* string_VkCullModeFlagBits(VkCullModeFlagBits input_val } } +#ifdef __cplusplus static inline std::string string_VkCullModeFlags(VkCullModeFlags input_value) { if (input_value == VK_CULL_MODE_FRONT_AND_BACK) { return "VK_CULL_MODE_FRONT_AND_BACK"; } std::string ret; @@ -5806,6 +5966,7 @@ static inline std::string string_VkCullModeFlags(VkCullModeFlags input_value) { if (ret.empty()) ret.append("VkCullModeFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineDepthStencilStateCreateFlagBits(VkPipelineDepthStencilStateCreateFlagBits input_value) { switch (input_value) { case VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT: @@ -5817,6 +5978,7 @@ static inline const char* string_VkPipelineDepthStencilStateCreateFlagBits(VkPip } } +#ifdef __cplusplus static inline std::string string_VkPipelineDepthStencilStateCreateFlags(VkPipelineDepthStencilStateCreateFlags input_value) { std::string ret; int index = 0; @@ -5831,6 +5993,7 @@ static inline std::string string_VkPipelineDepthStencilStateCreateFlags(VkPipeli if (ret.empty()) ret.append("VkPipelineDepthStencilStateCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineColorBlendStateCreateFlagBits(VkPipelineColorBlendStateCreateFlagBits input_value) { switch (input_value) { case VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT: @@ -5840,6 +6003,7 @@ static inline const char* string_VkPipelineColorBlendStateCreateFlagBits(VkPipel } } +#ifdef __cplusplus static inline std::string string_VkPipelineColorBlendStateCreateFlags(VkPipelineColorBlendStateCreateFlags input_value) { std::string ret; int index = 0; @@ -5854,6 +6018,7 @@ static inline std::string string_VkPipelineColorBlendStateCreateFlags(VkPipeline if (ret.empty()) ret.append("VkPipelineColorBlendStateCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineLayoutCreateFlagBits(VkPipelineLayoutCreateFlagBits input_value) { switch (input_value) { case VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT: @@ -5863,6 +6028,7 @@ static inline const char* string_VkPipelineLayoutCreateFlagBits(VkPipelineLayout } } +#ifdef __cplusplus static inline std::string string_VkPipelineLayoutCreateFlags(VkPipelineLayoutCreateFlags input_value) { std::string ret; int index = 0; @@ -5877,6 +6043,7 @@ static inline std::string string_VkPipelineLayoutCreateFlags(VkPipelineLayoutCre if (ret.empty()) ret.append("VkPipelineLayoutCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSamplerCreateFlagBits(VkSamplerCreateFlagBits input_value) { switch (input_value) { case VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT: @@ -5894,6 +6061,7 @@ static inline const char* string_VkSamplerCreateFlagBits(VkSamplerCreateFlagBits } } +#ifdef __cplusplus static inline std::string string_VkSamplerCreateFlags(VkSamplerCreateFlags input_value) { std::string ret; int index = 0; @@ -5908,6 +6076,7 @@ static inline std::string string_VkSamplerCreateFlags(VkSamplerCreateFlags input if (ret.empty()) ret.append("VkSamplerCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDescriptorPoolCreateFlagBits(VkDescriptorPoolCreateFlagBits input_value) { switch (input_value) { case VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT: @@ -5916,11 +6085,16 @@ static inline const char* string_VkDescriptorPoolCreateFlagBits(VkDescriptorPool return "VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT"; case VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT: return "VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT"; + case VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV: + return "VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV"; + case VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV: + return "VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV"; default: return "Unhandled VkDescriptorPoolCreateFlagBits"; } } +#ifdef __cplusplus static inline std::string string_VkDescriptorPoolCreateFlags(VkDescriptorPoolCreateFlags input_value) { std::string ret; int index = 0; @@ -5935,6 +6109,7 @@ static inline std::string string_VkDescriptorPoolCreateFlags(VkDescriptorPoolCre if (ret.empty()) ret.append("VkDescriptorPoolCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDescriptorSetLayoutCreateFlagBits(VkDescriptorSetLayoutCreateFlagBits input_value) { switch (input_value) { case VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT: @@ -5954,6 +6129,7 @@ static inline const char* string_VkDescriptorSetLayoutCreateFlagBits(VkDescripto } } +#ifdef __cplusplus static inline std::string string_VkDescriptorSetLayoutCreateFlags(VkDescriptorSetLayoutCreateFlags input_value) { std::string ret; int index = 0; @@ -5968,6 +6144,7 @@ static inline std::string string_VkDescriptorSetLayoutCreateFlags(VkDescriptorSe if (ret.empty()) ret.append("VkDescriptorSetLayoutCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkAttachmentDescriptionFlagBits(VkAttachmentDescriptionFlagBits input_value) { switch (input_value) { case VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT: @@ -5977,6 +6154,7 @@ static inline const char* string_VkAttachmentDescriptionFlagBits(VkAttachmentDes } } +#ifdef __cplusplus static inline std::string string_VkAttachmentDescriptionFlags(VkAttachmentDescriptionFlags input_value) { std::string ret; int index = 0; @@ -5991,6 +6169,7 @@ static inline std::string string_VkAttachmentDescriptionFlags(VkAttachmentDescri if (ret.empty()) ret.append("VkAttachmentDescriptionFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDependencyFlagBits(VkDependencyFlagBits input_value) { switch (input_value) { case VK_DEPENDENCY_BY_REGION_BIT: @@ -6006,6 +6185,7 @@ static inline const char* string_VkDependencyFlagBits(VkDependencyFlagBits input } } +#ifdef __cplusplus static inline std::string string_VkDependencyFlags(VkDependencyFlags input_value) { std::string ret; int index = 0; @@ -6020,6 +6200,7 @@ static inline std::string string_VkDependencyFlags(VkDependencyFlags input_value if (ret.empty()) ret.append("VkDependencyFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkFramebufferCreateFlagBits(VkFramebufferCreateFlagBits input_value) { switch (input_value) { case VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT: @@ -6029,6 +6210,7 @@ static inline const char* string_VkFramebufferCreateFlagBits(VkFramebufferCreate } } +#ifdef __cplusplus static inline std::string string_VkFramebufferCreateFlags(VkFramebufferCreateFlags input_value) { std::string ret; int index = 0; @@ -6043,6 +6225,7 @@ static inline std::string string_VkFramebufferCreateFlags(VkFramebufferCreateFla if (ret.empty()) ret.append("VkFramebufferCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkRenderPassCreateFlagBits(VkRenderPassCreateFlagBits input_value) { switch (input_value) { case VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM: @@ -6052,6 +6235,7 @@ static inline const char* string_VkRenderPassCreateFlagBits(VkRenderPassCreateFl } } +#ifdef __cplusplus static inline std::string string_VkRenderPassCreateFlags(VkRenderPassCreateFlags input_value) { std::string ret; int index = 0; @@ -6066,6 +6250,7 @@ static inline std::string string_VkRenderPassCreateFlags(VkRenderPassCreateFlags if (ret.empty()) ret.append("VkRenderPassCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSubpassDescriptionFlagBits(VkSubpassDescriptionFlagBits input_value) { switch (input_value) { case VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX: @@ -6089,6 +6274,7 @@ static inline const char* string_VkSubpassDescriptionFlagBits(VkSubpassDescripti } } +#ifdef __cplusplus static inline std::string string_VkSubpassDescriptionFlags(VkSubpassDescriptionFlags input_value) { std::string ret; int index = 0; @@ -6103,6 +6289,7 @@ static inline std::string string_VkSubpassDescriptionFlags(VkSubpassDescriptionF if (ret.empty()) ret.append("VkSubpassDescriptionFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkCommandPoolCreateFlagBits(VkCommandPoolCreateFlagBits input_value) { switch (input_value) { case VK_COMMAND_POOL_CREATE_TRANSIENT_BIT: @@ -6116,6 +6303,7 @@ static inline const char* string_VkCommandPoolCreateFlagBits(VkCommandPoolCreate } } +#ifdef __cplusplus static inline std::string string_VkCommandPoolCreateFlags(VkCommandPoolCreateFlags input_value) { std::string ret; int index = 0; @@ -6130,6 +6318,7 @@ static inline std::string string_VkCommandPoolCreateFlags(VkCommandPoolCreateFla if (ret.empty()) ret.append("VkCommandPoolCreateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkCommandPoolResetFlagBits(VkCommandPoolResetFlagBits input_value) { switch (input_value) { case VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT: @@ -6139,6 +6328,7 @@ static inline const char* string_VkCommandPoolResetFlagBits(VkCommandPoolResetFl } } +#ifdef __cplusplus static inline std::string string_VkCommandPoolResetFlags(VkCommandPoolResetFlags input_value) { std::string ret; int index = 0; @@ -6153,6 +6343,7 @@ static inline std::string string_VkCommandPoolResetFlags(VkCommandPoolResetFlags if (ret.empty()) ret.append("VkCommandPoolResetFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkCommandBufferUsageFlagBits(VkCommandBufferUsageFlagBits input_value) { switch (input_value) { case VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT: @@ -6166,6 +6357,7 @@ static inline const char* string_VkCommandBufferUsageFlagBits(VkCommandBufferUsa } } +#ifdef __cplusplus static inline std::string string_VkCommandBufferUsageFlags(VkCommandBufferUsageFlags input_value) { std::string ret; int index = 0; @@ -6180,6 +6372,7 @@ static inline std::string string_VkCommandBufferUsageFlags(VkCommandBufferUsageF if (ret.empty()) ret.append("VkCommandBufferUsageFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkQueryControlFlagBits(VkQueryControlFlagBits input_value) { switch (input_value) { case VK_QUERY_CONTROL_PRECISE_BIT: @@ -6189,6 +6382,7 @@ static inline const char* string_VkQueryControlFlagBits(VkQueryControlFlagBits i } } +#ifdef __cplusplus static inline std::string string_VkQueryControlFlags(VkQueryControlFlags input_value) { std::string ret; int index = 0; @@ -6203,6 +6397,7 @@ static inline std::string string_VkQueryControlFlags(VkQueryControlFlags input_v if (ret.empty()) ret.append("VkQueryControlFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkCommandBufferResetFlagBits(VkCommandBufferResetFlagBits input_value) { switch (input_value) { case VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT: @@ -6212,6 +6407,7 @@ static inline const char* string_VkCommandBufferResetFlagBits(VkCommandBufferRes } } +#ifdef __cplusplus static inline std::string string_VkCommandBufferResetFlags(VkCommandBufferResetFlags input_value) { std::string ret; int index = 0; @@ -6226,6 +6422,7 @@ static inline std::string string_VkCommandBufferResetFlags(VkCommandBufferResetF if (ret.empty()) ret.append("VkCommandBufferResetFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkStencilFaceFlagBits(VkStencilFaceFlagBits input_value) { switch (input_value) { case VK_STENCIL_FACE_FRONT_BIT: @@ -6237,6 +6434,7 @@ static inline const char* string_VkStencilFaceFlagBits(VkStencilFaceFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkStencilFaceFlags(VkStencilFaceFlags input_value) { if (input_value == VK_STENCIL_FACE_FRONT_AND_BACK) { return "VK_STENCIL_FACE_FRONT_AND_BACK"; } std::string ret; @@ -6252,6 +6450,7 @@ static inline std::string string_VkStencilFaceFlags(VkStencilFaceFlags input_val if (ret.empty()) ret.append("VkStencilFaceFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSubgroupFeatureFlagBits(VkSubgroupFeatureFlagBits input_value) { switch (input_value) { case VK_SUBGROUP_FEATURE_BASIC_BIT: @@ -6277,6 +6476,7 @@ static inline const char* string_VkSubgroupFeatureFlagBits(VkSubgroupFeatureFlag } } +#ifdef __cplusplus static inline std::string string_VkSubgroupFeatureFlags(VkSubgroupFeatureFlags input_value) { std::string ret; int index = 0; @@ -6291,6 +6491,7 @@ static inline std::string string_VkSubgroupFeatureFlags(VkSubgroupFeatureFlags i if (ret.empty()) ret.append("VkSubgroupFeatureFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPeerMemoryFeatureFlagBits(VkPeerMemoryFeatureFlagBits input_value) { switch (input_value) { case VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT: @@ -6306,6 +6507,7 @@ static inline const char* string_VkPeerMemoryFeatureFlagBits(VkPeerMemoryFeature } } +#ifdef __cplusplus static inline std::string string_VkPeerMemoryFeatureFlags(VkPeerMemoryFeatureFlags input_value) { std::string ret; int index = 0; @@ -6320,6 +6522,7 @@ static inline std::string string_VkPeerMemoryFeatureFlags(VkPeerMemoryFeatureFla if (ret.empty()) ret.append("VkPeerMemoryFeatureFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkMemoryAllocateFlagBits(VkMemoryAllocateFlagBits input_value) { switch (input_value) { case VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT: @@ -6333,6 +6536,7 @@ static inline const char* string_VkMemoryAllocateFlagBits(VkMemoryAllocateFlagBi } } +#ifdef __cplusplus static inline std::string string_VkMemoryAllocateFlags(VkMemoryAllocateFlags input_value) { std::string ret; int index = 0; @@ -6347,6 +6551,7 @@ static inline std::string string_VkMemoryAllocateFlags(VkMemoryAllocateFlags inp if (ret.empty()) ret.append("VkMemoryAllocateFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkExternalMemoryHandleTypeFlagBits(VkExternalMemoryHandleTypeFlagBits input_value) { switch (input_value) { case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: @@ -6382,6 +6587,7 @@ static inline const char* string_VkExternalMemoryHandleTypeFlagBits(VkExternalMe } } +#ifdef __cplusplus static inline std::string string_VkExternalMemoryHandleTypeFlags(VkExternalMemoryHandleTypeFlags input_value) { std::string ret; int index = 0; @@ -6396,6 +6602,7 @@ static inline std::string string_VkExternalMemoryHandleTypeFlags(VkExternalMemor if (ret.empty()) ret.append("VkExternalMemoryHandleTypeFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkExternalMemoryFeatureFlagBits(VkExternalMemoryFeatureFlagBits input_value) { switch (input_value) { case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT: @@ -6409,6 +6616,7 @@ static inline const char* string_VkExternalMemoryFeatureFlagBits(VkExternalMemor } } +#ifdef __cplusplus static inline std::string string_VkExternalMemoryFeatureFlags(VkExternalMemoryFeatureFlags input_value) { std::string ret; int index = 0; @@ -6423,6 +6631,7 @@ static inline std::string string_VkExternalMemoryFeatureFlags(VkExternalMemoryFe if (ret.empty()) ret.append("VkExternalMemoryFeatureFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkExternalFenceHandleTypeFlagBits(VkExternalFenceHandleTypeFlagBits input_value) { switch (input_value) { case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT: @@ -6438,6 +6647,7 @@ static inline const char* string_VkExternalFenceHandleTypeFlagBits(VkExternalFen } } +#ifdef __cplusplus static inline std::string string_VkExternalFenceHandleTypeFlags(VkExternalFenceHandleTypeFlags input_value) { std::string ret; int index = 0; @@ -6452,6 +6662,7 @@ static inline std::string string_VkExternalFenceHandleTypeFlags(VkExternalFenceH if (ret.empty()) ret.append("VkExternalFenceHandleTypeFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkExternalFenceFeatureFlagBits(VkExternalFenceFeatureFlagBits input_value) { switch (input_value) { case VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT: @@ -6463,6 +6674,7 @@ static inline const char* string_VkExternalFenceFeatureFlagBits(VkExternalFenceF } } +#ifdef __cplusplus static inline std::string string_VkExternalFenceFeatureFlags(VkExternalFenceFeatureFlags input_value) { std::string ret; int index = 0; @@ -6477,6 +6689,7 @@ static inline std::string string_VkExternalFenceFeatureFlags(VkExternalFenceFeat if (ret.empty()) ret.append("VkExternalFenceFeatureFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkFenceImportFlagBits(VkFenceImportFlagBits input_value) { switch (input_value) { case VK_FENCE_IMPORT_TEMPORARY_BIT: @@ -6486,6 +6699,7 @@ static inline const char* string_VkFenceImportFlagBits(VkFenceImportFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkFenceImportFlags(VkFenceImportFlags input_value) { std::string ret; int index = 0; @@ -6500,6 +6714,7 @@ static inline std::string string_VkFenceImportFlags(VkFenceImportFlags input_val if (ret.empty()) ret.append("VkFenceImportFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSemaphoreImportFlagBits(VkSemaphoreImportFlagBits input_value) { switch (input_value) { case VK_SEMAPHORE_IMPORT_TEMPORARY_BIT: @@ -6509,6 +6724,7 @@ static inline const char* string_VkSemaphoreImportFlagBits(VkSemaphoreImportFlag } } +#ifdef __cplusplus static inline std::string string_VkSemaphoreImportFlags(VkSemaphoreImportFlags input_value) { std::string ret; int index = 0; @@ -6523,6 +6739,7 @@ static inline std::string string_VkSemaphoreImportFlags(VkSemaphoreImportFlags i if (ret.empty()) ret.append("VkSemaphoreImportFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkExternalSemaphoreHandleTypeFlagBits(VkExternalSemaphoreHandleTypeFlagBits input_value) { switch (input_value) { case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: @@ -6542,6 +6759,7 @@ static inline const char* string_VkExternalSemaphoreHandleTypeFlagBits(VkExterna } } +#ifdef __cplusplus static inline std::string string_VkExternalSemaphoreHandleTypeFlags(VkExternalSemaphoreHandleTypeFlags input_value) { std::string ret; int index = 0; @@ -6556,6 +6774,7 @@ static inline std::string string_VkExternalSemaphoreHandleTypeFlags(VkExternalSe if (ret.empty()) ret.append("VkExternalSemaphoreHandleTypeFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkExternalSemaphoreFeatureFlagBits(VkExternalSemaphoreFeatureFlagBits input_value) { switch (input_value) { case VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT: @@ -6567,6 +6786,7 @@ static inline const char* string_VkExternalSemaphoreFeatureFlagBits(VkExternalSe } } +#ifdef __cplusplus static inline std::string string_VkExternalSemaphoreFeatureFlags(VkExternalSemaphoreFeatureFlags input_value) { std::string ret; int index = 0; @@ -6581,6 +6801,7 @@ static inline std::string string_VkExternalSemaphoreFeatureFlags(VkExternalSemap if (ret.empty()) ret.append("VkExternalSemaphoreFeatureFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkResolveModeFlagBits(VkResolveModeFlagBits input_value) { switch (input_value) { case VK_RESOLVE_MODE_NONE: @@ -6593,11 +6814,14 @@ static inline const char* string_VkResolveModeFlagBits(VkResolveModeFlagBits inp return "VK_RESOLVE_MODE_MIN_BIT"; case VK_RESOLVE_MODE_MAX_BIT: return "VK_RESOLVE_MODE_MAX_BIT"; + case VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID: + return "VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID"; default: return "Unhandled VkResolveModeFlagBits"; } } +#ifdef __cplusplus static inline std::string string_VkResolveModeFlags(VkResolveModeFlags input_value) { std::string ret; int index = 0; @@ -6612,6 +6836,7 @@ static inline std::string string_VkResolveModeFlags(VkResolveModeFlags input_val if (ret.empty()) ret.append("VkResolveModeFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDescriptorBindingFlagBits(VkDescriptorBindingFlagBits input_value) { switch (input_value) { case VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT: @@ -6627,6 +6852,7 @@ static inline const char* string_VkDescriptorBindingFlagBits(VkDescriptorBinding } } +#ifdef __cplusplus static inline std::string string_VkDescriptorBindingFlags(VkDescriptorBindingFlags input_value) { std::string ret; int index = 0; @@ -6641,6 +6867,7 @@ static inline std::string string_VkDescriptorBindingFlags(VkDescriptorBindingFla if (ret.empty()) ret.append("VkDescriptorBindingFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSemaphoreWaitFlagBits(VkSemaphoreWaitFlagBits input_value) { switch (input_value) { case VK_SEMAPHORE_WAIT_ANY_BIT: @@ -6650,6 +6877,7 @@ static inline const char* string_VkSemaphoreWaitFlagBits(VkSemaphoreWaitFlagBits } } +#ifdef __cplusplus static inline std::string string_VkSemaphoreWaitFlags(VkSemaphoreWaitFlags input_value) { std::string ret; int index = 0; @@ -6664,6 +6892,7 @@ static inline std::string string_VkSemaphoreWaitFlags(VkSemaphoreWaitFlags input if (ret.empty()) ret.append("VkSemaphoreWaitFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineCreationFeedbackFlagBits(VkPipelineCreationFeedbackFlagBits input_value) { switch (input_value) { case VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT: @@ -6677,6 +6906,7 @@ static inline const char* string_VkPipelineCreationFeedbackFlagBits(VkPipelineCr } } +#ifdef __cplusplus static inline std::string string_VkPipelineCreationFeedbackFlags(VkPipelineCreationFeedbackFlags input_value) { std::string ret; int index = 0; @@ -6691,6 +6921,7 @@ static inline std::string string_VkPipelineCreationFeedbackFlags(VkPipelineCreat if (ret.empty()) ret.append("VkPipelineCreationFeedbackFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkToolPurposeFlagBits(VkToolPurposeFlagBits input_value) { switch (input_value) { case VK_TOOL_PURPOSE_VALIDATION_BIT: @@ -6712,6 +6943,7 @@ static inline const char* string_VkToolPurposeFlagBits(VkToolPurposeFlagBits inp } } +#ifdef __cplusplus static inline std::string string_VkToolPurposeFlags(VkToolPurposeFlags input_value) { std::string ret; int index = 0; @@ -6726,99 +6958,56 @@ static inline std::string string_VkToolPurposeFlags(VkToolPurposeFlags input_val if (ret.empty()) ret.append("VkToolPurposeFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPipelineStageFlagBits2(uint64_t input_value) { - switch (input_value) { - case VK_PIPELINE_STAGE_2_NONE: - return "VK_PIPELINE_STAGE_2_NONE"; - case VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT: - return "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT"; - case VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT: - return "VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT"; - case VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT: - return "VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT"; - case VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT: - return "VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT"; - case VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT: - return "VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT"; - case VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT: - return "VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT"; - case VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT: - return "VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT"; - case VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT: - return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT"; - case VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT: - return "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT"; - case VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT: - return "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT"; - case VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT: - return "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT"; - case VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT: - return "VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT"; - case VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT: - return "VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT"; - case VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT: - return "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT"; - case VK_PIPELINE_STAGE_2_HOST_BIT: - return "VK_PIPELINE_STAGE_2_HOST_BIT"; - case VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT: - return "VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT"; - case VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT: - return "VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT"; - case VK_PIPELINE_STAGE_2_COPY_BIT: - return "VK_PIPELINE_STAGE_2_COPY_BIT"; - case VK_PIPELINE_STAGE_2_RESOLVE_BIT: - return "VK_PIPELINE_STAGE_2_RESOLVE_BIT"; - case VK_PIPELINE_STAGE_2_BLIT_BIT: - return "VK_PIPELINE_STAGE_2_BLIT_BIT"; - case VK_PIPELINE_STAGE_2_CLEAR_BIT: - return "VK_PIPELINE_STAGE_2_CLEAR_BIT"; - case VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT: - return "VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT"; - case VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT: - return "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT"; - case VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT: - return "VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT"; - case VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR: - return "VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR"; + if (input_value == VK_PIPELINE_STAGE_2_NONE) return "VK_PIPELINE_STAGE_2_NONE"; + if (input_value == VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT) return "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT) return "VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT) return "VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT) return "VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT) return "VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT) return "VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT) return "VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT) return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT) return "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT) return "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT) return "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT) return "VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT) return "VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT) return "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_HOST_BIT) return "VK_PIPELINE_STAGE_2_HOST_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT) return "VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT) return "VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_COPY_BIT) return "VK_PIPELINE_STAGE_2_COPY_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_RESOLVE_BIT) return "VK_PIPELINE_STAGE_2_RESOLVE_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_BLIT_BIT) return "VK_PIPELINE_STAGE_2_BLIT_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_CLEAR_BIT) return "VK_PIPELINE_STAGE_2_CLEAR_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT) return "VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT) return "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT) return "VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT"; + if (input_value == VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR) return "VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR"; #ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR: - return "VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR"; + if (input_value == VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR) return "VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR"; #endif //VK_ENABLE_BETA_EXTENSIONS - case VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT: - return "VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT"; - case VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT: - return "VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT"; - case VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV: - return "VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV"; - case VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: - return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; - case VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: - return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"; - case VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR: - return "VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR"; - case VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT: - return "VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT"; - case VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT: - return "VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT"; - case VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT: - return "VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT"; - case VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI: - return "VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI"; - case VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI: - return "VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI"; - case VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR: - return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR"; - case VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT: - return "VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT"; - case VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI: - return "VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI"; - case VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV: - return "VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV"; - default: - return "Unhandled VkPipelineStageFlagBits2"; - } -} - + if (input_value == VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT) return "VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT"; + if (input_value == VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT) return "VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT"; + if (input_value == VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV) return "VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV"; + if (input_value == VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR) return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + if (input_value == VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR) return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"; + if (input_value == VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR) return "VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR"; + if (input_value == VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT) return "VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT"; + if (input_value == VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT) return "VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT"; + if (input_value == VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT) return "VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT"; + if (input_value == VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI) return "VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI"; + if (input_value == VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI) return "VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI"; + if (input_value == VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR) return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR"; + if (input_value == VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT) return "VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT"; + if (input_value == VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI) return "VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI"; + if (input_value == VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV) return "VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV"; + return "Unhandled VkPipelineStageFlagBits2"; +} + +#ifdef __cplusplus static inline std::string string_VkPipelineStageFlags2(VkPipelineStageFlags2 input_value) { std::string ret; int index = 0; @@ -6833,103 +7022,59 @@ static inline std::string string_VkPipelineStageFlags2(VkPipelineStageFlags2 inp if (ret.empty()) ret.append("VkPipelineStageFlags2(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkAccessFlagBits2(uint64_t input_value) { - switch (input_value) { - case VK_ACCESS_2_NONE: - return "VK_ACCESS_2_NONE"; - case VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT: - return "VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT"; - case VK_ACCESS_2_INDEX_READ_BIT: - return "VK_ACCESS_2_INDEX_READ_BIT"; - case VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT: - return "VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT"; - case VK_ACCESS_2_UNIFORM_READ_BIT: - return "VK_ACCESS_2_UNIFORM_READ_BIT"; - case VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT: - return "VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT"; - case VK_ACCESS_2_SHADER_READ_BIT: - return "VK_ACCESS_2_SHADER_READ_BIT"; - case VK_ACCESS_2_SHADER_WRITE_BIT: - return "VK_ACCESS_2_SHADER_WRITE_BIT"; - case VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT: - return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT"; - case VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT: - return "VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT"; - case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT: - return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT"; - case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: - return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"; - case VK_ACCESS_2_TRANSFER_READ_BIT: - return "VK_ACCESS_2_TRANSFER_READ_BIT"; - case VK_ACCESS_2_TRANSFER_WRITE_BIT: - return "VK_ACCESS_2_TRANSFER_WRITE_BIT"; - case VK_ACCESS_2_HOST_READ_BIT: - return "VK_ACCESS_2_HOST_READ_BIT"; - case VK_ACCESS_2_HOST_WRITE_BIT: - return "VK_ACCESS_2_HOST_WRITE_BIT"; - case VK_ACCESS_2_MEMORY_READ_BIT: - return "VK_ACCESS_2_MEMORY_READ_BIT"; - case VK_ACCESS_2_MEMORY_WRITE_BIT: - return "VK_ACCESS_2_MEMORY_WRITE_BIT"; - case VK_ACCESS_2_SHADER_SAMPLED_READ_BIT: - return "VK_ACCESS_2_SHADER_SAMPLED_READ_BIT"; - case VK_ACCESS_2_SHADER_STORAGE_READ_BIT: - return "VK_ACCESS_2_SHADER_STORAGE_READ_BIT"; - case VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT: - return "VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT"; - case VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR: - return "VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR"; - case VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR: - return "VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR"; + if (input_value == VK_ACCESS_2_NONE) return "VK_ACCESS_2_NONE"; + if (input_value == VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT) return "VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT"; + if (input_value == VK_ACCESS_2_INDEX_READ_BIT) return "VK_ACCESS_2_INDEX_READ_BIT"; + if (input_value == VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT) return "VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT"; + if (input_value == VK_ACCESS_2_UNIFORM_READ_BIT) return "VK_ACCESS_2_UNIFORM_READ_BIT"; + if (input_value == VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT) return "VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT"; + if (input_value == VK_ACCESS_2_SHADER_READ_BIT) return "VK_ACCESS_2_SHADER_READ_BIT"; + if (input_value == VK_ACCESS_2_SHADER_WRITE_BIT) return "VK_ACCESS_2_SHADER_WRITE_BIT"; + if (input_value == VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT) return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT"; + if (input_value == VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT) return "VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT"; + if (input_value == VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT) return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT"; + if (input_value == VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"; + if (input_value == VK_ACCESS_2_TRANSFER_READ_BIT) return "VK_ACCESS_2_TRANSFER_READ_BIT"; + if (input_value == VK_ACCESS_2_TRANSFER_WRITE_BIT) return "VK_ACCESS_2_TRANSFER_WRITE_BIT"; + if (input_value == VK_ACCESS_2_HOST_READ_BIT) return "VK_ACCESS_2_HOST_READ_BIT"; + if (input_value == VK_ACCESS_2_HOST_WRITE_BIT) return "VK_ACCESS_2_HOST_WRITE_BIT"; + if (input_value == VK_ACCESS_2_MEMORY_READ_BIT) return "VK_ACCESS_2_MEMORY_READ_BIT"; + if (input_value == VK_ACCESS_2_MEMORY_WRITE_BIT) return "VK_ACCESS_2_MEMORY_WRITE_BIT"; + if (input_value == VK_ACCESS_2_SHADER_SAMPLED_READ_BIT) return "VK_ACCESS_2_SHADER_SAMPLED_READ_BIT"; + if (input_value == VK_ACCESS_2_SHADER_STORAGE_READ_BIT) return "VK_ACCESS_2_SHADER_STORAGE_READ_BIT"; + if (input_value == VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT) return "VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT"; + if (input_value == VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR) return "VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR"; + if (input_value == VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR) return "VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR"; #ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR: - return "VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR"; + if (input_value == VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR) return "VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR"; #endif //VK_ENABLE_BETA_EXTENSIONS #ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR: - return "VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR"; + if (input_value == VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR) return "VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR"; #endif //VK_ENABLE_BETA_EXTENSIONS - case VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT: - return "VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"; - case VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT: - return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"; - case VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT: - return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT"; - case VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT: - return "VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT"; - case VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV: - return "VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV"; - case VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV: - return "VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV"; - case VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR: - return "VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"; - case VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR: - return "VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR"; - case VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: - return "VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"; - case VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT: - return "VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT"; - case VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: - return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT"; - case VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT: - return "VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT"; - case VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI: - return "VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI"; - case VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR: - return "VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR"; - case VK_ACCESS_2_MICROMAP_READ_BIT_EXT: - return "VK_ACCESS_2_MICROMAP_READ_BIT_EXT"; - case VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT: - return "VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT"; - case VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV: - return "VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV"; - case VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV: - return "VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV"; - default: - return "Unhandled VkAccessFlagBits2"; - } -} - + if (input_value == VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT) return "VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"; + if (input_value == VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT) return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"; + if (input_value == VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT) return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT"; + if (input_value == VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT) return "VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT"; + if (input_value == VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV) return "VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV"; + if (input_value == VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV) return "VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV"; + if (input_value == VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR) return "VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"; + if (input_value == VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR) return "VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR"; + if (input_value == VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) return "VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"; + if (input_value == VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT) return "VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT"; + if (input_value == VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT) return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT"; + if (input_value == VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT) return "VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT"; + if (input_value == VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI) return "VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI"; + if (input_value == VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR) return "VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR"; + if (input_value == VK_ACCESS_2_MICROMAP_READ_BIT_EXT) return "VK_ACCESS_2_MICROMAP_READ_BIT_EXT"; + if (input_value == VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT) return "VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT"; + if (input_value == VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV) return "VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV"; + if (input_value == VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV) return "VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV"; + return "Unhandled VkAccessFlagBits2"; +} + +#ifdef __cplusplus static inline std::string string_VkAccessFlags2(VkAccessFlags2 input_value) { std::string ret; int index = 0; @@ -6944,6 +7089,7 @@ static inline std::string string_VkAccessFlags2(VkAccessFlags2 input_value) { if (ret.empty()) ret.append("VkAccessFlags2(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSubmitFlagBits(VkSubmitFlagBits input_value) { switch (input_value) { case VK_SUBMIT_PROTECTED_BIT: @@ -6953,6 +7099,7 @@ static inline const char* string_VkSubmitFlagBits(VkSubmitFlagBits input_value) } } +#ifdef __cplusplus static inline std::string string_VkSubmitFlags(VkSubmitFlags input_value) { std::string ret; int index = 0; @@ -6967,6 +7114,7 @@ static inline std::string string_VkSubmitFlags(VkSubmitFlags input_value) { if (ret.empty()) ret.append("VkSubmitFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkRenderingFlagBits(VkRenderingFlagBits input_value) { switch (input_value) { case VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT: @@ -6975,6 +7123,8 @@ static inline const char* string_VkRenderingFlagBits(VkRenderingFlagBits input_v return "VK_RENDERING_SUSPENDING_BIT"; case VK_RENDERING_RESUMING_BIT: return "VK_RENDERING_RESUMING_BIT"; + case VK_RENDERING_CONTENTS_INLINE_BIT_EXT: + return "VK_RENDERING_CONTENTS_INLINE_BIT_EXT"; case VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT: return "VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT"; default: @@ -6982,6 +7132,7 @@ static inline const char* string_VkRenderingFlagBits(VkRenderingFlagBits input_v } } +#ifdef __cplusplus static inline std::string string_VkRenderingFlags(VkRenderingFlags input_value) { std::string ret; int index = 0; @@ -6996,103 +7147,59 @@ static inline std::string string_VkRenderingFlags(VkRenderingFlags input_value) if (ret.empty()) ret.append("VkRenderingFlags(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkFormatFeatureFlagBits2(uint64_t input_value) { - switch (input_value) { - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT"; - case VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT: - return "VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT"; - case VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT: - return "VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT"; - case VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT: - return "VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT"; - case VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT: - return "VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT"; - case VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT: - return "VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"; - case VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT: - return "VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT"; - case VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT: - return "VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT"; - case VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT: - return "VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT"; - case VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT: - return "VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT"; - case VK_FORMAT_FEATURE_2_BLIT_SRC_BIT: - return "VK_FORMAT_FEATURE_2_BLIT_SRC_BIT"; - case VK_FORMAT_FEATURE_2_BLIT_DST_BIT: - return "VK_FORMAT_FEATURE_2_BLIT_DST_BIT"; - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT"; - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT"; - case VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT: - return "VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT"; - case VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT: - return "VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT"; - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT"; - case VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT: - return "VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT"; - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT"; - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT"; - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT"; - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT"; - case VK_FORMAT_FEATURE_2_DISJOINT_BIT: - return "VK_FORMAT_FEATURE_2_DISJOINT_BIT"; - case VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT: - return "VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT"; - case VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT: - return "VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT"; - case VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT: - return "VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT"; - case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT: - return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT"; - case VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR: - return "VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR"; - case VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR: - return "VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR"; - case VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR: - return "VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR"; - case VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT: - return "VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT"; - case VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: - return "VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; - case VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT: - return "VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT) return "VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT) return "VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT) return "VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT) return "VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) return "VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT) return "VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT) return "VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT) return "VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT) return "VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_BLIT_SRC_BIT) return "VK_FORMAT_FEATURE_2_BLIT_SRC_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_BLIT_DST_BIT) return "VK_FORMAT_FEATURE_2_BLIT_DST_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT) return "VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT) return "VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT) return "VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_DISJOINT_BIT) return "VK_FORMAT_FEATURE_2_DISJOINT_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT) return "VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT) return "VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT) return "VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT) return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT"; + if (input_value == VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR) return "VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR"; + if (input_value == VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR) return "VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR"; + if (input_value == VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR) return "VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR"; + if (input_value == VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT) return "VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT"; + if (input_value == VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR) return "VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + if (input_value == VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) return "VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT"; #ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR: - return "VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR"; + if (input_value == VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR) return "VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR"; #endif //VK_ENABLE_BETA_EXTENSIONS #ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR: - return "VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR"; + if (input_value == VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR) return "VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR"; #endif //VK_ENABLE_BETA_EXTENSIONS - case VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV: - return "VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV"; - case VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM: - return "VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM"; - case VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM: - return "VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM"; - case VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM: - return "VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM"; - case VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM: - return "VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM"; - case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV: - return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV"; - case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV: - return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV"; - case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV: - return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV"; - default: - return "Unhandled VkFormatFeatureFlagBits2"; - } -} - + if (input_value == VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV) return "VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV"; + if (input_value == VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM) return "VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM"; + if (input_value == VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM) return "VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM"; + if (input_value == VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM) return "VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM"; + if (input_value == VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM) return "VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM"; + if (input_value == VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV) return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV"; + if (input_value == VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV) return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV"; + if (input_value == VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV) return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV"; + return "Unhandled VkFormatFeatureFlagBits2"; +} + +#ifdef __cplusplus static inline std::string string_VkFormatFeatureFlags2(VkFormatFeatureFlags2 input_value) { std::string ret; int index = 0; @@ -7107,6 +7214,7 @@ static inline std::string string_VkFormatFeatureFlags2(VkFormatFeatureFlags2 inp if (ret.empty()) ret.append("VkFormatFeatureFlags2(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSurfaceTransformFlagBitsKHR(VkSurfaceTransformFlagBitsKHR input_value) { switch (input_value) { case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: @@ -7132,6 +7240,7 @@ static inline const char* string_VkSurfaceTransformFlagBitsKHR(VkSurfaceTransfor } } +#ifdef __cplusplus static inline std::string string_VkSurfaceTransformFlagsKHR(VkSurfaceTransformFlagsKHR input_value) { std::string ret; int index = 0; @@ -7146,6 +7255,7 @@ static inline std::string string_VkSurfaceTransformFlagsKHR(VkSurfaceTransformFl if (ret.empty()) ret.append("VkSurfaceTransformFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkCompositeAlphaFlagBitsKHR(VkCompositeAlphaFlagBitsKHR input_value) { switch (input_value) { case VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR: @@ -7161,6 +7271,7 @@ static inline const char* string_VkCompositeAlphaFlagBitsKHR(VkCompositeAlphaFla } } +#ifdef __cplusplus static inline std::string string_VkCompositeAlphaFlagsKHR(VkCompositeAlphaFlagsKHR input_value) { std::string ret; int index = 0; @@ -7175,6 +7286,7 @@ static inline std::string string_VkCompositeAlphaFlagsKHR(VkCompositeAlphaFlagsK if (ret.empty()) ret.append("VkCompositeAlphaFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSwapchainCreateFlagBitsKHR(VkSwapchainCreateFlagBitsKHR input_value) { switch (input_value) { case VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR: @@ -7190,6 +7302,7 @@ static inline const char* string_VkSwapchainCreateFlagBitsKHR(VkSwapchainCreateF } } +#ifdef __cplusplus static inline std::string string_VkSwapchainCreateFlagsKHR(VkSwapchainCreateFlagsKHR input_value) { std::string ret; int index = 0; @@ -7204,6 +7317,7 @@ static inline std::string string_VkSwapchainCreateFlagsKHR(VkSwapchainCreateFlag if (ret.empty()) ret.append("VkSwapchainCreateFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDeviceGroupPresentModeFlagBitsKHR(VkDeviceGroupPresentModeFlagBitsKHR input_value) { switch (input_value) { case VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR: @@ -7219,6 +7333,7 @@ static inline const char* string_VkDeviceGroupPresentModeFlagBitsKHR(VkDeviceGro } } +#ifdef __cplusplus static inline std::string string_VkDeviceGroupPresentModeFlagsKHR(VkDeviceGroupPresentModeFlagsKHR input_value) { std::string ret; int index = 0; @@ -7233,6 +7348,7 @@ static inline std::string string_VkDeviceGroupPresentModeFlagsKHR(VkDeviceGroupP if (ret.empty()) ret.append("VkDeviceGroupPresentModeFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDisplayPlaneAlphaFlagBitsKHR(VkDisplayPlaneAlphaFlagBitsKHR input_value) { switch (input_value) { case VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR: @@ -7248,6 +7364,7 @@ static inline const char* string_VkDisplayPlaneAlphaFlagBitsKHR(VkDisplayPlaneAl } } +#ifdef __cplusplus static inline std::string string_VkDisplayPlaneAlphaFlagsKHR(VkDisplayPlaneAlphaFlagsKHR input_value) { std::string ret; int index = 0; @@ -7262,6 +7379,7 @@ static inline std::string string_VkDisplayPlaneAlphaFlagsKHR(VkDisplayPlaneAlpha if (ret.empty()) ret.append("VkDisplayPlaneAlphaFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoCodecOperationFlagBitsKHR(VkVideoCodecOperationFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_CODEC_OPERATION_NONE_KHR: @@ -7283,6 +7401,7 @@ static inline const char* string_VkVideoCodecOperationFlagBitsKHR(VkVideoCodecOp } } +#ifdef __cplusplus static inline std::string string_VkVideoCodecOperationFlagsKHR(VkVideoCodecOperationFlagsKHR input_value) { std::string ret; int index = 0; @@ -7297,6 +7416,7 @@ static inline std::string string_VkVideoCodecOperationFlagsKHR(VkVideoCodecOpera if (ret.empty()) ret.append("VkVideoCodecOperationFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoChromaSubsamplingFlagBitsKHR(VkVideoChromaSubsamplingFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR: @@ -7314,6 +7434,7 @@ static inline const char* string_VkVideoChromaSubsamplingFlagBitsKHR(VkVideoChro } } +#ifdef __cplusplus static inline std::string string_VkVideoChromaSubsamplingFlagsKHR(VkVideoChromaSubsamplingFlagsKHR input_value) { std::string ret; int index = 0; @@ -7328,6 +7449,7 @@ static inline std::string string_VkVideoChromaSubsamplingFlagsKHR(VkVideoChromaS if (ret.empty()) ret.append("VkVideoChromaSubsamplingFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoComponentBitDepthFlagBitsKHR(VkVideoComponentBitDepthFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR: @@ -7343,6 +7465,7 @@ static inline const char* string_VkVideoComponentBitDepthFlagBitsKHR(VkVideoComp } } +#ifdef __cplusplus static inline std::string string_VkVideoComponentBitDepthFlagsKHR(VkVideoComponentBitDepthFlagsKHR input_value) { std::string ret; int index = 0; @@ -7357,6 +7480,7 @@ static inline std::string string_VkVideoComponentBitDepthFlagsKHR(VkVideoCompone if (ret.empty()) ret.append("VkVideoComponentBitDepthFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoCapabilityFlagBitsKHR(VkVideoCapabilityFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR: @@ -7368,6 +7492,7 @@ static inline const char* string_VkVideoCapabilityFlagBitsKHR(VkVideoCapabilityF } } +#ifdef __cplusplus static inline std::string string_VkVideoCapabilityFlagsKHR(VkVideoCapabilityFlagsKHR input_value) { std::string ret; int index = 0; @@ -7382,6 +7507,7 @@ static inline std::string string_VkVideoCapabilityFlagsKHR(VkVideoCapabilityFlag if (ret.empty()) ret.append("VkVideoCapabilityFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoSessionCreateFlagBitsKHR(VkVideoSessionCreateFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR: @@ -7395,6 +7521,7 @@ static inline const char* string_VkVideoSessionCreateFlagBitsKHR(VkVideoSessionC } } +#ifdef __cplusplus static inline std::string string_VkVideoSessionCreateFlagsKHR(VkVideoSessionCreateFlagsKHR input_value) { std::string ret; int index = 0; @@ -7409,6 +7536,7 @@ static inline std::string string_VkVideoSessionCreateFlagsKHR(VkVideoSessionCrea if (ret.empty()) ret.append("VkVideoSessionCreateFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoCodingControlFlagBitsKHR(VkVideoCodingControlFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR: @@ -7426,6 +7554,7 @@ static inline const char* string_VkVideoCodingControlFlagBitsKHR(VkVideoCodingCo } } +#ifdef __cplusplus static inline std::string string_VkVideoCodingControlFlagsKHR(VkVideoCodingControlFlagsKHR input_value) { std::string ret; int index = 0; @@ -7440,6 +7569,7 @@ static inline std::string string_VkVideoCodingControlFlagsKHR(VkVideoCodingContr if (ret.empty()) ret.append("VkVideoCodingControlFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoDecodeCapabilityFlagBitsKHR(VkVideoDecodeCapabilityFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR: @@ -7451,6 +7581,7 @@ static inline const char* string_VkVideoDecodeCapabilityFlagBitsKHR(VkVideoDecod } } +#ifdef __cplusplus static inline std::string string_VkVideoDecodeCapabilityFlagsKHR(VkVideoDecodeCapabilityFlagsKHR input_value) { std::string ret; int index = 0; @@ -7465,6 +7596,7 @@ static inline std::string string_VkVideoDecodeCapabilityFlagsKHR(VkVideoDecodeCa if (ret.empty()) ret.append("VkVideoDecodeCapabilityFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoDecodeUsageFlagBitsKHR(VkVideoDecodeUsageFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_DECODE_USAGE_DEFAULT_KHR: @@ -7480,6 +7612,7 @@ static inline const char* string_VkVideoDecodeUsageFlagBitsKHR(VkVideoDecodeUsag } } +#ifdef __cplusplus static inline std::string string_VkVideoDecodeUsageFlagsKHR(VkVideoDecodeUsageFlagsKHR input_value) { std::string ret; int index = 0; @@ -7494,6 +7627,7 @@ static inline std::string string_VkVideoDecodeUsageFlagsKHR(VkVideoDecodeUsageFl if (ret.empty()) ret.append("VkVideoDecodeUsageFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkVideoDecodeH264PictureLayoutFlagBitsKHR(VkVideoDecodeH264PictureLayoutFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR: @@ -7507,6 +7641,7 @@ static inline const char* string_VkVideoDecodeH264PictureLayoutFlagBitsKHR(VkVid } } +#ifdef __cplusplus static inline std::string string_VkVideoDecodeH264PictureLayoutFlagsKHR(VkVideoDecodeH264PictureLayoutFlagsKHR input_value) { std::string ret; int index = 0; @@ -7521,6 +7656,7 @@ static inline std::string string_VkVideoDecodeH264PictureLayoutFlagsKHR(VkVideoD if (ret.empty()) ret.append("VkVideoDecodeH264PictureLayoutFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPerformanceCounterDescriptionFlagBitsKHR(VkPerformanceCounterDescriptionFlagBitsKHR input_value) { switch (input_value) { case VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR: @@ -7532,6 +7668,7 @@ static inline const char* string_VkPerformanceCounterDescriptionFlagBitsKHR(VkPe } } +#ifdef __cplusplus static inline std::string string_VkPerformanceCounterDescriptionFlagsKHR(VkPerformanceCounterDescriptionFlagsKHR input_value) { std::string ret; int index = 0; @@ -7546,16 +7683,20 @@ static inline std::string string_VkPerformanceCounterDescriptionFlagsKHR(VkPerfo if (ret.empty()) ret.append("VkPerformanceCounterDescriptionFlagsKHR(0)"); return ret; } +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeCapabilityFlagBitsKHR(VkVideoEncodeCapabilityFlagBitsKHR input_value) { switch (input_value) { case VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR: return "VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR"; + case VK_VIDEO_ENCODE_CAPABILITY_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_DETECTION_BIT_KHR: + return "VK_VIDEO_ENCODE_CAPABILITY_INSUFFICIENT_BITSTREAM_BUFFER_RANGE_DETECTION_BIT_KHR"; default: return "Unhandled VkVideoEncodeCapabilityFlagBitsKHR"; } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeCapabilityFlagsKHR(VkVideoEncodeCapabilityFlagsKHR input_value) { std::string ret; int index = 0; @@ -7571,6 +7712,7 @@ static inline std::string string_VkVideoEncodeCapabilityFlagsKHR(VkVideoEncodeCa return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeRateControlModeFlagBitsKHR(VkVideoEncodeRateControlModeFlagBitsKHR input_value) { switch (input_value) { @@ -7587,6 +7729,7 @@ static inline const char* string_VkVideoEncodeRateControlModeFlagBitsKHR(VkVideo } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeRateControlModeFlagsKHR(VkVideoEncodeRateControlModeFlagsKHR input_value) { std::string ret; int index = 0; @@ -7602,6 +7745,7 @@ static inline std::string string_VkVideoEncodeRateControlModeFlagsKHR(VkVideoEnc return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeFeedbackFlagBitsKHR(VkVideoEncodeFeedbackFlagBitsKHR input_value) { switch (input_value) { @@ -7616,6 +7760,7 @@ static inline const char* string_VkVideoEncodeFeedbackFlagBitsKHR(VkVideoEncodeF } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeFeedbackFlagsKHR(VkVideoEncodeFeedbackFlagsKHR input_value) { std::string ret; int index = 0; @@ -7631,6 +7776,7 @@ static inline std::string string_VkVideoEncodeFeedbackFlagsKHR(VkVideoEncodeFeed return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeUsageFlagBitsKHR(VkVideoEncodeUsageFlagBitsKHR input_value) { switch (input_value) { @@ -7649,6 +7795,7 @@ static inline const char* string_VkVideoEncodeUsageFlagBitsKHR(VkVideoEncodeUsag } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeUsageFlagsKHR(VkVideoEncodeUsageFlagsKHR input_value) { std::string ret; int index = 0; @@ -7664,6 +7811,7 @@ static inline std::string string_VkVideoEncodeUsageFlagsKHR(VkVideoEncodeUsageFl return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeContentFlagBitsKHR(VkVideoEncodeContentFlagBitsKHR input_value) { switch (input_value) { @@ -7680,6 +7828,7 @@ static inline const char* string_VkVideoEncodeContentFlagBitsKHR(VkVideoEncodeCo } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeContentFlagsKHR(VkVideoEncodeContentFlagsKHR input_value) { std::string ret; int index = 0; @@ -7695,75 +7844,43 @@ static inline std::string string_VkVideoEncodeContentFlagsKHR(VkVideoEncodeConte return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus static inline const char* string_VkPipelineCreateFlagBits2KHR(uint64_t input_value) { - switch (input_value) { - case VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR: - return "VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR"; - case VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT_KHR: - return "VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT_KHR"; - case VK_PIPELINE_CREATE_2_DERIVATIVE_BIT_KHR: - return "VK_PIPELINE_CREATE_2_DERIVATIVE_BIT_KHR"; - case VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR: - return "VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR"; - case VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT_KHR: - return "VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT_KHR"; - case VK_PIPELINE_CREATE_2_DEFER_COMPILE_BIT_NV: - return "VK_PIPELINE_CREATE_2_DEFER_COMPILE_BIT_NV"; - case VK_PIPELINE_CREATE_2_CAPTURE_STATISTICS_BIT_KHR: - return "VK_PIPELINE_CREATE_2_CAPTURE_STATISTICS_BIT_KHR"; - case VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR: - return "VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR"; - case VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR: - return "VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR"; - case VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR: - return "VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR"; - case VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT: - return "VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT"; - case VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT: - return "VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT"; - case VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR: - return "VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_AABBS_BIT_KHR: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_AABBS_BIT_KHR"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR"; - case VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_NV: - return "VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_NV"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_MOTION_BIT_NV: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_MOTION_BIT_NV"; - case VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: - return "VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; - case VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT: - return "VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT"; - case VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT: - return "VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT"; - case VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT: - return "VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT"; - case VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT_EXT: - return "VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT_EXT"; - case VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT: - return "VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT"; - case VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV: - return "VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV"; - case VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT: - return "VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT"; - default: - return "Unhandled VkPipelineCreateFlagBits2KHR"; - } -} - + if (input_value == VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR) return "VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT_KHR) return "VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_DERIVATIVE_BIT_KHR) return "VK_PIPELINE_CREATE_2_DERIVATIVE_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR) return "VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT_KHR) return "VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_DEFER_COMPILE_BIT_NV) return "VK_PIPELINE_CREATE_2_DEFER_COMPILE_BIT_NV"; + if (input_value == VK_PIPELINE_CREATE_2_CAPTURE_STATISTICS_BIT_KHR) return "VK_PIPELINE_CREATE_2_CAPTURE_STATISTICS_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR) return "VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR) return "VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR) return "VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT) return "VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT"; + if (input_value == VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT) return "VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT"; + if (input_value == VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR) return "VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) return "VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_AABBS_BIT_KHR) return "VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_AABBS_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR) return "VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR) return "VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR) return "VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR) return "VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR) return "VK_PIPELINE_CREATE_2_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_NV) return "VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_NV"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_MOTION_BIT_NV) return "VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_MOTION_BIT_NV"; + if (input_value == VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR) return "VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + if (input_value == VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT) return "VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT) return "VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT"; + if (input_value == VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT) return "VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT"; + if (input_value == VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT) return "VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT"; + if (input_value == VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT_EXT) return "VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT_EXT"; + if (input_value == VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT) return "VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT"; + if (input_value == VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV) return "VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV"; + if (input_value == VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT) return "VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT"; + return "Unhandled VkPipelineCreateFlagBits2KHR"; +} + +#ifdef __cplusplus static inline std::string string_VkPipelineCreateFlags2KHR(VkPipelineCreateFlags2KHR input_value) { std::string ret; int index = 0; @@ -7778,69 +7895,42 @@ static inline std::string string_VkPipelineCreateFlags2KHR(VkPipelineCreateFlags if (ret.empty()) ret.append("VkPipelineCreateFlags2KHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkBufferUsageFlagBits2KHR(uint64_t input_value) { - switch (input_value) { - case VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR: - return "VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR"; - case VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR: - return "VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR"; - case VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR: - return "VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR"; - case VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR: - return "VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR"; - case VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR: - return "VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR"; - case VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR: - return "VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR"; - case VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR: - return "VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR"; - case VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR: - return "VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR"; - case VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR: - return "VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR"; - case VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX: - return "VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX"; - case VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT: - return "VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT"; - case VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR: - return "VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR"; - case VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT: - return "VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT"; - case VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT: - return "VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT"; - case VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR: - return "VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR"; - case VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR: - return "VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR) return "VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR) return "VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR) return "VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR) return "VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR) return "VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR) return "VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR) return "VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR) return "VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR) return "VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX) return "VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX"; + if (input_value == VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT) return "VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT"; + if (input_value == VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR) return "VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT) return "VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT"; + if (input_value == VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT) return "VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT"; + if (input_value == VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR) return "VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR) return "VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR"; #ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR: - return "VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR) return "VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR"; #endif //VK_ENABLE_BETA_EXTENSIONS #ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR: - return "VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR) return "VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR"; #endif //VK_ENABLE_BETA_EXTENSIONS - case VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR: - return "VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR"; - case VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR: - return "VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR"; - case VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR: - return "VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR"; - case VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT: - return "VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT"; - case VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT: - return "VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT"; - case VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT: - return "VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT"; - case VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT: - return "VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT"; - case VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT: - return "VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT"; - default: - return "Unhandled VkBufferUsageFlagBits2KHR"; - } -} - + if (input_value == VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR) return "VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR) return "VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR) return "VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR"; + if (input_value == VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT) return "VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT"; + if (input_value == VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT) return "VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT"; + if (input_value == VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT) return "VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT"; + if (input_value == VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT) return "VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT"; + if (input_value == VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT) return "VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT"; + return "Unhandled VkBufferUsageFlagBits2KHR"; +} + +#ifdef __cplusplus static inline std::string string_VkBufferUsageFlags2KHR(VkBufferUsageFlags2KHR input_value) { std::string ret; int index = 0; @@ -7855,6 +7945,7 @@ static inline std::string string_VkBufferUsageFlags2KHR(VkBufferUsageFlags2KHR i if (ret.empty()) ret.append("VkBufferUsageFlags2KHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDebugReportFlagBitsEXT(VkDebugReportFlagBitsEXT input_value) { switch (input_value) { case VK_DEBUG_REPORT_INFORMATION_BIT_EXT: @@ -7872,6 +7963,7 @@ static inline const char* string_VkDebugReportFlagBitsEXT(VkDebugReportFlagBitsE } } +#ifdef __cplusplus static inline std::string string_VkDebugReportFlagsEXT(VkDebugReportFlagsEXT input_value) { std::string ret; int index = 0; @@ -7886,6 +7978,7 @@ static inline std::string string_VkDebugReportFlagsEXT(VkDebugReportFlagsEXT inp if (ret.empty()) ret.append("VkDebugReportFlagsEXT(0)"); return ret; } +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeH264CapabilityFlagBitsEXT(VkVideoEncodeH264CapabilityFlagBitsEXT input_value) { switch (input_value) { @@ -7912,6 +8005,7 @@ static inline const char* string_VkVideoEncodeH264CapabilityFlagBitsEXT(VkVideoE } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeH264CapabilityFlagsEXT(VkVideoEncodeH264CapabilityFlagsEXT input_value) { std::string ret; int index = 0; @@ -7927,6 +8021,7 @@ static inline std::string string_VkVideoEncodeH264CapabilityFlagsEXT(VkVideoEnco return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeH264StdFlagBitsEXT(VkVideoEncodeH264StdFlagBitsEXT input_value) { switch (input_value) { @@ -7966,11 +8061,16 @@ static inline const char* string_VkVideoEncodeH264StdFlagBitsEXT(VkVideoEncodeH2 return "VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_ENABLED_BIT_EXT"; case VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_EXT: return "VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_STD_SLICE_QP_DELTA_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_STD_SLICE_QP_DELTA_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT"; default: return "Unhandled VkVideoEncodeH264StdFlagBitsEXT"; } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeH264StdFlagsEXT(VkVideoEncodeH264StdFlagsEXT input_value) { std::string ret; int index = 0; @@ -7986,6 +8086,7 @@ static inline std::string string_VkVideoEncodeH264StdFlagsEXT(VkVideoEncodeH264S return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeH264RateControlFlagBitsEXT(VkVideoEncodeH264RateControlFlagBitsEXT input_value) { switch (input_value) { @@ -8004,6 +8105,7 @@ static inline const char* string_VkVideoEncodeH264RateControlFlagBitsEXT(VkVideo } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeH264RateControlFlagsEXT(VkVideoEncodeH264RateControlFlagsEXT input_value) { std::string ret; int index = 0; @@ -8019,6 +8121,7 @@ static inline std::string string_VkVideoEncodeH264RateControlFlagsEXT(VkVideoEnc return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeH265CapabilityFlagBitsEXT(VkVideoEncodeH265CapabilityFlagBitsEXT input_value) { switch (input_value) { @@ -8047,6 +8150,7 @@ static inline const char* string_VkVideoEncodeH265CapabilityFlagBitsEXT(VkVideoE } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeH265CapabilityFlagsEXT(VkVideoEncodeH265CapabilityFlagsEXT input_value) { std::string ret; int index = 0; @@ -8062,6 +8166,7 @@ static inline std::string string_VkVideoEncodeH265CapabilityFlagsEXT(VkVideoEnco return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeH265StdFlagBitsEXT(VkVideoEncodeH265StdFlagBitsEXT input_value) { switch (input_value) { @@ -8103,11 +8208,16 @@ static inline const char* string_VkVideoEncodeH265StdFlagBitsEXT(VkVideoEncodeH2 return "VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_EXT"; case VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_EXT: return "VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_EXT"; default: return "Unhandled VkVideoEncodeH265StdFlagBitsEXT"; } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeH265StdFlagsEXT(VkVideoEncodeH265StdFlagsEXT input_value) { std::string ret; int index = 0; @@ -8123,6 +8233,7 @@ static inline std::string string_VkVideoEncodeH265StdFlagsEXT(VkVideoEncodeH265S return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeH265CtbSizeFlagBitsEXT(VkVideoEncodeH265CtbSizeFlagBitsEXT input_value) { switch (input_value) { @@ -8137,6 +8248,7 @@ static inline const char* string_VkVideoEncodeH265CtbSizeFlagBitsEXT(VkVideoEnco } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeH265CtbSizeFlagsEXT(VkVideoEncodeH265CtbSizeFlagsEXT input_value) { std::string ret; int index = 0; @@ -8152,6 +8264,7 @@ static inline std::string string_VkVideoEncodeH265CtbSizeFlagsEXT(VkVideoEncodeH return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeH265TransformBlockSizeFlagBitsEXT(VkVideoEncodeH265TransformBlockSizeFlagBitsEXT input_value) { switch (input_value) { @@ -8168,6 +8281,7 @@ static inline const char* string_VkVideoEncodeH265TransformBlockSizeFlagBitsEXT( } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeH265TransformBlockSizeFlagsEXT(VkVideoEncodeH265TransformBlockSizeFlagsEXT input_value) { std::string ret; int index = 0; @@ -8183,6 +8297,7 @@ static inline std::string string_VkVideoEncodeH265TransformBlockSizeFlagsEXT(VkV return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus #ifdef VK_ENABLE_BETA_EXTENSIONS static inline const char* string_VkVideoEncodeH265RateControlFlagBitsEXT(VkVideoEncodeH265RateControlFlagBitsEXT input_value) { switch (input_value) { @@ -8201,6 +8316,7 @@ static inline const char* string_VkVideoEncodeH265RateControlFlagBitsEXT(VkVideo } } +#ifdef __cplusplus static inline std::string string_VkVideoEncodeH265RateControlFlagsEXT(VkVideoEncodeH265RateControlFlagsEXT input_value) { std::string ret; int index = 0; @@ -8216,6 +8332,7 @@ static inline std::string string_VkVideoEncodeH265RateControlFlagsEXT(VkVideoEnc return ret; } #endif //VK_ENABLE_BETA_EXTENSIONS +#endif // __cplusplus static inline const char* string_VkExternalMemoryHandleTypeFlagBitsNV(VkExternalMemoryHandleTypeFlagBitsNV input_value) { switch (input_value) { case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV: @@ -8231,6 +8348,7 @@ static inline const char* string_VkExternalMemoryHandleTypeFlagBitsNV(VkExternal } } +#ifdef __cplusplus static inline std::string string_VkExternalMemoryHandleTypeFlagsNV(VkExternalMemoryHandleTypeFlagsNV input_value) { std::string ret; int index = 0; @@ -8245,6 +8363,7 @@ static inline std::string string_VkExternalMemoryHandleTypeFlagsNV(VkExternalMem if (ret.empty()) ret.append("VkExternalMemoryHandleTypeFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkExternalMemoryFeatureFlagBitsNV(VkExternalMemoryFeatureFlagBitsNV input_value) { switch (input_value) { case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV: @@ -8258,6 +8377,7 @@ static inline const char* string_VkExternalMemoryFeatureFlagBitsNV(VkExternalMem } } +#ifdef __cplusplus static inline std::string string_VkExternalMemoryFeatureFlagsNV(VkExternalMemoryFeatureFlagsNV input_value) { std::string ret; int index = 0; @@ -8272,6 +8392,7 @@ static inline std::string string_VkExternalMemoryFeatureFlagsNV(VkExternalMemory if (ret.empty()) ret.append("VkExternalMemoryFeatureFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkConditionalRenderingFlagBitsEXT(VkConditionalRenderingFlagBitsEXT input_value) { switch (input_value) { case VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT: @@ -8281,6 +8402,7 @@ static inline const char* string_VkConditionalRenderingFlagBitsEXT(VkConditional } } +#ifdef __cplusplus static inline std::string string_VkConditionalRenderingFlagsEXT(VkConditionalRenderingFlagsEXT input_value) { std::string ret; int index = 0; @@ -8295,6 +8417,7 @@ static inline std::string string_VkConditionalRenderingFlagsEXT(VkConditionalRen if (ret.empty()) ret.append("VkConditionalRenderingFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkSurfaceCounterFlagBitsEXT(VkSurfaceCounterFlagBitsEXT input_value) { switch (input_value) { case VK_SURFACE_COUNTER_VBLANK_BIT_EXT: @@ -8304,6 +8427,7 @@ static inline const char* string_VkSurfaceCounterFlagBitsEXT(VkSurfaceCounterFla } } +#ifdef __cplusplus static inline std::string string_VkSurfaceCounterFlagsEXT(VkSurfaceCounterFlagsEXT input_value) { std::string ret; int index = 0; @@ -8318,6 +8442,7 @@ static inline std::string string_VkSurfaceCounterFlagsEXT(VkSurfaceCounterFlagsE if (ret.empty()) ret.append("VkSurfaceCounterFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDebugUtilsMessageSeverityFlagBitsEXT(VkDebugUtilsMessageSeverityFlagBitsEXT input_value) { switch (input_value) { case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: @@ -8333,6 +8458,7 @@ static inline const char* string_VkDebugUtilsMessageSeverityFlagBitsEXT(VkDebugU } } +#ifdef __cplusplus static inline std::string string_VkDebugUtilsMessageSeverityFlagsEXT(VkDebugUtilsMessageSeverityFlagsEXT input_value) { std::string ret; int index = 0; @@ -8347,6 +8473,7 @@ static inline std::string string_VkDebugUtilsMessageSeverityFlagsEXT(VkDebugUtil if (ret.empty()) ret.append("VkDebugUtilsMessageSeverityFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDebugUtilsMessageTypeFlagBitsEXT(VkDebugUtilsMessageTypeFlagBitsEXT input_value) { switch (input_value) { case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: @@ -8362,6 +8489,7 @@ static inline const char* string_VkDebugUtilsMessageTypeFlagBitsEXT(VkDebugUtils } } +#ifdef __cplusplus static inline std::string string_VkDebugUtilsMessageTypeFlagsEXT(VkDebugUtilsMessageTypeFlagsEXT input_value) { std::string ret; int index = 0; @@ -8376,6 +8504,7 @@ static inline std::string string_VkDebugUtilsMessageTypeFlagsEXT(VkDebugUtilsMes if (ret.empty()) ret.append("VkDebugUtilsMessageTypeFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkGeometryFlagBitsKHR(VkGeometryFlagBitsKHR input_value) { switch (input_value) { case VK_GEOMETRY_OPAQUE_BIT_KHR: @@ -8387,6 +8516,7 @@ static inline const char* string_VkGeometryFlagBitsKHR(VkGeometryFlagBitsKHR inp } } +#ifdef __cplusplus static inline std::string string_VkGeometryFlagsKHR(VkGeometryFlagsKHR input_value) { std::string ret; int index = 0; @@ -8401,6 +8531,7 @@ static inline std::string string_VkGeometryFlagsKHR(VkGeometryFlagsKHR input_val if (ret.empty()) ret.append("VkGeometryFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkGeometryInstanceFlagBitsKHR(VkGeometryInstanceFlagBitsKHR input_value) { switch (input_value) { case VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR: @@ -8420,6 +8551,7 @@ static inline const char* string_VkGeometryInstanceFlagBitsKHR(VkGeometryInstanc } } +#ifdef __cplusplus static inline std::string string_VkGeometryInstanceFlagsKHR(VkGeometryInstanceFlagsKHR input_value) { std::string ret; int index = 0; @@ -8434,6 +8566,7 @@ static inline std::string string_VkGeometryInstanceFlagsKHR(VkGeometryInstanceFl if (ret.empty()) ret.append("VkGeometryInstanceFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkBuildAccelerationStructureFlagBitsKHR(VkBuildAccelerationStructureFlagBitsKHR input_value) { switch (input_value) { case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR: @@ -8465,6 +8598,7 @@ static inline const char* string_VkBuildAccelerationStructureFlagBitsKHR(VkBuild } } +#ifdef __cplusplus static inline std::string string_VkBuildAccelerationStructureFlagsKHR(VkBuildAccelerationStructureFlagsKHR input_value) { std::string ret; int index = 0; @@ -8479,6 +8613,7 @@ static inline std::string string_VkBuildAccelerationStructureFlagsKHR(VkBuildAcc if (ret.empty()) ret.append("VkBuildAccelerationStructureFlagsKHR(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkHostImageCopyFlagBitsEXT(VkHostImageCopyFlagBitsEXT input_value) { switch (input_value) { case VK_HOST_IMAGE_COPY_MEMCPY_EXT: @@ -8488,6 +8623,7 @@ static inline const char* string_VkHostImageCopyFlagBitsEXT(VkHostImageCopyFlagB } } +#ifdef __cplusplus static inline std::string string_VkHostImageCopyFlagsEXT(VkHostImageCopyFlagsEXT input_value) { std::string ret; int index = 0; @@ -8502,6 +8638,7 @@ static inline std::string string_VkHostImageCopyFlagsEXT(VkHostImageCopyFlagsEXT if (ret.empty()) ret.append("VkHostImageCopyFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPresentScalingFlagBitsEXT(VkPresentScalingFlagBitsEXT input_value) { switch (input_value) { case VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT: @@ -8515,6 +8652,7 @@ static inline const char* string_VkPresentScalingFlagBitsEXT(VkPresentScalingFla } } +#ifdef __cplusplus static inline std::string string_VkPresentScalingFlagsEXT(VkPresentScalingFlagsEXT input_value) { std::string ret; int index = 0; @@ -8529,6 +8667,7 @@ static inline std::string string_VkPresentScalingFlagsEXT(VkPresentScalingFlagsE if (ret.empty()) ret.append("VkPresentScalingFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkPresentGravityFlagBitsEXT(VkPresentGravityFlagBitsEXT input_value) { switch (input_value) { case VK_PRESENT_GRAVITY_MIN_BIT_EXT: @@ -8542,6 +8681,7 @@ static inline const char* string_VkPresentGravityFlagBitsEXT(VkPresentGravityFla } } +#ifdef __cplusplus static inline std::string string_VkPresentGravityFlagsEXT(VkPresentGravityFlagsEXT input_value) { std::string ret; int index = 0; @@ -8556,6 +8696,7 @@ static inline std::string string_VkPresentGravityFlagsEXT(VkPresentGravityFlagsE if (ret.empty()) ret.append("VkPresentGravityFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkIndirectStateFlagBitsNV(VkIndirectStateFlagBitsNV input_value) { switch (input_value) { case VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV: @@ -8565,6 +8706,7 @@ static inline const char* string_VkIndirectStateFlagBitsNV(VkIndirectStateFlagBi } } +#ifdef __cplusplus static inline std::string string_VkIndirectStateFlagsNV(VkIndirectStateFlagsNV input_value) { std::string ret; int index = 0; @@ -8579,6 +8721,7 @@ static inline std::string string_VkIndirectStateFlagsNV(VkIndirectStateFlagsNV i if (ret.empty()) ret.append("VkIndirectStateFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkIndirectCommandsLayoutUsageFlagBitsNV(VkIndirectCommandsLayoutUsageFlagBitsNV input_value) { switch (input_value) { case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV: @@ -8592,6 +8735,7 @@ static inline const char* string_VkIndirectCommandsLayoutUsageFlagBitsNV(VkIndir } } +#ifdef __cplusplus static inline std::string string_VkIndirectCommandsLayoutUsageFlagsNV(VkIndirectCommandsLayoutUsageFlagsNV input_value) { std::string ret; int index = 0; @@ -8606,6 +8750,7 @@ static inline std::string string_VkIndirectCommandsLayoutUsageFlagsNV(VkIndirect if (ret.empty()) ret.append("VkIndirectCommandsLayoutUsageFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDeviceDiagnosticsConfigFlagBitsNV(VkDeviceDiagnosticsConfigFlagBitsNV input_value) { switch (input_value) { case VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV: @@ -8621,6 +8766,7 @@ static inline const char* string_VkDeviceDiagnosticsConfigFlagBitsNV(VkDeviceDia } } +#ifdef __cplusplus static inline std::string string_VkDeviceDiagnosticsConfigFlagsNV(VkDeviceDiagnosticsConfigFlagsNV input_value) { std::string ret; int index = 0; @@ -8635,6 +8781,7 @@ static inline std::string string_VkDeviceDiagnosticsConfigFlagsNV(VkDeviceDiagno if (ret.empty()) ret.append("VkDeviceDiagnosticsConfigFlagsNV(0)"); return ret; } +#endif // __cplusplus #ifdef VK_USE_PLATFORM_METAL_EXT static inline const char* string_VkExportMetalObjectTypeFlagBitsEXT(VkExportMetalObjectTypeFlagBitsEXT input_value) { switch (input_value) { @@ -8655,6 +8802,7 @@ static inline const char* string_VkExportMetalObjectTypeFlagBitsEXT(VkExportMeta } } +#ifdef __cplusplus static inline std::string string_VkExportMetalObjectTypeFlagsEXT(VkExportMetalObjectTypeFlagsEXT input_value) { std::string ret; int index = 0; @@ -8670,6 +8818,7 @@ static inline std::string string_VkExportMetalObjectTypeFlagsEXT(VkExportMetalOb return ret; } #endif //VK_USE_PLATFORM_METAL_EXT +#endif // __cplusplus static inline const char* string_VkGraphicsPipelineLibraryFlagBitsEXT(VkGraphicsPipelineLibraryFlagBitsEXT input_value) { switch (input_value) { case VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT: @@ -8685,6 +8834,7 @@ static inline const char* string_VkGraphicsPipelineLibraryFlagBitsEXT(VkGraphics } } +#ifdef __cplusplus static inline std::string string_VkGraphicsPipelineLibraryFlagsEXT(VkGraphicsPipelineLibraryFlagsEXT input_value) { std::string ret; int index = 0; @@ -8699,6 +8849,7 @@ static inline std::string string_VkGraphicsPipelineLibraryFlagsEXT(VkGraphicsPip if (ret.empty()) ret.append("VkGraphicsPipelineLibraryFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkImageCompressionFlagBitsEXT(VkImageCompressionFlagBitsEXT input_value) { switch (input_value) { case VK_IMAGE_COMPRESSION_DEFAULT_EXT: @@ -8714,6 +8865,7 @@ static inline const char* string_VkImageCompressionFlagBitsEXT(VkImageCompressio } } +#ifdef __cplusplus static inline std::string string_VkImageCompressionFlagsEXT(VkImageCompressionFlagsEXT input_value) { std::string ret; int index = 0; @@ -8728,6 +8880,7 @@ static inline std::string string_VkImageCompressionFlagsEXT(VkImageCompressionFl if (ret.empty()) ret.append("VkImageCompressionFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkImageCompressionFixedRateFlagBitsEXT(VkImageCompressionFixedRateFlagBitsEXT input_value) { switch (input_value) { case VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT: @@ -8785,6 +8938,7 @@ static inline const char* string_VkImageCompressionFixedRateFlagBitsEXT(VkImageC } } +#ifdef __cplusplus static inline std::string string_VkImageCompressionFixedRateFlagsEXT(VkImageCompressionFixedRateFlagsEXT input_value) { std::string ret; int index = 0; @@ -8799,6 +8953,7 @@ static inline std::string string_VkImageCompressionFixedRateFlagsEXT(VkImageComp if (ret.empty()) ret.append("VkImageCompressionFixedRateFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkDeviceAddressBindingFlagBitsEXT(VkDeviceAddressBindingFlagBitsEXT input_value) { switch (input_value) { case VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT: @@ -8808,6 +8963,7 @@ static inline const char* string_VkDeviceAddressBindingFlagBitsEXT(VkDeviceAddre } } +#ifdef __cplusplus static inline std::string string_VkDeviceAddressBindingFlagsEXT(VkDeviceAddressBindingFlagsEXT input_value) { std::string ret; int index = 0; @@ -8822,6 +8978,7 @@ static inline std::string string_VkDeviceAddressBindingFlagsEXT(VkDeviceAddressB if (ret.empty()) ret.append("VkDeviceAddressBindingFlagsEXT(0)"); return ret; } +#endif // __cplusplus #ifdef VK_USE_PLATFORM_FUCHSIA static inline const char* string_VkImageConstraintsInfoFlagBitsFUCHSIA(VkImageConstraintsInfoFlagBitsFUCHSIA input_value) { switch (input_value) { @@ -8840,6 +8997,7 @@ static inline const char* string_VkImageConstraintsInfoFlagBitsFUCHSIA(VkImageCo } } +#ifdef __cplusplus static inline std::string string_VkImageConstraintsInfoFlagsFUCHSIA(VkImageConstraintsInfoFlagsFUCHSIA input_value) { std::string ret; int index = 0; @@ -8855,6 +9013,32 @@ static inline std::string string_VkImageConstraintsInfoFlagsFUCHSIA(VkImageConst return ret; } #endif //VK_USE_PLATFORM_FUCHSIA +#endif // __cplusplus +static inline const char* string_VkFrameBoundaryFlagBitsEXT(VkFrameBoundaryFlagBitsEXT input_value) { + switch (input_value) { + case VK_FRAME_BOUNDARY_FRAME_END_BIT_EXT: + return "VK_FRAME_BOUNDARY_FRAME_END_BIT_EXT"; + default: + return "Unhandled VkFrameBoundaryFlagBitsEXT"; + } +} + +#ifdef __cplusplus +static inline std::string string_VkFrameBoundaryFlagsEXT(VkFrameBoundaryFlagsEXT input_value) { + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFrameBoundaryFlagBitsEXT(static_cast<VkFrameBoundaryFlagBitsEXT>(1U << index))); + } + ++index; + input_value >>= 1; + } + if (ret.empty()) ret.append("VkFrameBoundaryFlagsEXT(0)"); + return ret; +} +#endif // __cplusplus static inline const char* string_VkBuildMicromapFlagBitsEXT(VkBuildMicromapFlagBitsEXT input_value) { switch (input_value) { case VK_BUILD_MICROMAP_PREFER_FAST_TRACE_BIT_EXT: @@ -8868,6 +9052,7 @@ static inline const char* string_VkBuildMicromapFlagBitsEXT(VkBuildMicromapFlagB } } +#ifdef __cplusplus static inline std::string string_VkBuildMicromapFlagsEXT(VkBuildMicromapFlagsEXT input_value) { std::string ret; int index = 0; @@ -8882,6 +9067,7 @@ static inline std::string string_VkBuildMicromapFlagsEXT(VkBuildMicromapFlagsEXT if (ret.empty()) ret.append("VkBuildMicromapFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkMicromapCreateFlagBitsEXT(VkMicromapCreateFlagBitsEXT input_value) { switch (input_value) { case VK_MICROMAP_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT: @@ -8891,6 +9077,7 @@ static inline const char* string_VkMicromapCreateFlagBitsEXT(VkMicromapCreateFla } } +#ifdef __cplusplus static inline std::string string_VkMicromapCreateFlagsEXT(VkMicromapCreateFlagsEXT input_value) { std::string ret; int index = 0; @@ -8905,15 +9092,13 @@ static inline std::string string_VkMicromapCreateFlagsEXT(VkMicromapCreateFlagsE if (ret.empty()) ret.append("VkMicromapCreateFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkMemoryDecompressionMethodFlagBitsNV(uint64_t input_value) { - switch (input_value) { - case VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV: - return "VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV"; - default: - return "Unhandled VkMemoryDecompressionMethodFlagBitsNV"; - } + if (input_value == VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV) return "VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV"; + return "Unhandled VkMemoryDecompressionMethodFlagBitsNV"; } +#ifdef __cplusplus static inline std::string string_VkMemoryDecompressionMethodFlagsNV(VkMemoryDecompressionMethodFlagsNV input_value) { std::string ret; int index = 0; @@ -8928,6 +9113,7 @@ static inline std::string string_VkMemoryDecompressionMethodFlagsNV(VkMemoryDeco if (ret.empty()) ret.append("VkMemoryDecompressionMethodFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkOpticalFlowGridSizeFlagBitsNV(VkOpticalFlowGridSizeFlagBitsNV input_value) { switch (input_value) { case VK_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_NV: @@ -8945,6 +9131,7 @@ static inline const char* string_VkOpticalFlowGridSizeFlagBitsNV(VkOpticalFlowGr } } +#ifdef __cplusplus static inline std::string string_VkOpticalFlowGridSizeFlagsNV(VkOpticalFlowGridSizeFlagsNV input_value) { std::string ret; int index = 0; @@ -8959,6 +9146,7 @@ static inline std::string string_VkOpticalFlowGridSizeFlagsNV(VkOpticalFlowGridS if (ret.empty()) ret.append("VkOpticalFlowGridSizeFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkOpticalFlowUsageFlagBitsNV(VkOpticalFlowUsageFlagBitsNV input_value) { switch (input_value) { case VK_OPTICAL_FLOW_USAGE_UNKNOWN_NV: @@ -8978,6 +9166,7 @@ static inline const char* string_VkOpticalFlowUsageFlagBitsNV(VkOpticalFlowUsage } } +#ifdef __cplusplus static inline std::string string_VkOpticalFlowUsageFlagsNV(VkOpticalFlowUsageFlagsNV input_value) { std::string ret; int index = 0; @@ -8992,6 +9181,7 @@ static inline std::string string_VkOpticalFlowUsageFlagsNV(VkOpticalFlowUsageFla if (ret.empty()) ret.append("VkOpticalFlowUsageFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkOpticalFlowSessionCreateFlagBitsNV(VkOpticalFlowSessionCreateFlagBitsNV input_value) { switch (input_value) { case VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_HINT_BIT_NV: @@ -9009,6 +9199,7 @@ static inline const char* string_VkOpticalFlowSessionCreateFlagBitsNV(VkOpticalF } } +#ifdef __cplusplus static inline std::string string_VkOpticalFlowSessionCreateFlagsNV(VkOpticalFlowSessionCreateFlagsNV input_value) { std::string ret; int index = 0; @@ -9023,6 +9214,7 @@ static inline std::string string_VkOpticalFlowSessionCreateFlagsNV(VkOpticalFlow if (ret.empty()) ret.append("VkOpticalFlowSessionCreateFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkOpticalFlowExecuteFlagBitsNV(VkOpticalFlowExecuteFlagBitsNV input_value) { switch (input_value) { case VK_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_NV: @@ -9032,6 +9224,7 @@ static inline const char* string_VkOpticalFlowExecuteFlagBitsNV(VkOpticalFlowExe } } +#ifdef __cplusplus static inline std::string string_VkOpticalFlowExecuteFlagsNV(VkOpticalFlowExecuteFlagsNV input_value) { std::string ret; int index = 0; @@ -9046,6 +9239,7 @@ static inline std::string string_VkOpticalFlowExecuteFlagsNV(VkOpticalFlowExecut if (ret.empty()) ret.append("VkOpticalFlowExecuteFlagsNV(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkShaderCreateFlagBitsEXT(VkShaderCreateFlagBitsEXT input_value) { switch (input_value) { case VK_SHADER_CREATE_LINK_STAGE_BIT_EXT: @@ -9067,6 +9261,7 @@ static inline const char* string_VkShaderCreateFlagBitsEXT(VkShaderCreateFlagBit } } +#ifdef __cplusplus static inline std::string string_VkShaderCreateFlagsEXT(VkShaderCreateFlagsEXT input_value) { std::string ret; int index = 0; @@ -9081,6 +9276,7 @@ static inline std::string string_VkShaderCreateFlagsEXT(VkShaderCreateFlagsEXT i if (ret.empty()) ret.append("VkShaderCreateFlagsEXT(0)"); return ret; } +#endif // __cplusplus static inline const char* string_VkAccelerationStructureCreateFlagBitsKHR(VkAccelerationStructureCreateFlagBitsKHR input_value) { switch (input_value) { case VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR: @@ -9094,6 +9290,7 @@ static inline const char* string_VkAccelerationStructureCreateFlagBitsKHR(VkAcce } } +#ifdef __cplusplus static inline std::string string_VkAccelerationStructureCreateFlagsKHR(VkAccelerationStructureCreateFlagsKHR input_value) { std::string ret; int index = 0; @@ -9108,4 +9305,5 @@ static inline std::string string_VkAccelerationStructureCreateFlagsKHR(VkAcceler if (ret.empty()) ret.append("VkAccelerationStructureCreateFlagsKHR(0)"); return ret; } -// NOLINTEND +#endif // __cplusplus + |